瀏覽代碼

Wrote about modelling language in the context of the modeller

Yentl Van Tendeloo 8 年之前
父節點
當前提交
97ffe87925
共有 2 個文件被更改,包括 117 次插入156 次删除
  1. 1 1
      doc/actionlanguage.rst
  2. 116 155
      doc/modeller_modellanguage.rst

+ 1 - 1
doc/actionlanguage.rst

@@ -32,7 +32,7 @@ The only requirement on the value, is that it is a string that can be parsed as
 
     >>> instantiate_attr_code("my_fsa", "transition_1", "action", \
     ...     """
-    ...     include "io.alh"
+    ...     include "primitives.alh"
     ...     Void function action(model : Element):
     ...         log("Executed action!")
     ...         return!

+ 116 - 155
doc/modeller_modellanguage.rst

@@ -4,206 +4,167 @@ Modelling Language
 Apart from the action language, the Modelverse also has a modelling language.
 With this language, models (*i.e.*, data) can be defined in addition to the algorithms.
 
-This language is still work in progress, but should be decent enough to construct simple metamodels and instantiate them.
+This language is still work in progress, but should be decent enough to construct simple models.
 All models have the extension \*.mvc, indicating that they are models and should be compiled as such.
+There is no constraint that this extension is mandatory.
 
-If you want to create models interactively, such as with another tool, it is strongly recommended to use the interactive interface to do this, as the modelling language is completely static.
+First, we show an example on how to create a simple PetriNet model.
+To take into account action language in the example model, we will also show an example for Finite State Automata.
 
-Language description
---------------------
+Example: Petri Nets
+-------------------
 
-The modelling language defines data structures, which will be formed as models in the Modelverse.
+Creating a simple Petri Net is easy using the Modelverse modelling language.
+An example is given below, which contains some places and transitions, with some connections between them::
 
-Several constructs are supported.
-
-Include
-^^^^^^^
-
-When combined with action language, for example with code fragments, the action language might require some includes of header files.
-To do this, the includes can be placed at the top of the hierarchy.
-The structure is as follows::
-
-        include "primitives.alh"
+    Place p1 {
+        name = "place 1"
+        tokens = 1
+    }
 
-Model
-^^^^^
+    Place p2 {
+        name = "place 2"
+        tokens = 2
+    }
 
-Every model is defined by first specifying the type of model to instantiate, followed by the name of the model to create.
-The name of the model can then later on be referenced in other models (as type, or for exporting).
-Within the model, all names of the type model can be used as types again.
-This is only used internally for bootstrapping purposes, so feel free to write whatever you want here.
+    Transition t1 {
+        name = "transition"
+    }
 
-The structure is as follows::
+    P2T p2t (p1, t1) {
+        weight = 1
+    }
 
-        SimpleClassDiagrams PetriNets{
-                ...
-        }
+    T2P t2p (t1, p2) {
+        weight = 2
+    }
 
-All further operations happen inside such a definition.
+The name immediately after the type (e.g., *p1*), is the identifier used throughout the textual representation.
+All identification of the element at the model-level should happen based on defined attributes.
+The identifiers can also be overwritten internally, in which case the latest definition is used.
+Do note that there is no concept of scope here, so identifiers stay visible throughout the whole file.
+It is possible to have anonymous identifiers, but only if the identifier is actually never used.
+For example, the two arcs could just as well have been defined as follows ::
 
-Instance
-^^^^^^^^
+    P2T (p1, t1) {
+        weight = 1
+    }
 
-A model consists of some instances.
-These instances are instances of types specified by the model that is the metaclass of the current model.
+    T2P (t1, p2) {
+        weight = 2
+    }
 
-The structure is as follows::
+Example: Finite State Automata
+------------------------------
 
-        SimpleClassDiagrams PetriNets {
-                Class Place {
-                        ...
-                }
-        }
+Next we use a simple Finite State Automata example model.
+This will introduce two new concepts: hierarchy and code attributes.
 
-Attribute
+Hierarchy
 ^^^^^^^^^
 
-Each model instance can contain attributes.
-There are two kinds of attributes: defining attributes, or value attributes.
-
-For defining attributes, the structure is as follows::
-
-    Class A{
-        my_parameter : ParameterType
-    }
+The Modelverse does not natively support a notion of hierarchy, but its modelling language can easily be used to represent hierarchy.
+Models can be indented, which means that a link is created from the container to the containee.
+If only one link type is allowed between both, the type is automatically selected.
+If multiple link types are possible, it is ambiguous and the model will fail to compile.
+For example, if we consider a hierarchical state::
 
-This defines a parameter called *my_parameter* which is typed by *ParameterType*.
-*ParameterType* must always be a type defined in the type that is being instantiated.
-Even if this is a primitive, such as *Integer*, the metamodel must define what it calls an *Integer*.
-While this might seem bothersome, this clearly defines the notion of what a type means, without having to resort to the implementation.
+    CompositeState s1 {
+        name = "state 1"
 
-Value attributes are similar, but have a different syntax, and contain an actual value.
-Their structure is as follows::
+        CompositeState s2 {
+            name = "state 2"
 
-    A a{
-        my_parameter = 1
+            State s3 {
+                name = "state 3"
+            }
+        }
     }
 
-They assign a value to a previously defined attribute.
-In this case, it is important that the value conforms to the type specified in the defining attribute.
-
-Merge with Action Language
---------------------------
-
-It is of course possible to incorporate action language inside of a model.
-A typical use case for this is the definition of constraints or actions.
-Action language is surrounded by dollar signs ($), which causes the parser to redirect the text between dollar signs to the action language parser.
-All includes necessary for the compilation of the action code, must be provided at the top of the document.
-
-Examples
---------
-
-Some simple examples of models are provided below.
-This code only makes the specified models available in code; to do something with these models, an algorithms has to read out the model and operate on it.
+    State s4 {
+        name = "state 4"
+    }
 
-Petri Net metamodel
-^^^^^^^^^^^^^^^^^^^
+When the only allowed links between a *CompositeState* and any other state is this, the model will compile fine as it is.
+However, we also want to define transitions, which can go from a *CompositeState* to a normal *State* as well.
+As such, we must update the model as follows, specifying the association type::
 
-A simple Petri Net metamodel can be created, based on the SimpleClassDiagrams metamodel.
-This looks like this::
+    CompositeState s1 {
+        name = "state 1"
 
-    import models/SimpleClassDiagrams as SCD
+        {Contains} CompositeState s2 {
+            name = "state 2"
 
-    SCD PetriNets{
-        SimpleAttribute Natural {}
-        Class Place{
-            tokens : Natural
-        }
-        Class Transition{}
-        Association P2T (Place, Transition) {
-            weight : Natural
-        }
-        Association T2P (Transition, Place) {
-            weight : Natural
+            {Contains} State s3 {
+                name = "state 3"
+            }
         }
     }
 
-    export PetriNets to models/PetriNets
+    State s4 {
+        name = "state 4"
+    }
 
-Note that in this metamodel, there is no constraint placed on the value of a Natural: it can literaly be anything.
-That is why usually, you want to place constraints on the value.
-In this case, the value needs to be an integer, and it must be larger than or equal to zero.
-Such constraints are written in the action language, surrounded by dollar signs::
+As there is no difference between *Contains* and *Transition*, there is nothing that prevents you from creating something like::
 
-    import models/SimpleClassDiagrams as SCD
-    include "primitives.alh"
+    State s1 {
+        name = "state 1"
 
-    SCD PetriNets{
-        SimpleAttribute Natural {
-            $
-                if (bool_not(is_physical_int(self))):
-                    return "Natural has no integer value at " + name!
-                elif (integer_lt(self, 0)):
-                    return "Natural does not have a positive or zero value at " + name!
-                else:
-                    return "OK"!
-             $
-        }
-        Class Place{
-            tokens : Natural {
-                target_lower_cardinality = 1
-                target_upper_cardinality = 1
-                }
-        }
-        Class Transition{}
-        Association P2T (Place, Transition) {
-            weight : Natural {
-                target_lower_cardinality = 1
-                target_upper_cardinality = 1
-                }
+        {Transition} State {
+            name = "state 2"
         }
-        Association T2P (Transition, Place) {
-            weight : Natural {
-                target_lower_cardinality = 1
-                target_upper_cardinality = 1
-                }
+
+        {Contains} State {
+            name = "state 3"
         }
     }
 
-Petri Net instance
-^^^^^^^^^^^^^^^^^^
+In this case, the state *state 1* and *state 2* are actually at the same level, with a transition between them.
+This can get rather confusing, and is therefore discouraged.
 
-The previous metamodel can then be instantiated::
+Code
+^^^^
 
-    import models/PetriNets as PetriNets
+Using code in the model definition is easy, and merely requires the use of the $ symbol around the text, instead of the usual " symbols.
+For example, to define a Transition with an action::
 
-    PetriNets my_petrinet {
-        Place p1 {
-            tokens = 1
-        }
-        Place p2 {
-            tokens = 3
-        }
-        Transition t1 {}
-        P2T (p1, t1) {
-            weight = 1
-        }
-        T2P (t1, p2) {
-            weight = 2
-        }
+    State s1 {
+        name = "state 1"
     }
 
-    export my_petrinet to models/my_petrinet
-
-Use in interactive interface
-----------------------------
-
-The interactive interface, such as the *prompt.py* script, can also invoke the model compiler.
-In this case, however, the import, export, and model type and model name parameters are ignored as they have to be defined and checked in the bigger context of the MvC.
+    State s2 {
+        name = "state 2"
+    }
 
-Internal use only
------------------
+    Transition (s1, s2) {
+        action = $
+            include "primitives.alh"
+            Void function action(model : Element):
+                log("Test!")
+                return !
+            $
+    }
 
-Some constructs only make sense in the context of the bootstrap generation.
-These constructs can still be used at all times, but are meaningless.
+In this case, it is impossible to use code defined externally.
+All code between $ symbols is passed on as-is to the action language compiler.
 
-Import
-^^^^^^
+Note the import statements, which will likely be repeated in each and every code block.
+It is possible to define include statements at the top of the model, in which case the include is automatically prepended in each and every code block::
 
-An import pulls in a model and makes it accessible using a simpler identifier.
-The structure is as follows::
+    include "primitives.alh"
 
-    import path/in/modelverse as my_model
+    State s1 {
+        name = "state 1"
+    }
 
-After this import, the model that was previously exported to *path/in/modelverse* becomes available as *my_model*.
+    State s2 {
+        name = "state 2"
+    }
 
+    Transition (s1, s2) {
+        action = $
+            Void function action(model : Element):
+                log("Test!")
+                return !
+            $
+    }