# Introduction

The Calculon language is extremely simple. There are three types, `real`

,
`vector`

and `boolean`

. Everything is explicitly typed
(except that if you omit a type specifier, you get `real`

.
Everything is an expression. Variables are immutable and looping must be done
via recursion.

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:

`0`

is a real constant.`true`

or`false`

are boolean constants.`return`

must 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.w`

extract the first four elements from a vector. (Obviously assuming the vector has enough elements.) An out of bound access is a compile time error.`V[n]`

extracts the`n`

th 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.length`

returns the number of elements in a vector.`V.sum`

computes 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 expr`

defines 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 expr`

defines 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 expr`

defines a function. The new function is available both when evaluating`expr`

**and**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 falsevalue`

does conditional evaluation. If`booleanvalue`

is`true`

then`truevalue`

is evaluated; otherwise`falsevalue`

is evaluated. Both must have the same type.

In addition the usual set of infix and prefix operators are available:

- For
**booleans**:`==`

,`!=`

,`and`

,`or`

,`not`

.`and`

and`or`

are short-circuiting. - 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
operators, `if`

...`then`

...`else`

,
`let`

.

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:

`acos()`

`acosh()`

`asin()`

`asinh()`

`atan()`

`atan2()`

`atanh()`

`cbrt()`

`ceil()`

`copysign()`

`cos()`

`cosh()`

`erf()`

`erfc()`

`exp()`

`exp2()`

`expm1()`

`fabs()`

`fdim()`

`floor()`

`fma()`

`fmax()`

`fmin()`

`fmod()`

`hypot()`

`j0()`

`j1()`

`lgamma()`

`log()`

`log10()`

`log1p()`

`log2()`

`logb()`

`nearbyint()`

`pow()`

`remainder()`

`rint()`

`round()`

`sin()`

`sinh()`

`sqrt()`

`tan()`

`tgamma()`

`trunc()`

`y0()`

`y1()`