Browse Source

Make the action language section fit in with the context and provide primitives

Yentl Van Tendeloo 8 years ago
parent
commit
5f678e7f5b
1 changed files with 184 additions and 12 deletions
  1. 184 12
      doc/actionlanguage.rst

+ 184 - 12
doc/actionlanguage.rst

@@ -1,28 +1,67 @@
 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.
+Apart from simple attributes, such as the number of tokens on a PetriNet Place, code blocks are another frequent requirement.
+Current tools often do away with this by typing it as a string, and then passing it on internally to, for example, a Python interpreter.
+In this case, the code is nothing else than a string and there is no control whatsoever over the structure and semantics.
+Also, requiring an existing interpreter for that language, restricts the set of platforms for which a Modelverse can be implemented.
 
-Users will mainly use this language to write actions and constraints, or even model operations.
+In the Modelverse, we alleviate this problem by providing a built-in and explicitly modelled action language.
+This action language is primitive in the Modelverse, meaning that its abstract syntax tree can be represented, instead of just its textual representation.
+The abstract syntax tree is executed on-the-fly in the Modelverse, preventing the mapping to any other internal representation.
+The semantics of this language is also explicitly modelled, making it possible to automatically generate interpreters for any desired platform.
+
+In this section, we now focus on how to use this action language.
+As PetriNets are a bit too simple to require actions, we will use Finite State Automata as an example.
 
 .. warning::
    The current action language compiler is rather basic and contains quite some problems.
 
-Files
------
+Example: Finite State Automata
+------------------------------
+
+In the context of Finite State Automata, it is often necessary to define actions on specific transitions.
+Upon execution of the transition, the associated action is executed.
+When defining a model, we can also upload code snippets as attribute values::
+
+    >>> instantiate_attr_code("my_fsa", "transition_1", "action", open("actions/transition_1.alc", "r").read())
+
+This will assign the action stored in the file *actions/transition_1.alc* to the *action* attribute of the transition.
+Of course, it is not necessary to open a file for this, as the function itself could just as well be inlined.
+The only requirement on the value, is that it is a string that can be parsed as Action Language::
+
+    >>> instantiate_attr_code("my_fsa", "transition_1", "action", \
+    ...     """
+    ...     include "io.alh"
+    ...     Void function action(model : Element):
+    ...         log("Executed action!")
+    ...         return!
+    ...     """
+
+Action language attributes are considered identical to any other attribute.
+The exception is of course that they are assigned using the code specific function, as otherwise we would have uploaded a string.
+Note the difference between the assignment of a string, and the assignment of action code::
 
-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.
+    >>> instantiate_attr("my_fsa", "transition_1", "action", open("actions/transition_1.alc", "r").read())
+    >>> instantiate_attr_code("my_fsa", "transition_1", "action", open("actions/transition_1.alc", "r").read())
+
+The first line assigns a string to the attribute, and is therefore not executable, nor is it parsed or considered in any way.
+The second line assigns code to the attribute, and is therefore executable, and parsed upon assignment.
+
+The signature of each function, in the case of our example this is "Void function action(model : Element)", depends on how the code will be used later on.
+
+Multi-function code
+-------------------
+
+Some code is ideally expressed using multiple functions.
+As the Modelverse does not support subfunctions, it supports the second best alternative: multiple functions can be defined.
+When multiple functions are defined, the *main* function will be executed, which can refer to any of the other functions defined in the same block.
+If no *main* function is found, the topmost function is executed.
 
 Language description
 --------------------
 
+Next we describe the basic constructs of the language, as offered by our compiler.
 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.
@@ -202,6 +241,7 @@ 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.
+There is a set of standard header files included in the Modelverse, which are probably the only ones you will need.
 
 Constants
 ^^^^^^^^^
@@ -234,3 +274,135 @@ User input and output is done through the keyworded operations *input()* and *ou
 
 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.
+
+Primitive operations
+^^^^^^^^^^^^^^^^^^^^
+
+Apart from the minimal syntax, the Modelverse supports a wide library of functions.
+These functions are all built on top of the previously defined constructs.
+A list of these functions is shown below.
+
+* Boolean function value_eq(a: Element, b: Element)
+* Boolean function value_neq(a: Element, b: Element)
+* Boolean function bool_and(a: Boolean, b: Boolean)
+* Boolean function bool_or(a: Boolean, b: Boolean)
+* Boolean function bool_not(a: Boolean)
+* Element function create_node()
+* Element function create_edge(a: Element, b: Element)
+* Element function create_value(a: Element)
+* Boolean function is_edge(a: Element)
+* Integer function read_nr_out(a: Element)
+* Element function read_out(a: Element, b: Integer)
+* Integer function read_nr_in(a: Element)
+* Element function read_in(a: Element, b: Integer)
+* Element function read_edge_src(a: Element)
+* Element function read_edge_dst(a: Element)
+* Boolean function delete_element(a: Element)
+* Boolean function element_eq(a: Element, b: Element)
+* Boolean function element_neq(a: Element, b: Element)
+* Float function cast_i2f(a: Integer)
+* String function cast_i2s(a: Integer)
+* Boolean function cast_i2b(a: Integer)
+* Integer function cast_f2i(a: Float)
+* Boolean function cast_f2b(a: Float)
+* String function cast_f2s(a: Float)
+* Integer function cast_s2i(a: String)
+* Float function cast_s2f(a: String)
+* Boolean function cast_s2b(a: String)
+* Integer function cast_b2i(a: Boolean)
+* Float function cast_b2f(a: Boolean)
+* String function cast_b2s(a: Boolean)
+* String function cast_e2s(a: Element)
+* String function cast_a2s(a: Action)
+* String function cast_v2s(a: Element)
+* String function cast_id2s(a: Element)
+* Element function dict_add(a: Element, b: Element, c: Element)
+* Element function dict_add_fast(a: Element, b: Element, c: Element)
+* Element function dict_delete(a: Element, b: Element)
+* Element function dict_delete_node(a: Element, b: Element)
+* Element function dict_read(a: Element, b: Element)
+* Element function dict_read_edge(a: Element, b: Element)
+* Element function dict_read_node(a: Element, b: Element)
+* Integer function dict_len(a: Element)
+* Boolean function dict_in(a: Element, b: Element)
+* Boolean function dict_in_node(a: Element, b: Element)
+* Element function dict_keys(a: Element)
+* Float function float_addition(a: Float, b: Float)
+* Float function float_subtraction(a: Float, b: Float)
+* Float function float_multiplication(a: Float, b: Float)
+* Float function float_division(a: Float, b: Float)
+* Float function float_neg(a: Float)
+* Boolean function float_gt(a: Float, b: Float)
+* Boolean function float_gte(a: Float, b: Float)
+* Boolean function float_lt(a: Float, b: Float)
+* Boolean function float_lte(a: Float, b: Float)
+* Integer function integer_addition(a: Integer, b: Integer)
+* Integer function integer_subtraction(a: Integer, b: Integer)
+* Integer function integer_multiplication(a: Integer, b: Integer)
+* Integer function integer_division(a: Integer, b: Integer)
+* Integer function integer_modulo(a: Integer, b: Integer)
+* Boolean function integer_gt(a: Integer, b: Integer)
+* Boolean function integer_gte(a: Integer, b: Integer)
+* Boolean function integer_lt(a: Integer, b: Integer)
+* Boolean function integer_lte(a: Integer, b: Integer)
+* Boolean function integer_neg(a: Integer)
+* Element function list_read(a: Element, b: Integer)
+* Element function list_append(a: Element, b: Element)
+* Element function list_insert(a: Element, b: Element, c: Integer)
+* Element function list_delete(a: Element, b: Integer)
+* Integer function list_len(a: Element)
+* Boolean function list_in(a : Element, b : Element)
+* Element function set_add(a: Element, b: Element)
+* Element function set_add_node(a: Element, b: Element)
+* Element function set_pop(a: Element)
+* Element function set_read(a : Element)
+* Element function set_remove(a: Element, b: Element)
+* Boolean function set_in(a: Element, b: Element)
+* Element function set_remove_node(a: Element, b: Element)
+* Element function set_in_node(a: Element, b: Element)
+* Integer function set_len(a: Element)
+* String function string_join(a: String, b: String)
+* String function string_get(a: String, b: Integer)
+* String function string_substr(a: String, b: Integer, c: Integer)
+* Integer function string_len(a: String)
+* Element function string_split(a: String, b: String)
+* Boolean function string_startswith(a: String, b: String)
+* String function log(a: String)
+* Element function read_root()
+* Element function read_taskroot()
+* Element function input()
+* Element function output(a : Element)
+* Boolean function is_physical_int(a : Element)
+* Boolean function is_physical_float(a : Element)
+* Boolean function is_physical_string(a : Element)
+* Boolean function is_physical_action(a : Element)
+* Boolean function is_physical_boolean(a : Element)
+* Boolean function has_value(a : Element)
+* Float function time()
+* String function hash(a : String)
+* Void function sleep(a : Float)
+* Void function interruptable_sleep(a : Float)
+* Element function exec(a : Element)
+* Element function resolve(var_name : String)
+* Boolean function has_input()
+* Element function list_pop(lst : Element, index : Integer)
+* Element function list_pop_final(lst : Element)
+* Element function set_copy(set : Element)
+* String function set_to_string(set : Element)
+* String function list_to_string(set : Element)
+* String function dict_to_string(dict : Element)
+* Element function set_overlap(sa : Element, sb : Element)
+* Element function set_equality(sa : Element, sb : Element)
+* Element function dict_eq(da : Element, db : Element)
+* Element function dict_copy(dict : Element)
+* Element function set_to_list(s : Element)
+* Element function create_tuple(a : Element, b : Element)
+* Void function dict_overwrite(a : Element, b : Element, c : Element)
+* Void function set_merge(sa : Element, sb : Element)
+* Element function make_reverse_dictionary(dict : Element)
+* Element function set_create()
+* Element function list_create()
+* Element function dict_create()
+* String function reverseKeyLookup(a: Element, b: Element)
+* Element function reverseKeyLookupMulti(a: Element, b: Element)
+* Element function dict_values(dict : Element)