JCM Scripting Code Syntax
The essence of the JCM scripting code is to make use of the same names system as used for translatable labels and documentation. It's not necessary to know the references of objects in the low-level java code. See the documentation page on names for more explanation.
The script is intepreted by the java code in jcm/tls/player. This operates in a separate thread, so it can work simultaneously with response to mouse-events.
The original text script is first split into items, dividing at each space, tab, or newline. Thus, everything, even opening and closing brackets, must be separated by such whitespace on both sides,. Multiple spaces are ignored, so the layout on the page is free.
Simple scripts, without loops or variables, can be written without understanding the remainder below. Just use a sequence of instructions:
object_name : value_to_set
Note that for future development of JCM, it is anticipated that the java "Beanshell" (www.beanshell.org) will probably be used to replace this scripting code system. Therefore you are not advised to invest time writing scripts using this code
Code sections and flow
Each section 'Sec' of the code ('scriptchunk' in @player) has:
a current location 'Loc' (the index of the last item processed),
a current value 'Val' (a string that can represent a number, some text, or a name of a variable or an object in JCM),
an instruction 'Next', and the previous one 'Prev'.
three flags, 'inquote', 'inbracket', 'skip'.
At the beginning of each step, Loc is incremented by one, and Next is then read from the item at Loc.
There is a simple recursive system for managing program flow.
The first Sec starts with Loc = -1, Val = null, inbracket true, other flags false.
After getting and intepreting Next, a Sec will continue to the next step while either inbracket or inquote is true, otherwise it has finished.
Each Instruction (as below) starts a new Sec for each of its parameters 'Par', 'Par2', etc., with Loc following from its parent. This starts with with Val null and all flags false. When it has finished, its Val is returned as the Par, and its parent's Loc follows from where it left off
Sub also starts a new Sec whose Loc is the first location of its Par, and returns to its parent's Loc when done.
Goto sets Loc to the first location of its Par, without starting a new Sec, and never comes back
Next is processed as follows:
If Next is a single quote ', inquote is set to true until the next single quote ' is reached.
If Next is an opening bracket '(', inbracket is set to true until the next closing bracket ')'
While inquote is true, Next is appended to Val.
While skip is true, Next is ignored.
Otherwise, Next is checked agaNextt the list of Functions (below).
If no instruction is found, set Val = the contents of Next, and record Prev=Next
Variable and Object Contents
Note: in the instructions listed below, Val refers to the string itself, whereas ValC refer to its contents. The same applies for parameters Par and ParC.
The 'contents' is one of the following (sought in this order):
If Val starts with $ it's a script variable (if not yet registered, a new one is created - they are all global in scope).
A JCM @iob with the name of Val , if one can be found (see @names)
Any other public field in JCM with the name of Val, sought using java reflection (see @ref)
Failing all the above, the string Val itself (possibly interpreted as a floating point number if appropriate)
Note: for a JCM object, "setting" its contents calls its doscript(Next) method (see @iob). For @param, that sets the value. In the case of menu parameters, 'next' and 'prev' can be used instead of menu items. For @blankplot there are special functions to set up a new graph. For most other objects, its state is written to debug output.
For a java field that is an array, its index can be appended using a dot
The same notation can be used for writing into arrays, but to make the model recalculate you also have to set the appropriate module changed=true, then add 'go'
For an example see emitdeclinescript
If the script causes a java exception, a message will be reported to debug output, but the script will keep going.
Instructions:
(value of Next What to do )
Setting values
: set Val= Prev and ValC = ParC
:+ :- :~ combination of : self +/-/~etc.
; set Val = null
_ set Val= Prev and set ValC = Par (use for setting to strings not contents)
var set Val = ParC (to make a variable name dynamically)
put set ParC = ValC
Branching
if set Val = ParC and if this is true, start another Sec, otherwise skip a Sec
else if Val is false start another Sec, otherwise skip a Sec
sub start a subroutine whose name is ParC
sub jump to name is ParC
Boolean
! set ValC = not ParC
< / > set ValC= ValC less than / greater than ParC
& / | set ValC = ValC AND / OR ParC
== / != set ValC = ValC equals / notequals ParC (works for both strings and numbers)
Mathematical
rnd set ValC = random number between 0 and 1
int set ValC = ParC rounded to an integer
exp or log set ValC = exponential or natural logaritm of ParC
+, -, /, asterix set ValC = ValC +, -, /, x ParC (using floating point arithmetic)
Note: the interpreter is very simple, so it doesn't know about arithmetic precedence, so always use brackets!
% set ValC = remainder after division by ParC
^ set ValC = ValC to power of ParC
Strings
~ set ValC = ValC +(append a string) ParC
Control
run run JCM main model loop (only necessary if scriptmode=delay, see @scriptparam)
end break out of script
Timing
w wait ParC milliseconds
p pause (duration specified by last w)
Text output
? write ValC to debug output (java console or a @notepad)
c write ParC to debug output
Showing webpages
swp show specified webpage (as below)
page set page to ParC
frame set browser frame to ParC
html set htmlinfo to ParC (a webpage may pick up this info using javascript)
jvs run ParC as javascript (from page containing main applet)
Demo:
show show popup info for iob with name of Val (duration as for pause)