The GENESIS Script Language Interpreter (SLI) provides a framework in which a simulation programmer can define and manipulate GENESIS elements. The SLI interprets statements in the GENESIS simulation language, and constitutes the operating system ``shell'' at work when you are running GENESIS.
The simulator shell is an interpretive operating environment which lets you:
You can perform these operations in either of two ways:
User-defined SLI scripts are used to glue the pieces of a simulation together. XODUS graphical objects that you use to define the front end of a simulation and GENESIS data handlers are all controlled from SLI scripts.
The shell contains a library of basic commands which you can augment through the addition of compiled C commands or interpreted SLI functions.
GENESIS routines are called by entering a routine name followed by any necessary arguments and options separated by whitespace.
routine-name arg1 arg2 ... -option1 option1-arg1 ... -option2 ...
A valid routine-name is a script identifier consisting of any combination of alphabetic (A-Z or a-z) or numeric (0-9) characters, or underscores (``_'') -- all other symbols are invalid characters in an identifier.
Routine arguments consist of literal strings of characters, results of other GENESIS routines or expressions, strings of characters including whitespace enclosed in double quotes and the value of parameters passed to a script or function. Combinations of these which appear together without any intervening whitespace are concatenated and passed as a single argument to the routine.
Routine options follow command arguments, and are introduced by a dash character. Option names may be abbreviated to any unambiguous length. Each option may accept additional arguments following the option name.
A carriage return marks the end of a statement, so you do not need to use semicolons at the end of a line. However, you can use semicolons to terminate statements as a way to include multiple statements on a single line. Several examples:
genesis > reset; step 100 genesis > int a, b, c ; a=1 ; b=2 ; c=3 genesis > if( a < b); echo {a} is less than {b}; end 1 is less than 2In other cases, the ``command'' returns a value and might more properly be called a function. In the documentation for GENESIS commands, we will use the term ``routine'' for built-in GENESIS commands, and will reserve the term ``function'' for a script function that is written in the GENESIS scripting language. The procedure for creating your own functions is described under Functions.
The following two examples illustrate how a routine call can be supplied as the argument to another routine or as a value in a script language expression:
genesis > echo { getfield /neutral_test x } genesis > float length = { getfield /cell/soma len }
Routines used in the context of an argument to another routine or within a script language expression must be enclosed in curly brackets.
All GENESIS statements are subject to these and other basic syntactical rules. If a statement you submit violates these rules, the interpreter will respond with an error message (and ignore your instruction).
In GENESIS, you create a variable by entering a variable ``type'' specifier at the command line, followed by the variable name (a script identifier), optionally followed by a value to assign to the variable:
variable-type variable-name [= expression]You can create any of three types of variables at the GENESIS shell:
Type | Meaning | Example Value |
int | integer number | 5, 18, 6000, -34 |
float | double precision floating-point number | 5.0, 3.14, -2001.4 |
str | character string | five, 5.0, hello |
genesis > int a genesis > float PI = 3.141593 genesis > float myfloat = 2*PI genesis > float floatstr = "6.3" genesis > str hi = "hello there"Note that case is significant for variable names (as in other areas): ``PI'' is different from ``Pi'', which is different from ``pi''. Also note that the character sequence ``6.3'' could be the value of either a floating point variable or a string variable.
Once you have defined a variable, you can change its value using an assignment statement:
variable-name = expressionFor example:
genesis > a = 40 genesis > myfloat = 100.5 genesis > hi = "The value of myfloat = " @ myfloat
Variables declared in a function are local to the function. Those declared outside of a function in a script (or script which is included with the ``include'' statement) are global variables. When a value is assigned to a global variable, it will affect any statements or functions which follow this assignment. One often refers to ``constants'' in a GENESIS script. These are not true constants, but are just variables which are not expected to take on new values during the course of a simulation.
Script variable values are retrieved by naming the variable in the context of an expression. In the description of GENESIS script language statements, expressions appear as indicated. In other contexts the value of an expression may be subtituted by enclosing the expression in curly brackets:
genesis > float pi = 3.1415 genesis > echo pi pi genesis > echo { pi } 3.1415
As with many languages, GENESIS will cast expressions involving both floating point and integer variables to floating point. It will also convert a string to a float if the string is a valid representation of a number. For example,
genesis > int i = 5 genesis > int j = 2 genesis > float x = 2 genesis > str num = "5" genesis > echo {i/j} 2 genesis > echo {i/x} 2.5 genesis > echo {num/2} 2.5 genesis > num = "i/x" genesis > echo {num} i/x genesis > echo {{num}/2} ** Error - CastToFloat: Error casting 'i/x', using 0.0 0
As with any programing language, GENESIS lets you define functions in order to make your script programs more modular and easier to modify. You should group function definitions together at the beginning of a script, preceding any statements that will use them. The listglobals routine will list any user-defined functions.
The general form of a function definition in GENESIS is:
function function-name [ (arg1 [, arg ... ] ) ] statement-1 . . . statement-n endFor example:
function print_area(length, diameter) float length, diameter float area float PI=3.14159 area = PI*diameter*length echo The area is {area} end function link_compartment(channel,compartment) addmsg {channel} {compartment} RAXIAL Ra previous_state addmsg {compartment} {channel} AXIAL previous_state end
The SLI also lets you define functions interactively at the GENESIS prompt. For example:
genesis > function my_echo(inputval) ? echo { inputval } ? end genesis > listglobals function my_echo genesis > my_echo 33 33
The return keyword allows a return from the function before the end statement. It may optionally be used to return a value. For example:
function make_positive(num) // a silly version of "abs" float num if (num >= 0) return {num} else return {abs {num}} end end
The keywords function, return, and end are features of the interpreter, not normal GENESIS commands; consequently, they do not appear in a listing of GENESIS routines (e.g., as given by the listcommands routine).
The routines argc and argv are often used inside of function definitions to return the number of arguments and the array of arguments which are passed to the function.
The table below lists the basic operators available in GENESIS, from highest to lowest precedence. These operators can be applied to variables or constants within a GENESIS expression.
Operators | Function |
- | unary minus |
** | power |
* / % ~ | multiply, divide, modulo (int only), bitwise complement |
+ - & | ˆ @ | add, subtract, bitwise and, bitwise or, |
bitwise xor, string concatenation | |
! | logical complement |
< <= > >= == != | relational operators (perform both numeric |
and string comparisons) | |
&& || | logical and, logical or |
The following examples illustrate the use of several of the basic operators.
For string concatenation, the ``@'' operator is used:
genesis > echo {"sub" @ "genius"} subgeniusThe following command shows how precedence is employed:
genesis > echo { 24 / 12 + 7 * 2 } 16You can also explicitly specify the precedence of operations in an expression by using parentheses:
genesis > echo { 3 * 4 + 5 } 17 genesis > echo { 3 * (4 + 5 ) } 27The following command does not return 5.4 because each element of the expression is an integer:
genesis > echo { 9 * 3 / 5 } 5For comparisons in GENESIS, the integer 0 is considered False; all other integer values are considered True; GENESIS returns 1 to indicate True. The following command returns 1 because the expression is True (it would have returned 0 if the expression had been False):
genesis > echo { 4 > 2 } 1Here is an example of negation in determining the nonexistence of an element:
if (!{exists {dest}/soma}) ...The relational operators are defined to be non-associative. This prevents silly expressions like the following:
1 < 2 < 4 [WRONG]
GENESIS supports four kinds of conditional control structures:
Note that you can break out of any of these loops before their expected termination by using the ``break'' or ``return'' statements.
The GENESIS ``if ...'' conditional structure takes the following form:
if (expression) statements elif (expression) statements else statements endThe elif and else portions of the form are optional and multiple elif portions may appear.
The ``if''/``elif'' expressions are evaluated in the order of appearance. When an expression evaluates ``true'', all the statements between the ``true'' expression and the following matching ``elif'', ``else'' or ``end'' will be executed; if all evaluated expressions are ``false'', then the statements between the ``else'' and the ``end'' are executed (or no statements are executed if there is no ``else'' clause).
Note that the GENESIS if construct does not recognize the keyword ``then''.
These are some examples of valid if statements:
if(1) echo hello end if(1); echo hello; end if( (GRAPHICS == 1) || (5+3 > 10) ) echo hello endThe following function uses the if/elif/else/end construct and prints ``zero'', ``negative'' or ``positive'' depending on the first argument:
function iftest(arg) int arg if ( arg == 0 ) echo zero elif ( arg < 0 ) echo negative else echo positive end end
The GENESIS ``while ...'' conditional looping statement has the following syntax:
while (expression) statements endThe expression is evaluated. If it is ``true'' (i.e., not 0), then all the statements will be executed, then the expression will be evaluated again; if the evaluated expression is ``false'', then all the statements are skipped and control is turned to the first statement after the ``end''.
An example of a while loop is the following:
str parent while(getfield {{parent} object->name} != "xgraph") parent = {el {parent}/..} endNote that the expression can be complicated and can involve some of the actual work of the loop.
The GENESIS ``for ...'' conditional structure uses an incrementable variable in assessing the condition for continuing through the loop. The syntax of the loop is as follows:
for (init_assignment; expression; incr_assignment) statements end
The init_assignment is an assignment statement which is evaluated once prior to entering the loop. The incr_assignment is an assignment statment which is executed following the statements each time through the loop. Otherwise, the for/end statement operates in the same manner as while/end.
To print the numbers one through ten:
int i for (i = 1; i <= 10; i = i + 1) echo {i} end
The GENESIS ``foreach'' statement loops through a set of statements once for each item in a specified argument list, having assigned the value of each item in the list to a looping variable for use by the statements:
foreach loop-var ( arg1 [ arg ...] ) statements endFor example:
str name foreach name ({el {path}/##[OBJECT=xform]}) xshow {name} endThe use of wildcards in the specification of pathnames is described in the section Hierarchical Structure. Again, you need to have declared the variables used in the loop before their use in the loop.