# The Aseba language

This help is also available within Aseba Studio in the `Help->Language` menu. When using technical words, these are linked to the corresponding Wikipedia article. You might also want to read the concepts page first. The page presents the language as it is from version 1.2 of Aseba, for earlier versions, please read this page.

The Aseba language resembles Matlab (a common scientific programming language); this similarity allows developers with previous knowledge of some scripting language to feel quickly at ease with Aseba and thus lowers the learning curve. Semantically, it is a simple imperative programming language with a single basic data type (16 bit signed integers) and arrays. This simplicity allows developers to program behaviours with no prior knowledge of a type system, integers being the most natural type of variables and well suited to programming microcontroller-based mobile robots.

# Comments

Comments allow information to be added which is ignored by the compiler. Comments are very useful to annotate the code with human-readable notes or to temporarily disable some code. Comments begin with a # and terminate at the end of the line.

Example:

    # this is a comment
    var b # another comment

Comments spanning several lines are also possible. They begin with #* and end with *#.

Example:

    #*
    this is a comment spanning
    several lines
    *#
    var b # a simple comment

# Scalars

Scalar values are used in Aseba to represent numbers. They can be used in any expressions, like the initialisation of a variable, a mathematical expression or in a logical condition.

## Notation

Scalars can be given using several radices. The most natural way is the decimal system, using digits from 0 to 9. Negative numbers are declared using a `-` (minus) sign in front of the number.

    i = 42
    i = 31415
    i = -7

Both binary and hexadecimal numbers can also be used. Binary numbers are prefixed by `0b`, whereas hexadecimal numbers are prefixed by `0x`.

    # binary notation
    i = 0b110         # i = 6
    i = 0b11111111    # i = 255

    # hexadecimal notation
    i = 0x10    # i = 16
    i = 0xff    # i = 255

# Variables

Variables refer either to single scalar values or to arrays of scalar values. The values are comprised between -32768 and 32767, which is the range of 16 bit signed integers. You must declare all user-defined variables, using the keyword `var`, at the beginning of the Aseba script before doing any processing.

The name of a variable is defined by these rules:

- The name can only contain upper or lower case alphabetic characters, '_' or '.'
- The name must start with a valid alphabetic character or '_'
- The name is case sensitive: a variable named "foo" is different from one named "Foo"
- The name cannot be identical with one of Aseba's keywords (see reserved keywords)

Variables may be initialised in the declaration, using the assignation symbol and combined with any valid mathematical expression. A variable without any prior initialisation may have a random value, it should never be assumed to be zero.

Example:

    var a
    var b = 0
    var c = 2*a + b        # warning: 'a' is not initialised

## Reserved keywords

The following keywords cannot be used as a valid name for variables, as they are already used by the Aseba language.

Keywords
abs | call | callsub | do
else | elseif | emit | end
for | if | in | onevent
return | step | sub | then
var | when | while |

## Constants

Constants can be defined in Aseba Studio, using the "Constants" panel, but they cannot be defined directly in the code. A constant represents a numeric value, which can be used wherever a number can be used. But unlike a variable, a constant cannot be modified during execution. Constants are useful when you want to easily change the behaviour between different executions, such as while adapting a threshold value, with a scope spanning several Aseba nodes. A constant cannot have the same name as a variable, otherwise an error is raised.

    # assuming a constant named THRESHOLD
    var i = 600

    if i > THRESHOLD then
        i = THRESHOLD - 1
    end

## Arrays

Arrays represent a contiguous area in memory, addressed as a single logical entity. The size of an array is fixed and must be specified in the declaration. Arrays can be declared using the usual square bracket operator `[]`. The number between the square brackets specifies the number of elements to be assigned to the array, thereafter referred to as its size. It can be any constant expression, including mathematical operations using scalars and constants. An optional assignation can be made using the array constructor (see below). If this is done, the size of the array need not be specified.

Example:

    var a[10]                   # array of 10 elements
    var b[3] = [2, 3, 4]        # initialisation
    var c[] = [3, 1, 4, 1, 5]   # implicit size of 5 elements
    var d[3*FOO-1]              # size declared using a constant expression (FOO declared as a constant)

Arrays can be accessed in several ways:

- A single element is accessed by using the square bracket operator with a single value. Array indexes begin at zero. Any expression can be used as index, including mathematical expressions involving other variables.
- A range of elements can be accessed by using the square bracket operator with two constant expressions separated by a colon ':'.
- If the square brackets are omitted, the entire array is accessed.

Example:

    var foo[5] = [1,2,3,4,5]
    var i = 1
    var a
    var b[3]
    var c[5]
    var d[5]

    a = foo[0]       # copy first element from 'foo' to 'a'
    a = foo[2*i-2]       # same
    b = foo[1:3]       # take 2nd, 3rd and 4th elements of 'foo', copy to 'b'
    b = foo[1:2*2-1]   # same
    c = foo           # copy 5 elements from array 'foo' to array 'c'
    d = c * foo       # multiply arrays 'foo' and 'c' element by element, copy result to 'd'

## Array constructors

Array constructors are a way to build arrays from variables, other arrays, scalars, or even complex expressions. They are useful in several cases, for example when initialising another array, or as operands in expressions, functions and events. An array constructor is made by using square brackets enclosing several expressions separated by a `,` (comma). The size of an array constructor is the sum of the sizes of the individual elements, and it must match the size of the array in which the result is stored.

Example:

    var a[5] = [1,2,3,4,5]    # array constructor to initialise an array
    var b[3] = [a[1:2],0]    # results in array b initialised to [2,3,0]
    a = a + [1,1,1,1,1]    # add 1 to each element of array a
    a = [b[1]+2,a[0:3]]    # results in [5,2,3,4,5]

# Expressions and assignations

Expressions allow mathematical computations and are written using the normal mathematical infix syntax. Assignations use the keyword `=` and set the result of the computation of an expression into a scalar variable, an array element or a whole array, depending on the size of the operands. Aseba provides several operators. Please refer to the table below for a brief description, as well as for the precedence of each operator. To evaluate an expression in a different order, pairs of parentheses can be used to group sub-expressions.

Precedence | Operator | Description | Associativity | Arity
--- | --- | --- | --- | ---
1 | () | Group a sub-expression |  | unary
2 | * / | Multiplication, division |  | binary
| % | Modulo |  | binary
3 | + - | Addition, subtraction |  | binary
4 | << >> | Left shift, right shift |  | binary
5 | | | Binary or | Left associative | binary
6 | ^ | Binary exclusive or (xor) | Left associative | binary
7 | & | Binary and | Left associative | binary
8 | - | Unary minus |  | unary
9 | ~ | Binary not |  | unary
10 | abs | Absolute value |  | unary
11 | = | Assignment |  | binary
| |= ^= &= | Assignment by binary or, xor, and |  | binary
| *= /= | Assignment by product and quotient |  | binary
| %= | Assignment by modulo |  | binary
| += -= | Assignment by sum and difference |  | binary
| <<= >>= | Assignment by left / right shift |  | binary
| ++ -- | Unary increment and decrement |  | unary

The assignment by versions of the binary operators work by applying the operator to a variable and storing the result in this same variable. For instance, `A *= 2` is equal to `A = A * 2`. These short-cuts aim at making the code more readable.

Example:

    a = 1 + 1
    # Result: a = 2
    a *= 3
    # Result: a = 6
    a++
    # Result: a = 7

    b = b + d[0]
    b = (a - 7) % 5
    c[a] = d[a]
    c[0:1] = d[2:3] * [3,2]

## Usage

Mathematical expressions are a general tool. As such, they can be used in a great variety of situations. Just to mention a few:

- On the right side of an assignation
- As an index when accessing elements of arrays
- Inside function calls
- As argument when emitting an event

# Flow control

## Conditionals

Aseba provides two types of conditionals: `if` and `when`. These consist of a test of conditions and blocks of code. The test consists of comparisons, optionally grouped using the `and` (logical conjunction), `or` (logical disjunction), and `not` (logical negation) operators, and parentheses.
A comparison consists of an operator and two operands, and can either be true or false. The operands can be arbitrary expressions. The following table lists the comparison operators.

Operator | Truth value
--- | ---
`==` | true if operands are equal
`!=` | true if operands are different
`>` | true if first operand is strictly larger than the second one
`>=` | true if the operand is larger or equal to the second one
`<` | true if first operand is strictly smaller than the second one
`<=` | true if the operand is smaller or equal to the second one

Both `if` and `when` execute a different block of code according to whether a condition is true or false; but `when` executes the block corresponding to true only if the last evaluation of the condition was false and the current one is true. This allows the execution of code only when something changes. The `if` conditional executes a first block of code if the condition is true, a second block of code to execute if the condition is false can be added using the `else` keyword. Furthermore, additional conditions can be chained using the `elseif` keyword.

Example:

    if a - b > c[0] then
        c[0] = a
    elseif a > 0 then
        b = a
    else
        b = 0
    end

    if a < 2 and a > 2 then
        b = 1
    else
        b = 0
    end

    when a > b do
        leds[0] = 1
    end

Here the `when` block executes only when `a` becomes larger than `b`.

## Loops

Two constructs allow the creation of loops: `while` and `for`.

A `while` loop repeatedly executes a block of code as long as the condition is true. The condition is of the same form as the one `if` uses.

Example:

    while i < 10 do
        v = v + i * i
        i = i + 1
    end

A `for` loop allows a variable to iterate over a range of integers, with an optional step size.

Example:

    for i in 1:10 do
        v = v + i * i
    end
    for i in 30:1 step -3 do
        v = v - i * i
    end

# Blocks

## Subroutines

When you want to perform the same sequence of operations at two or more different places in the code, you can write common code just once in a subroutine and then call this subroutine from different places. You define a subroutine using the `sub` keyword followed by the name of the subroutine. You call the subroutine using the `callsub` keyword, followed by the name of the subroutine. Subroutines must be defined before they are called. Subroutines cannot have arguments, nor be recursive, either directly or indirectly. Subroutines can access any variable.

Example:

    var v = 0

    sub toto
    v = 1

    onevent test
    callsub toto

## Events

Aseba is an event-based architecture, which means that events trigger code execution asynchronously.
Events can be external, for instance a user-defined event coming from another Aseba node, or internal, for instance emitted by a sensor that provides updated data. The reception of an event executes, if defined, the block of code that begins with the `onevent` keyword followed by the name of the event; the code at the top of the script is executed when the script is started or reset. The script can also send events by using the `emit` keyword, followed by the name of the event and the name of the variable to send, if any. If a variable is provided, the size of the event must match the size of the argument to be emitted. Instead of a variable, array constructors and mathematical expressions can also be used in more complex situations. Events allow the script to trigger the execution of code on another node or to communicate with an external program.

To allow the execution of related code upon new events, scripts must not block and thus must not contain any infinite loop. For instance in the context of robotics, where a traditional robot control program would do some processing inside an infinite loop, an Aseba script would just do the processing inside a sensor-related event.

Example:

    var run = 0

    onevent start
    run = 1

    onevent stop
    run = 0

    onevent ir_sensors
    if run == 1 then
        emit sensors_values proximity_sensors_values
    end

## Return Statement

It is possible to early return from subroutines and stop the execution of events with the `return` statement.

Example:

    var v = 0

    sub toto
    if v == 0 then
        return
    end
    v = 1

    onevent test
    callsub toto
    return
    v = 2

# Native functions

We designed Aseba script to be simple in order to allow a quick understanding even by novice developers and to implement the virtual machine efficiently on a micro-controller. To perform complex or resource-intensive processing, we provide native functions that are implemented in native code for efficiency. For instance, a native function is the natural way to implement a scalar product.

Native functions are safe, as they specify and check the size of their arguments, which can be constants, variables, array accesses, array constructors and expressions. In the case of an array, you can access the whole array, a single element, or a sub-range of the array. Native functions take their arguments by reference and can modify their contents but do not return any value. You can use native functions through the `call` keyword.

Example:

    var a[3] = 1, 2, 3
    var b[3] = 2, 3, 4
    var c[5] = 5, 10, 15
    var d
    call math.dot(d, a, b, 3)
    call math.dot(d, a, c[0:2], 3)
    call math.dot(a[0], c[0:2], 3)

# What to read next?

You might be interested to read:

- Description of the native functions standard library