Bläddra i källkod

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

Yentl Van Tendeloo 8 år sedan
förälder
incheckning
5f678e7f5b
1 ändrade filer med 184 tillägg och 12 borttagningar
  1. 184 12
      doc/actionlanguage.rst

+ 184 - 12
doc/actionlanguage.rst

@@ -1,28 +1,67 @@
 Action Language
 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::
 .. warning::
    The current action language compiler is rather basic and contains quite some problems.
    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
 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.
 The language is inspired by Python syntax, and highly resembles it.
 Nonetheless, it is a lot simpler.
 Nonetheless, it is a lot simpler.
 In the remainder of this subsection, we go over the different language constructs.
 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.
 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.
 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.
 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
 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.
 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.
 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)