|
@@ -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) {}
|