﻿ Kronos Beta 1

A Very Quick Reference

## Overview

Kronos programs are built from expressions and definitions.

An expression describes a sequence of mathematical or logical operations to produce a result from one or more initial values.

A definition binds an expression to a symbol. Subsequently, the symbol can be used to refer to the expression.

## Expressions

`x + 3 * Crt:cos(y)`

This expression describes a computation of a numerical result from the initial values of x, 3 and y.

Expressions are essentially a sequence of tokens. In the example above, the tokens are x, +, 3, * and Crt:cos(y).

Tokens are delimited by either white space or parentheses.

### Constants

Constants are plain numbers. A plain number is interpreted as a 32-bit floating point real number. Prefices and suffices can be used to enforce a different number type;

```3i      /* constant 3 as a 32-bit integer */
3.1415d /* constant 3.1415 as a 64-bit real */
9q      /* constant 9 as a 64-bit integer */
#6.54   /* special type of number Invariant */```
##### Invariant

Invariant numbers are prefixed with '#'.

Such numbers are important for two reasons; they never change during program execution and can thus be heavily optimized. The compiler can also use them for metaprogramming purposes.

### Literals

String literals can be entered as quoted strings;

`"Hello World"`

### Symbols

Symbols can be names for variables or functions. They can include alphanumeric characters as well as some punctuation characters.

Each symbol must start with an alphabetical character.

```x
MyVariabeName
some-symbol123
attention!```

### Tuples

A tuple is a grouping of data. Such grouping is expressed with parentheses.

`(1 2 3 4 5)`
A tuple of five numbers.
`[1 2 "text" 3]`
A list containing numbers, a string and a number.
`[(1 2) (10 20) (100 200)]`
A list of three vectors

### Functions

A symbol and a tuple without an intervening whitespace is considered a function.

The symbol names the function, and the tuple specifies the arguments passed to the function.

```Factorial(#5)
Algorithm:Reduce(Add 1 2 3 4)```
Some function calls
```(somesymbol(1 3)) /* this is a function call in parentheses */
(somesymbol (1 3)) /* this is a 3-member tuple! */ ```
Whitespace is important to disambiguate functions and tuples!

### Infix Functions

The Kronos parser translates some infix operators to functions for a more readable syntax. The following relations apply:

```a + b   /* Add(a b) */
a - b   /* Sub(a b) */
a * b   /* Mul(a b) */
a / b   /* Div(a b) */
a > b   /* Greater(a b) */
a < b   /* Less(a b) */
a == b  /* Equal(a b) */
a != b  /* Not-Equal(a b) */
a >= b  /* Greater-Equa(a b) */
a >= b  /* Less-Equal(a b) */
a & b   /* And(a b) */
a | b   /* Or(a b) */
a ^ b   /* Xor(a b) */
```

Because some infix characters are legal token characters, infix operators must always be surrounded by whitespace:

```much - fun   /* becomes Sub(much fun) */
much-fun     /* refers to symbol 'much-fun' */
```

## Definitions

Actual programming in Kronos happens via definitions. For example, to hear an audio output, you define the audio-generating function.

### Symbols

Defining symbols is called binding.

Definitions are done via the equality sign.

```a = 5 /* a is now 5 */
x = y / Sqrt(z) /* an expression tied to x */
```

Defined symbols are unlike variables in two accords; they actually contain the expression itself, rather than the value it results in. Secondly, typical to functional languages, once defined, they can never change.

#### Tie-in

Multiple symbols can be defined at once by defining a .

```(a b c) = (1 2 3) /* a is now 1, b is 2... */
```

Tie-in is mostly useful when you receive a tuple that is bound to a symbol. The tuple can be deconstructed with a partial tie-in:

```/* suppose list = (1 2 3 4 5) */
(x xs) = list /* x is now 1, xs is (2 3 4 5) */
```

Together with recursion, partial tie-in is used for loop-like constructs.

#### Ignore-binding

You can use '_' as a special symbol that never actually gets defined. Useful as a part of a tie-in, you can use it to ignore certain parts of the tuple.

```someSurroundSignal = (l1 c1 r1 ls1 rs1 lfe)
(l2 _ r2 _) = someSurroundSignal
```

In this exampe, l2 and r2 were bound to l1 and r1, while the rest of the elements are just ignored.

The first '_' corresponds to c1 and the second one to the tuple (ls1 rs1 lfe).

### Functions

Function definitions look like so;

```MyFunction(x y z)
{
MyFunction = x + y + z
}
```

The first line contains the function name and the argument tuple. In the consequent wavy brackets, the function bodies are given by way of defining a symbol eponymous to the function.

This particular example computes the sum of three numbers.

To call the function, attach an argument tuple;

```MyFunction(1 2 3) /* returns 6 */
```

If you refer to the function name without arguments, it evaluates to the definition of the function itself. This way, you can use function definitions as data.

#### Polymorphism

Multiple definitions for a function can be given at once. This allows the function to behave differently according to its arguments.

```SumNumbers(numbers)
{
(a b) = numbers
SumNumbers = a + b
/* second form */
(x y z) = numbers
SumNumbers = x + y + z
}
```

This function can sum either three or two arguments.

Polymorphism is often most useful in the case of recursion:

```SumNumbers(numbers)
{
SumNumbers = numbers
/* second form */
(n ns) = numbers
SumNumbers = n + SumNumbers(ns)
}
```

This function can sum any number of arguments; while the 'numbers' argument can be tied-in to (n ns), the function calls itself with 'ns' as the argument and adds the result to 'n'. At some point, 'numbers' is going to be a single number, at which point the first definition will be used instead.