Action Language
===============

The primary language of the Modelverse, is its action language.
This language serves as a nicer representation of the underlying Modelverse Graph Language, which is stored as a graph.
The action language gets parsed by the parser, resulting in a kind of abstract syntax graph.
This abstract syntax graph highly resembles an executable graph in the Modelverse Graph Language.

Users will mainly use this language to write actions and constraints, but maybe also to implement their own interfaces, or override core functionality of the Modelverse.

.. warning::
   The current parser is unable to handle whitespaces in a general way.
   As such, all indentation needs to be done using tabs, and the difference needs to be exactly 1.
   This is different from Python, where tabs and whitespaces can be mixed, and the number can even vary.

Files
-----

There are two kinds of files: code files, and headers.
This distinction is similar to C and related languages.
Code in header files will always be copied throughout all including files.
As such, it is a good idea to have header files which declare the signatures of functions, but leave the actual implementation to the code files.
Code files do not need to import the headers they are implementing: all variable names are automatically shared.

Language description
--------------------

The language is inspired by Python syntax, and highly resembles it.
Nonetheless, it is a lot simpler.
In the remainder of this subsection, we go over the different language constructs.

If
^^

The IF construct is similar to that found in other languages.
Its structure is as follows::

    if condition1:
       do_when_condition1
    elif condition2:
       do_when_condition2
    else:
       do_otherwise

Each condition can be an expression.
The code blocks can be any other kind of code.
Just like Python, indentation is the only way to structure code.
Unlike Python, only tabs are allowed (thus no space), and the number of tabs must be exactly one higher for a deeper block.

The presence of an "elif" and "else" is optional.

While
^^^^^

The WHILE construct is similar to that found in other languages.
Contrary to Python, there is no support for the "else" construct.
Its structure is as follows::

    while condition:
        action

Conditions and actions are similar to the If construct.

Break
^^^^^

Whereas this is supported in the Modelverse, the parser currently does not consider this keyword.

Continue
^^^^^^^^

Whereas this is supported in the Modelverse, the parser currently does not consider this keyword.

Return
^^^^^^

The RETURN construct is again similar to how it is expected.
To prevent ambiguity in the grammar, an exclamation mark should follow after the expression to return.
Its structure is as follows::

    return expression!

The expression can be any expression, similar to the condition in an If and While.

Function call
^^^^^^^^^^^^^

Function calls happen like usual, by appending an opening and closing parenthesis at the end.
Its structure is as follows::

    my_function(argument_a, argument_b)

Arguments can again be any kind of expression.
Named parameters are not supported in the grammar, though the Modelverse can internally handle them.

Function definition
^^^^^^^^^^^^^^^^^^^

Defining a function makes the function available as a variable in the remainder of the context.
Forward declaration is unnecessary: all function names are retrieved before going over the body of the functions.
This makes mutual recursion easy.

A function needs to define its return type, as well as the type of all its parameters.
In case the type is unknown, or can be anything, *Element* can be used as a kind of "void pointer".
Its structure is as follows::

    Element function function_name(parameter_a : Integer):
        body_of_the_function

First comes the returntype, followed by the keyword "function".
Again, indentation needs to happen using tabs.

Assignment
^^^^^^^^^^

Assignment is like usual.
Its structure is::

    a = expression

This assumes that a is already defined.

Declaration
^^^^^^^^^^^

All variables used in the Modelverse need to be defined statically.
Defining a variable reserves a part of the Modelverse State to hold the value for this value.
As such, variables cannot be used if they are not defined.
Additionally, a declared variable will have a type defined with it.
Again, if the type can vary or is unknown, this can be *Element*.

.. warning::
   Contrary to other languages, declaring a variable does not equal defining the variable.
   Therefore, after a variable is declared, it can be used, but its contents will be non-existing.
   It is wise to always assign a value to a declared value right after declaration!

Its structure is as follows::

    String abc

There are two kinds of declaration: local declaration, and global declaration.
Local declarations happen in the current block of the code, and their references get removed when exiting the block.
Global declarations have identically the same syntax, but are specified at the top level (*i.e.*, they have no tabs in front of them).
Global declarations do not assign a value and are thus external references, to be defined in the future or by some other module.
Sharing between modules is possible this way, as all global names are linked together when linking the application together.
A global declaration that is never defined is flagged as invalid by the compiler and will prevent compilation.

Definition
^^^^^^^^^^

Defining a variable is similar to a global declaration, but now there is an immediate assignment.
Immediate assignment is only possible at the top level.
Note that the assignment must be of a constant which requires no execution of functions or such.
Also, it is impossible to assign the value of another variable.

Its structure is as follows::

    String abc = "abc"

It is possible that a definition does not yet know the value to assign, or is an empty element.
To notify the other files that this is the defining element, use the import syntax to assign *?* to it::

    Element abc = ?

This results in the Modelverse creating an empty node as placeholder for a value.
The value will now be defined and accessible.

Imports
^^^^^^^

Direct imports in the Modelverse are possible, but are not recommended for ordinary users.
This syntax allows a variable to be bound to an absolute location in the Modelverse, which is resolved at compile time.
The primary use case for this is the creation of bootstrap files, but it is also possible for other purposes.
Use with care!

Its structure is as follows::

    String abc = ?path/in/modelverse

A special case is when the path is empty, which indicates that a new (anonymous) node should be created for it::

    Element abc = ?

Include
^^^^^^^

Other files can easily be included using the include syntax.
This is a raw include: the contents of the file are just copied inside the file at that exact spot.
Generally, you should only include *.alh* files, unless you know what you are doing.

Constants
^^^^^^^^^

The Modelverse supports a set of constants that can be used.
All constants can be assigned in a definition of globals.

============= ========================================================================== =======
Constant type Values                                                                     Example
============= ========================================================================== =======
Integer       Any possible integer, either positive (no prefix) or negative (- prefix)   1
Float         Any possible floating point value; scientific notation is not supported    1.0
Boolean       Either True or False                                                       True
String        Any possible string, enclosed with either double or single quotes          "abc"
Action        An action construct from the Modelverse, prefixed with an exclamation mark !If
============= ========================================================================== =======

Operators
^^^^^^^^^

While operators are seemingly supported by the compiler, these are actually expanded to function calls to relevant functions.
For example, *1 + 2*, is expanded to *integer_addition(1, 2)*

User I/O
^^^^^^^^

User input and output is done through the keyworded operations *input()* and *output(msg)*.
*input()* returns the first message in the input queue of the current user.
*output(msg)* places the value of the expression in the output queue of the current user.

All I/O is done using queues: the value is only read and written to a specific place in the Modelverse.
To actually read or write it at the client side, these special places should be accessed through dedicated Modelverse operations.

Examples
--------

We now show some simple code fragments written in valid Action Language code.
As this code is directly executable in the Modelverse, the main function is always called "main" and all includes are also present.
We do not currently handle how to execute this code: this is explained further on.

Fibonacci
^^^^^^^^^

The Fibonacci code is fairly simple.
First, the primitives are imported to make sure that we know about all operations on primitives.
Then, a function *fib* is defined, which will recursively compute the specified Fibonacci number.
This is wrapped by a *main* function, which takes input from the user and outputs the result of the *fib* function.

This code looks as follows::

    include "primitives.alh"

    Integer function fib(param : Integer):
        if (param <= 2):
            return 1!
        else:
            return fib(param - 1) + fib(param - 2)!

    Void function main():
        while(True):
            output(fib(input()))

Factorial
^^^^^^^^^

Similarly, the code for computing a factorial is given below::

    include "primitives.alh"

    Integer function factorial(n : Integer):
        if(n <= 1):
            return 1!
        else:
            return n * factorial(n - 1)!

    Void function main():
        while(True):
            output(factorial(input()))

Binary to decimal converter
^^^^^^^^^^^^^^^^^^^^^^^^^^^

A simple binary to decimal converter is given below::

    include "primitives.alh"

    Integer function b2d(param : String):
        Integer value
        value = 0
        Integer length
        length = string_len(param)
        Integer counter
        counter = integer_subtraction(length, 1)
        Integer accumul
        accumul = 1

        while (counter >= 0):
            if (string_get(param, counter) == "1"):
                value = integer_addition(value, accumul)
            accumul = integer_multiplication(accumul, 2)
            counter = integer_subtraction(counter, 1)

        return value!

    Void function main():
        while(True):
            output(b2d(input()))
