Expressions

= Ordinary Expressions = Context Free allows expressions to be used anywhere that the compiler accepts a number, except for rule/path weights.

The following components are allowed in an expression:
 * constants
 * simple numeric constants (e.g., 12.45)
 * &infin;
 * percentages (e.g., 9.6%)
 * functions
 * vector[index] : vector access
 * (expression) : parentheses
 * ^ : exponentiation
 * - : negation
 * * / : multiplication and division
 * + - -- : addition, subtraction, and proper subtraction
 * .. &hellip; +- &plusmn; : random number operators
 * x .. y or x &hellip; y is equivalent to rand(x, y)
 * x +- y or x &plusmn; y is equivalent to rand(x-y, x+y)
 * &lt; &gt; &lt;= &le; &gt;= &ge; == <> &ne; : comparison
 * && || ^^ : boolean and, or, and exclusive-or
 * , : vector creating, binds several numeric expressions to form a vector

Standard rules of operator ordering and precedence are supported; i.e., 2 + 3 * 4 is equivalent to 2 + (3 * 4).

Functions
Trigonometry functions:
 * cos(x) - cosine of x in degrees
 * sin(x) - sine of x in degrees
 * tan(x) - tangent of x in degrees
 * acos(x) - arc-cosine of x, returned in degrees
 * asin(x) - arc-sine of x, returned in degrees
 * atan(x) - arc-tangent of x, returned in degrees
 * atan2(y, x) - arc-tangent of y/x, returned in degrees

Hyperbolic functions:
 * cosh(x) - hyperbolic cosine of x
 * sinh(x) - hyperbolic sine of x
 * tanh(x) - hyperbolic tangent of x
 * acosh(x) - hyperbolic arc-cosine of x
 * asinh(x) - hyperbolic arc-sine of x
 * atanh(x) - hyperbolic arc-tangent of x

General math functions:
 * log(x) - natural logarithm of x
 * log10(x) - decimal logarithm of x
 * exp(x) - ex
 * sqrt(x) - square root of x
 * abs(x) - absolute value of x
 * mod(x, y) - x modulo y

Integer functions:
 * floor(x) - rounds x to the next lower integer
 * factorial(x) - x!
 * sg(x) - returns 0 if x=0 or 1 if x&ne;0
 * isNatural(x) - returns true if x is a legal natural number, and integer in the interval [0,CF::MaxNatural]
 * div(x, y) - x&divide;y in the integer domain
 * divides(x, y) - return 1 if y divides x or 0 if y does not divide x

Binary functions:
 * bitnot(x) - binary inverse of x
 * bitor(x, y) - binary OR of x and y
 * bitand(x, y) - binary AND of x and y
 * bitxor(x, y) - binary exclusive-OR of x and y
 * bitleft(x, y) - binary left shift of x by y bits
 * bitright(x, y) - binary right shift of x by y bits

The binary functions convert their operands to 52-bit, unsigned binary numbers before performing the binary operation. Results are masked by 0xfffffffffffff.

Miscellaneous functions:
 * infinity - &infin;
 * infinity(x) - &infin; if x&ge;0 or -&infin; if x<0
 * min(x0, x1, x2, &hellip;) - evaluates arguments and returns the smallest one
 * max(x0, x1, x2, &hellip;) - evaluates arguments and returns the largest one

Animation frame time functions:
 * frame - current animation frame number or CF::Frame if not animating, the return value is 0 for the first frame through 1 for the last frame.
 * ftime - current animation time or CF::FrameTime if not animating

Random functions:
 * rand_static - returns a static random number in the interval [0,1)
 * rand_static(x) - returns a static random number in the interval [0,x) (if x > 0) or [x,0) (if x < 0)
 * rand_static(x, y) - returns a static random number in the interval [x,y) (if y > x) or [y,x) (if x > y)
 * rand - returns a dynamic random number in the interval [0,1)
 * rand(x) - returns a dynamic random number in the interval [0,x) (if x > 0) or [x,0) (if x < 0)
 * rand(x, y) - returns a dynamic random number in the interval [x,y) (if y > x) or [y,x) (if x > y)
 * randint - returns a dynamic random integer in the interval [0,2) (i.e., returns 0 or 1)
 * randint(x) - returns a dynamic random integer in the interval [0,x) (if x > 0) or [x,0) (if x < 0)
 * randint(x, y) - returns a dynamic random integer in the interval [x,y) (if y > x) or [y,x) (if x > y)

The rand_static functions are converted into a random number when the cfdg file is compiled. So the value is constant for the entire run, but it is different for each variation. A rand_static function inside of a loop has the same value for each iteration of the loop. This is not as useful as the full dynamic random function that everyone fervently desires. But it is the best that can be done with the Context Free 2.x execution model and it is moderately useful.

rand and randint return new values each time they are executed. randint is equivalent to floor(rand) and is provided as a convenience.

Special Functions

 * select(n, expr0, expr1, expr2, expr3, &hellip;) - evaluates n and then evaluates and returns expr0 if n<1, expr1 if 1&le;n<2, expr2 if 2&le;n<3, etc. Must have at least two arguments. The expr0, expr1, expr2, etc. need not be numeric expressions, they can all be shape adjustments or shape specifications. They must all be the same type.
 * if(n, expr_true, expr_false) - evaluates n and then evaluates and returns expr_true if n&ne;0 or expr_false if n=0. This is just syntactic sugar for the select function.
 * let(var1=expr1; var2=expr2; &hellip; ; expression) - evaluates each of the argument expressions, expr1, expr2, etc., and binds them to var1, var2, etc. Then it evaluates the last expression in the context of the bound variables and returns this value. NB: the variable bindings are separated by semicolons, not commas.

Let Examples
Let us know if there is a function that you would like to see added to Context Free.

=Simple Expressions= inside shape adjustments there are limitations placed on the types of expressions that are allowed. Expressions in shape adjustments are called simple expressions, while the full strength expressions described above are called ordinary expressions.

simple expression :==
 * numeric constant
 * simple numeric constants (e.g., 12.45)
 * percentages (e.g., 9.6%)
 * (ordinary expression)
 * -simple expression
 * +simple expression
 * variable
 * function(ordinary expression) or function
 * vector[index] : vector access
 * simple expression &hellip; simple expression or simple expression .. simple expression
 * simple expression &plusmn; simple expression or simple expression +- simple expression
 * simple expression &plusmn; simple expression or simple expression +- simple expression

You can get around this restriction by wrapping an ordinary expression in parentheses.