Modelling Language

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.

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.

Generalization

The first concept is that of generalization. As expected, a class can inherit from another class through the intuitive notation:

Class NamedElement {}
Class Place : NamedElement {}
Class Transition : NamedElement {}

What is special in the Modelverse, is that associations can just as well inherit from one another:

Association Arc (NamedElement, NamedElement) {}
Association P2T : Arc (Place, Transition) {}
Association T2P : Arc (Transition, Place) {}

Attributes

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:

Class NamedElement{
    name : String
}

Note that now as well, it is necessary to define the types. This can just be done as expected:

SimpleAttribute String {
    constraint = $
        String function constraint(value : Element):
            if (is_primitive_string(value)):
                return "OK"!
            else:
                return "String has a non-string value"!
        $
}

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:

Class NamedElement {
    name? : String
}

A Petri Net metamodel can now be created, based on the SimpleClassDiagrams metamodel. This looks like this:

include "primitives.alh"

SimpleAttribute String {
    constraint = $
        String function constraint(value : Element):
            if (is_primitive_string(value)):
                return "OK"!
            else:
                return "String has a non-string value"!
        $
}

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 NamedElement {
    name : String
}

Class Place : NamedElement {
    tokens : Natural
}

Class Transition : NamedElement {}

Association Arc (NamedElement, NamedElement) {
    weight : Natural
}

Association P2T : Arc (Place, Transition) {}

Association T2P : Arc (Transition, Place) {}