Simple-Script
Simple-Script is a simple expression language. A Simple-Script program consists
of a string with expressions embedded within it, enclosed in braces. The result of
evaluating a Simple-Script program is the same string, but with the expressions replaced
by their values (converted to strings). For example:
- Program:
- {a := 1 ; b := 2 }{a} plus {b} is {a+b}
- Result:
- 1 plus 2 is 3
Programs are evaluated within the context of an initial environment, which is a mapping
from variable names to data items.
Data
Data Types
Simple-Script data items have the following types:
- Number
- Numbers are 64 bit floating point numbers.
- String
- Strings are sequences of 0 or more unicode characters
- Vector
- Vectors are sequences of 0 or more Simple-Script data items. Note that vectors are
(currently) mutable, as in Java. For example {a:= 0,..4 ; b := a ; b[0] := 99 ; a[0] } is
99! This "feature" may disappear in future versions, so don't count on it.
- Trivial
- There is only one item of the Trivial type, it is called the trivial object.
Conversions
Numbers can convert to strings. Vectors convert to strings by catenation of the
(conversions of) their elements. The trivial object converts to the empty string.
Since there is no Boolean type, the Number type doubles as a Boolean type. Any value
sufficiently close to zero (the fuzz factor is 1 millionth in the current implementation)
is considered false. All other values are true.
Since there is no integer type, the Number type triples as an integer type. Where
integers are needed, a double can be converted using the formula floor(x+FUZZ), where FUZZ
is about 1 millionth.
White-space
Within braces, C and C++ style comments are treated as white-space, as are blanks,
tabs, and newlines. Note that either kind of comment can include } characters, which,
since they are commented, do not terminate the expression.
White-space serves only to separate tokens.
Expressions
The various kinds of expressions are discussed in the following sections in order of
precedence, from highest to lowest, except has noted.
In the following, E, F, and G are Simple-Script expressions.
Literals
Numeric literals are sequences of 1 or more decimal digits with an optional decimal
point.
String literals are enclosed in double quotes. The following escape sequences are
possible:
\n |
ASCII char 10 |
\t |
ASCII char 9 |
\" |
Double quote |
\\ |
Backslash |
\uwxyz |
Unicode character. w, x, y, and z must
be digits or letters from a to f. wxyz is interpreted as a hexadecimal number
specifying the unicode position of the character. |
Variables
Variables are written as a sequence of one or more letters, digits, and underscores,
starting with a letter and ending with a letter or digit; furthermore all keywords are
reserved and can not be used as variables. Variable's names are case sensitive.
Variables need not (indeed can not) be declared.
A variable used as an expression must have been assigned to a value within the current
environment.
Control constructs
- (E)
- Parentheses are used to override or emphasize the default grouping.
- if E0 then F1 elseif E1 then F2 elseif E2 then F2 else G end
- If expressions provide conditional evaluation. As many elseif clauses as desired may be
used. The else clause is optional. The semantics are probably what you would expect:
expressions Ei are evaluated in sequence until one is found that evaluates to true, then
the corresponding Fi is evaluated and its result is the if's result; if no Ei is true,
then the result is G, or, in the absence of an else clause, the trivial object..
- while E do F end
- Again the semantics are probably what you would expect: E and then F are evaluated
repeatedly until E evaluates to false. The result is the trivial object.
- for v in E do F end
- E must evaluate to a vector. F is evaluated once for each item in E, with variable v
assigned that item. The result is a vector of results of F. For example a sum of squares
of vector A can be calculated by:
sum for a in A do a*a end
Subscript
- E[F]
- E must evaluate to a vector and F to a number. The result is item F (considered as an
integer, and counting from 0) of E.
Unary Arithmetic operations
All unary arithmetic operations have the same precedence.
- sum E
- E must evaluate to a vector of numbers. The result is the sum of the numbers in the
vector.
- count E
- E must evaluate to a vector of numbers. The result is the number of numbers in the
vector that are not zero.
- average E
- E must evaluate to a vector of numbers. The result is the average. If the vector is of
length 0, the average is 0.0.
- # E
- E must evaluate to a vector. The result is the length of the vector.
- - E
- E must evaluate to a number. The result is the negation of the number.
Binary Operators
Operands are evaluated from left to right. Both operands are evaluated. associativity
is left.
- E*F and E/F
- E and F must evaluate to numbers. A zero divided by zero is 0.0. Otherwise dividing by a
zero is not allowed.
- E+F and E-F
- E and F must evaluate to numbers.
- E++F
- The result is the catenation of E and F, converted to strings.
- E,..F
- E and F must evaluate to numbers. The result is a vector of integers starting with E
(converted to an integer) and going up to but not including F (converted to an
integer).
Relational operators
Relations are neither left nor right associative, but are chaining, meaning, for
example that a _< b < c is true only if both a is less than or equal to b and b is
less than c. Operands are evaluated, from left to right, only until a chain of relations
is shown to be false. All relational operators share the same precedence.
Comparison of numbers obeys tricotomy: one of E<F, E=F, or E>F will be true,
usually the one you expect. Numbers are considered equal if they are within a fuzz factor
of each other. The fuzz factor is about 1 in a million. Equality is, thus, not transitive!
- E=F and E~=F
- Equal and not-equal. Numbers can be compared to numbers, strings to strings, vectors to
vectors (recursively). No conversions are made. The result is 0 (false) or 1 (true).
- E<F, E_<F, E>F, E>_F
- Less than, less or equal, greater than, and greater or equal. E and F must evaluate to
numbers. The result is 0 (false) or 1 (true).
Logical operators
- ~E
- Same as if E then 0 else 1 end
- E /\ F
- Same as if E then F else 0 end
- E \/ F
- Same as if E then 1 else F end
- E => F
- Same as if E then F else 1 end
Assignment
- id := F or id[E0] := F or id[E0][E1] := F etc.
- Assignment to a variable that does not exist creates the variable -- so watch your
spelling! Assignment to an existing vector can extend the length of the vector by up to
one place. Assignment to a new vector must be to item 0. For examples: a[0][0] := 1.0 is
ok, unless a has a value that is not a vector or a[0] has a value that is not a vector.
a[1][0] := 1.0 is ok only if a has a value that is a vector of length 1 or more and a[1]
either didn't previously exist, or was a vector. a[0][1] := 1.0 is ok only if a has a
value that is a vector of at least length 1 and a[0] is a vector of at least length 1. F
is evaluated first, then E0, then E1, etc. The result of an assignment is the trivial
object.
Sequential composition
- E F or E;F
- E is evaluated, then F. The result is the result of F. The semicolon is required when F
starts with a minus sign (-).