General
Core Concepts
The fundamental modeling construct is the Entity, representing a concept similarly to classes in OOP.
Entities may contain:
- Slots, which describe features or properties of the concept (similar to class fields).
A slot may optionally have a value, which can be either a primitive value (e.g., a Boolean literal) or a reference to another Entity.
- Operations, which define behavior (similar to methods).
- Annotations, which customize or influence behavior/handling of the container entity.
Notably, Slots, Operations, and Annotations are themselves modeled as Entities, ensuring a uniform representation across all elements.
Annotations can be added to Entities, Slots and Operations but not the Annotations.
Classification and Refinement
Each Entity has a unique Classifier, which serves as a template defining its structural elements (slots, operations, annotations). The relationship between an Entity and its Classifier is called Refinement. A sequence of such relationships forms the refinement chain, which may be of arbitrary length.
During refinement: - The Entity must conform to the structural constraints defined by its Classifier. - It may further concretize the concept, as long as it does not violate the constraints along the refinement chain.
Every Entity is a direct or indirect refinement of the built-in Base Entity, which is self-defined (i.e., Base is its own Classifier).
Loops are not allowed in the refinement chain, with the only exception being the built-in Base Entity, since it serves as its own Classifier.
Slots, Operations and Annotations of an Entity can themselves be refined, when refining the container Entity.
Slots
In entity definitions, slots are only explicitly declared when they are modified or specialized.
Inherited slots that remain unchanged are implicit: they are not listed in the definition but remain fully accessible and referenceable.
Slots accessible through the refinement chain can be further refined at any point, even skipping one or more intermediate refinement steps.
No Entity may have two slots with the same name accessible at any level, including implicit slots inherited from its Classifier.
If a slot has an assigned value, that value may be overridden during refinement.
An Entity may mark its slots as omitted using the Omit annotation.
Omitted slots become inaccessible and cannot be referenced further down the refinement chain.
During refinement, a slot may be split into multiple slots to represent distinct aspects or fragments of the original feature.
For example, a general wheel slot may be refined into frontWheel and rearWheel.
When dividing a slot into multiple slots:
- The new keyword must be applied consistently to all resulting slots to preserve the original slot.
- Otherwise, the original slot is implicitly omitted.
Slot division can also be used to rename a slot by creating a new slot from the original and omitting the original one.
New slots are introduced by dividing the special Base.Fields slot.
Therefore, adding new slots is only possible as long as Base.Fields has not been omitted.
Type System
The type system distinguishes between primitive values and modeled entities.
Primitive Types
The following primitive types are supported: - Boolean – true/false values - Integer – whole numbers - Float – decimal numbers - String – text
Modeled Entities
Modeled entities can be either:
- Static – these entities are included in the modeling space
- Dynamic – these entities exist only at runtime.
Dynamic entities allow modeling their structure and executing Operations on them, but are not added to the modeling space. As a result, static entities cannot reference dynamic entities, but dynamic entities can reference static entities. Dynamic entities are useful in scenarios such as passing structured parameters or reporting validation errors.
Validation
Every Entity has a Validate operation, which is used to check the correctness of its refinement.
Validation returns a collection of errors, or an empty list if the validation succeeds.
Validation checks are applied automatically by the framework, but they can also be called manually.
During refinement, the Validate operation can be overridden; however, all Validate operations along the entire refinement chain are always checked, so validation cannot be relaxed—only strengthened.
Validation may be influenced by Constraints. Constraints are Annotations with a special operation called Check. Similar to Validate, Check returns a list of errors. Constraints applied to entities are automatically checked whenever the entity is validated.
The validation rules defined within an Entity apply only to its refinements, not to the Entity itself. However, checks associated with constraints on the Entity are active at the annotated level. For example, if a type annotation is added to a Slot and a value is also assigned, the validation immediately verifies the value at that level.
Annotations
Omit
The Omit annotation can be applied to a Slot.
It indicates that the annotated slot cannot be referenced further down the refinement chain.
Type Constraint
The Type constraint specifies the type of a slot's value.
The type can be either a primitive or a modeled type.
In the case of a modeled type, type compatibility is checked along the refinement chain.
Cardinality Constraint
The Cardinality constraint defines the cardinality of a slot: how many fragments it can be divided into or how many values it can hold.
Final Constraint
The Final constraint indicates that the annotated Entity or Slot cannot be further instantiated.
- If applied to an Entity, all of its slots’ values must also be final (either literals or references to final entities).
Contract Constraint
The Contract constraint allows partial validation, similar to interfaces.
It defines a structure using slots. Any annotations may also be applied to the slots.
An Entity annotated with a Contract must:
- Include all the slots defined in the contract.
- Have the specified annotations (or their refinements) present on the corresponding slots.