Browse Source

Wrote part about modelling language for language engineers

Yentl Van Tendeloo 4 years ago
parent
commit
2d1cee14ea
1 changed files with 69 additions and 175 deletions
  1. 69 175
      doc/languageengineer_modellanguage.rst

+ 69 - 175
doc/languageengineer_modellanguage.rst

@@ -1,209 +1,103 @@
 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.
+We now revisit the modelling language.
+All concepts defined for modellers, are equally valid for language engineers.
+Indeed, language engineering is a specific type of modelling.
 
-This language is still work in progress, but should be decent enough to construct simple metamodels and instantiate them.
-All models have the extension \*.mvc, indicating that they are models and should be compiled as such.
+The only real extension that we need to make, is to extend the syntax with a specific construct to define a generalization hierarchy and attributes.
 
-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.
+Generalization
+--------------
 
-Language description
---------------------
+The first concept is that of generalization.
+As expected, a class can inherit from another class through the intuitive notation::
 
-The modelling language defines data structures, which will be formed as models in the Modelverse.
+    Class NamedElement {}
+    Class Place : NamedElement {}
+    Class Transition : NamedElement {}
 
-Several constructs are supported.
+What is special in the Modelverse, is that associations can just as well inherit from one another::
 
-Include
-^^^^^^^
+    Association Arc (NamedElement, NamedElement) {}
+    Association P2T : Arc (Place, Transition) {}
+    Association T2P : Arc (Transition, Place) {}
 
-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::
+Attributes
+----------
 
-        include "primitives.alh"
+Attributes can still be created using only modelling constructs, as introduced before, though this becomes convoluted.
+More efficiently, the attribute can be defined as follows.
+Note that, thanks to inheritance, the *Place* and *Transition* can also access the *name* attribute, as they inherit it.
+The *NamedElement* can now be defined as follows::
 
-Model
-^^^^^
-
-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.
-
-The structure is as follows::
-
-        SimpleClassDiagrams PetriNets{
-                ...
-        }
-
-All further operations happen inside such a definition.
-
-Instance
-^^^^^^^^
-
-A model consists of some instances.
-These instances are instances of types specified by the model that is the metaclass of the current model.
-
-The structure is as follows::
-
-        SimpleClassDiagrams PetriNets {
-                Class Place {
-                        ...
-                }
-        }
-
-Attribute
-^^^^^^^^^
-
-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
+    Class NamedElement{
+        name : String
     }
 
-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.
-
-Value attributes are similar, but have a different syntax, and contain an actual value.
-Their structure is as follows::
+Note that now as well, it is necessary to define the types.
+This can just be done as expected::
 
-    A a{
-        my_parameter = 1
+    SimpleAttribute String {
+        constraint = $
+            String function constraint(value : Element):
+                if (is_primitive_string(value)):
+                    return "OK"!
+                else:
+                    return "String has a non-string value"!
+            $
     }
 
-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
---------
+Finally, it is possible to define an *optional* attribute.
+In that case, the attribute must not be defined, though you should be aware that reading an undefined attribute will result in an error value being returned.
+Default values are not supported in the Modelverse.
+This is done by using the following notation to make the attribute optional::
 
-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.
-
-Petri Net metamodel
-^^^^^^^^^^^^^^^^^^^
-
-A simple Petri Net metamodel can be created, based on the SimpleClassDiagrams metamodel.
-This looks like this::
-
-    import models/SimpleClassDiagrams as SCD
-
-    SCD PetriNets{
-        SimpleAttribute Natural {}
-        Class Place{
-            tokens : Natural
-        }
-        Class Transition{}
-        Association P2T (Place, Transition) {
-            weight : Natural
-        }
-        Association T2P (Transition, Place) {
-            weight : Natural
-        }
+    Class NamedElement {
+        name? : String
     }
 
-    export PetriNets to models/PetriNets
-
-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::
+A Petri Net metamodel can now be created, based on the SimpleClassDiagrams metamodel.
+This looks like this::
 
-    import models/SimpleClassDiagrams as SCD
     include "primitives.alh"
 
-    SCD PetriNets{
-        SimpleAttribute Natural {
+    SimpleAttribute String {
+        constraint = $
+            String function constraint(value : Element):
+                if (is_primitive_string(value)):
+                    return "OK"!
+                else:
+                    return "String has a non-string value"!
             $
-                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!
+    }
+
+    SimpleAttribute Natural {
+        constraint = $
+            String function constraint(value : Element):
+                if (bool_not(is_physical_int(value))):
+                    return "Natural has no integer value"!
+                elif (integer_lt(value, 0)):
+                    return "Natural does not have a positive or zero value"!
                 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
-                }
-        }
-        Association T2P (Transition, Place) {
-            weight : Natural {
-                target_lower_cardinality = 1
-                target_upper_cardinality = 1
-                }
-        }
+            $
     }
 
-Petri Net instance
-^^^^^^^^^^^^^^^^^^
-
-The previous metamodel can then be instantiated::
-
-    import models/PetriNets as PetriNets
-
-    PetriNets my_petrinet {
-        Place p1 {
-            tokens = 1
-        }
-        Place p2 {
-            tokens = 3
-        }
-        Transition t1 {}
-        P2T (p1, t1) {
-            weight = 1
-        }
-        T2P (t1, p2) {
-            weight = 2
-        }
+    Class NamedElement {
+        name : String
     }
 
-    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.
-
-Internal use only
------------------
-
-Some constructs only make sense in the context of the bootstrap generation.
-These constructs can still be used at all times, but are meaningless.
-
-Import
-^^^^^^
+    Class Place : NamedElement {
+        tokens : Natural
+    }
 
-An import pulls in a model and makes it accessible using a simpler identifier.
-The structure is as follows::
+    Class Transition : NamedElement {}
 
-    import path/in/modelverse as my_model
+    Association Arc (NamedElement, NamedElement) {
+        weight : Natural
+    }
 
-After this import, the model that was previously exported to *path/in/modelverse* becomes available as *my_model*.
+    Association P2T : Arc (Place, Transition) {}
 
+    Association T2P : Arc (Transition, Place) {}