The Calculon language is extremely simple. There are three types,
boolean. Everything is explicitly typed
(except that if you omit a type specifier, you get
Everything is an expression. Variables are immutable and looping must be done
The simplest way to think about a Calculon script is as a series of let statements followed by a return, but the details are a bit more complicated than that.
The following list describes the major syntactic elements:
0is a real constant.
falseare boolean constants.
returnmust be the last keyword in a Calculon script. When seen, any output parameters are set and the scripts exit. You cannot use this inside a function.
[0, 1, 2]is a vector. The elements must be reals (but need not be constant). You may supply any positive, non-zero number of elements. The size of a vector is part of its type; vectors of different sizes are not compatible.
[*4 2]is also a vector; this has four elements, all of which are set to 2. The size of the vector must be a constant (but the value does not need to be).
sqrt(2)calls a function. Functions may take any number of parameters, of any type, and return a single parameter, of any type. Functions are not polymorphic.
V.x, V.y, V.z, V.wextract the first four elements from a vector. (Obviously assuming the vector has enough elements.) An out of bound access is a compile time error.
nth element of a vector. If the vector is square --- e.g. four, nine or sixteen elements --- you may also use
V[x, y]to extract a given element by coordinate. The elements are stored in row-major order. Out of bound indices wrap.
V.lengthreturns the number of elements in a vector.
V.sumcomputes the sum of all elements in the vector. (You can calculate the Pythagorean magnitude of a vector with
sqrt(V*V), of course.)
let i = 1 in exprdefines a variable that becomes available when evaluating
expr. The new variable is does not have an explicit type and its type is inferred from its definition.
let v: vector*3 = [0, 1, 2] in exprdefines a variable that becomes available when evaluating
expr. The new variable is explicitly typed and if you try to define a variable with a type that differs from its declaration you will get an error. You must specify the size of vectors.
let f(v1:vector*3, v2:vector*3):vector*3 = v1 + v2 in exprdefines a function. The new function is available both when evaluating
exprand inside the function body, which allows recursion. Note that the scoping rules here are different to when you define a variable! Also note that type inference is not done on functions!
if booleanvalue then truevalue else falsevaluedoes conditional evaluation. If
truevalueis evaluated; otherwise
falsevalueis evaluated. Both must have the same type.
In addition the usual set of infix and prefix operators are available:
- For booleans:
- For vectors:
/. the operation is applied to each component. If you're doing this, both parameters must have the same sized vector. For non-conditionals, if you pass a real as the second parameter, then that value is applied to all components.
- For reals: all the usual C-like operators. Complain if you find any missing.
The order of precedence, from highest to lowest, is: unary operators,
multiplication and division, addition and subtraction, comparisons, boolean
The type signatures used for Calculon scripts is subtly different from the type signatures used for Calculon functions. Functions may return only one value, and their signatures look like this:
(x:real, y:real): vector*2
Scripts may return any number of parameters, and their signatures look like this:
(x:real, y:real): (v:vector*2, length:real)
It is perfectly acceptable for output parameters to have the same name as an input parameter (or a global variable).
Most of the standard maths library is bound. They all behave exactly like their Posix namesakes. As of writing, the list consists of: