Child pages
  • Structure
Skip to end of metadata
Go to start of metadata

Since MPS frees you from defining a grammar for your intented languages, you obviously need different ways to specify the structure of your languages. This is where the Structure Language comes in handy. It gives you all the means to define the language structure. As we discussed earlier, when coding in MPS you're effectively building the AST directly, so the structure of your language needs to specify the elements, the bricks, you use to build the AST.

The bricks are called Concepts and the Structure Language exposes concepts and concept interfaces as well as their members: properties, references, children, concept(-wide) properties, and concept(-wide) links.

Concepts and Concept Interfaces

Now let's look at those in more detail. A Concept defines the structure of a concept instance, a node of the future AST representing code written using your language. The Concept says which properties the nodes might contain, which nodes may be referred to, and what children nodes are allowed (for more information about nodes see the Basic notionssection). Concepts also define concept-wide members - concept properties and concept links, which are shared among all nodes of the particular Concept. You may think of them as "static" members.

Apart from Concepts, there are also Concept Interfaces. Concept interfaces represent independent traits, which can be inherited and implemented by many different concepts. You typically use them to bring orthogonal concepts together in a single concept. For example, if your Concept instance has a name by which it can be identified, you can implement the INamedConcept interface in your Concept and you get the name property plus associated behavior and constraints added to your Concept.

Concepts inheritance

Just like in OO programming, a Concept can extend another Concept, and implement many Concept Interfaces. A Concept Interface can extend multiple other Concept Interfaces. This system is similar to Java classes, where a class can have only one super-class but many implemented interfaces, and where interfaces may extend many other interfaces.

If a concept extends another concept or implements a concept interface, it transitively inherits all members (i.e if A has member m, A is extended by B and B is extended by C, then C also has the member m)

Concept interfaces with special meaning

There are several concept interfaces in MPS that have a special meaning or behavior when implemented by your concepts. Here's a list of the most useful ones:

Concept Interface

Meaning

IDeprecatable

Used if instances of your concept can be deprecated. Sets a strikeout style if isDeprecated set to true.

INamedConcept

Used if instances of your concept have an identifying name. This name appears in the code completion list.

IType

Is used to mark all concepts representing types

IWrapper

Deleting a node whose immediate parent is an instance of IWrapper deletes the parent node as well.

Concept members

Properties

Property is a value stored inside a concept instance. Each property must have a type, which for properties is limited to: primitives, such as boolean, string and integer; enumerations, which can have a value from a predefined set; and constrained data types (strings constrained by a regular expression).

References

Holding scalar values would not get as far. To increase expressiveness of our languages nodes are allowed to store references to other nodes. Each reference has a name, a type, and a cardinality. The type restricts the allowed type of a reference target. Cardinality defines how many references of this kind a node can have. References can only have two types of cardinalities: 1:0..1 and 1:1.

Smart references

A node containing a single reference of 1:1 cardinality is called a smart reference. These are somewhat special references. They do their best to hide from the language user and be as transparent as possible. MPS treats the node as if it was a the actual reference itself, which simplifies code editing and code-completion. For example, default completion items are created whenever the completion menu is required: for each possible reference target, a menu item is created with matching text equal to the presentation of a target node.

Children

To compose nodes into trees, we need to allow children to be hooked up to them. Each child declaration holds a target concept, its role and cardinality. Target concept specifies the type of children. Role specifies the name for this group of children. Finally, cardinality specifies how many children from this group can be contained in a single node. There are 4 allowed types of cardinality: 1:1, 1:0..1, 1:0..n, and 1:1..n.

Specialized references and children

Sometimes, when one concept extends another, we not only want to inherit all of its members but also want to override some of its traits. This is possible with children and references specialization. When you specialize a child or reference, you narrow its target type. For example, if you have concept A which extends B, and have a reference r in concept C with target type B, you might narrow the type of reference r in C's subconcepts. It works the same way for concept's children.

Concept links and properties

Sometimes we want to define concept-wide members. For example, we might want to describe how all instances of a particular type will be presented in a completion menu. Or we frequently need to mark a concept as abstract. Also concept-wide members can help you express some domain specific purpose of a concept. This is what concept links and properties are for. Concept link and properties are declared in a concept declaration and the value you assign to them are valid for all instances of that concept. Also, if you have a concept-wide member declaration specified in a particular concept, different concrete values can then be set to the member in its subconcept. For example, the "abstract" concept property, which is of a boolean type, is declared in the BaseConcept concept. Some sub-concepts, like BaseAssignmentExpression have the "abstract" concept-wide property set to true, while others, like e.g. AssignmentExpression not. It is then up to the language designer to reflect the property values in the language behavior.

Annotation concepts

TO DO..

Previous Next

  • No labels

3 Comments

  1. Anonymous

    Correction:

    (i.e if A has member m, B is extended by C and C is extended by E, then E has member m)

    should read

    (i.e if A has member m, A is extended by B and B is extended by C, then C has member m)

  2. Anonymous

    ... if your concept has a name by which it can be identified ...

    Isn't the concept instance that which is identified by the name?