Introduction
Metta is a foundational Domain-Specific Language (DSL) within the Quassar environment, designed to enable the creation of new DSLs through the declarative definition of metamodels. Its goal is to let developers design custom modeling languages tailored to specific domains — without having to write parsers or grammar rules by hand.
Instead of describing DSLs through low-level grammars such as EBNF or parser generators, Metta focuses on defining the structure of a language itself. A metamodel written in Metta specifies the essential building blocks of a DSL — including concepts, properties, components, facets, and semantic rules. These elements capture the organization of the domain and define how its parts relate to one another, forming the blueprint from which the DSL is automatically generated.
A typical metamodel includes concepts, properties, optional facets, composition relationships, and formal constraints. Once the metamodel is defined, it is transformed automatically into a working DSL. This is done through a specialization process over a shared base language called Tara. Tara provides the common syntax and grammar, while Metta injects domain-specific vocabulary and semantic rules. The result is a concrete DSL that can be used to model real-world instances using a consistent, expressive, and safe syntax.
The DSL produced from Metta can be used for configuration, simulation, validation, or code generation. It preserves the structure and logic defined in the metamodel, ensuring that models are aligned with the domain’s semantics from the start.
Metta is especially suited for domains with layered abstractions, such as smart cities, digital twins, industrial systems, and autonomous agents. It addresses the common pain points in DSL development — fragmentation, inconsistency, and duplication — by offering a single, reusable foundation from which reliable domain languages can be systematically derived.
Core Concepts
Metta is centered around a set of semantic constructs that enable the structured definition of DSLs. This approach allows developers to generate new DSLs automatically, with consistent structure and semantics, tailored precisely to the needs of any domain.
- Concept: A category that groups entities sharing the same structure and defining properties. Concepts are derived from metaconcepts and serve as templates for instantiating specific elements in lower levels of abstraction.
- Facet: An optional dimension that can be assigned to concepts or entities to enrich them with additional properties or behaviors. Facets support polymorphism and modularity, allowing cross-cutting features to be modeled cleanly.
- Property: A descriptive feature of a metaconcept or concept. Properties define the internal structure of elements and may include constraints on type, value ranges, or units of measurement.
- Relationship: A semantic link between elements, such as generalization/specialization, composition, or abstraction/concretization. These define how concepts and entities are structured and interrelated within the domain.
- Semantic Rule: A formal constraint that governs the validity of models. These include rules about instantiation, property immutability, required facets, component cardinality, and more. Semantic rules ensure that the model aligns with the logic of the domain.
Getting Started
This section introduces brico, a DSL for modeling smart buildings. It walks you through a minimal working example, showing how to define your domain in Metta and then instantiate it using the brico language.
Step 1: Define the domain with Metta
We start by describing the abstract structure of a building system: a campus is composed of buildings, which contain floors, rooms, and sensors. Each element includes its own properties and constraints.
Concept Campus
def string manager
def string location
Concept:{1..*} Building
def string address
def integer yearBuilt
has Sensor
Concept:{1..*} Floor
def integer level
Concept:{1..*} Room
def integer area
has Sensor
Concept Sensor is component
facet Type
sub Temperature
sub Humidity
sub CO2
Step 2: Validate the metamodel
Run the check operation to ensure the model has no structural or semantic errors. Any issues must be fixed before continuing.
Step 3: Commit the version
Once validated, use the commit operation to save the metamodel as version 1.0.0. Future changes will ask whether to register a major, minor, or patch update, and the version number will be updated accordingly.
Step 4: Forge the DSL
Use the forge operation to create the DSL based on your metamodel. You’ll be taken to the DSL’s forge interface, where you can configure:
- Name: brico
- Logo: auto-generated, editable
- Title: Brico — DSL for modeling smart building structures
- Description: A language for defining campuses, buildings, rooms, and sensors
- How to cite: Editable text
- License: Defaults to MIT (can be changed)
Step 4.1 (optional): Create a model template
In the Kit tab, define a starter structure or files that will appear when someone creates a new model with brico.
Step 4.2 (optional): Add examples
Also in the Kit tab, you can include example models to help users get started faster.
Step 4.3 (optional): Write documentation
In the Help tab, you can write the reference guide for your DSL, explaining concepts, syntax, and examples.
Step 4.4: Define the execution environment
To enable execution, simulation, or transformation of models, use the Execution Environment tab. This environment is built using the automatically generated parser library.
The parser lets you load and work with models programmatically. You can download it or add it as a Maven dependency. It’s the foundation for anything you want to build on top of your DSL — from code generators to runtime engines.
Step 5: Start modeling
Once the DSL is forged, you can use the start modeling operation to create and edit actual models using brico.
Here is an example of a concrete model:
Campus North
manager = "Alice Rivera"
location = "North Zone"
Building Alpha
address = "123 Innovation Blvd"
yearBuilt = 2012
Floor(level = 1)
Room(area = 35)
Sensor is Temperature
Sensor is CO2
Room
area = 28
Sensor is Humidity
Floor(level = 2)
Room
area = 42
Sensor is Temperature
Building(address = "125 Innovation Blvd", yearBuilt = 2015) Beta
Floor(level = 0) > Room(area = 30) > Sensor is CO2
Tip: This example is ready to copy and modify. You can rename buildings, change sensor types, or adjust the structure as needed.
DSL Reference
This section provides detailed, structured reference for each top-level construct in the DSL.
Properties and Relationships
Syntax
property ::= "def" type IDENTIFIER [ "=" literal ]
type ::= [ primitiveType ":" identifer | "word" ":"" "{" wordlist "}" | IDENTIFIER ][ "[" "]"
primitiveType ::= "string" | "integer" | "boolean" | "double" | "long" | "instant"
wordList ::= stringLiteral { "," stringLiteral }
literal ::= scalarLiteral | listLiteral
scalarLiteral ::= stringLiteral | integerLiteral | booleanLiteral | doubleLiteral
listLiteral ::= "[" scalarLiteral { "," scalarLiteral } "]"
Examples
Primitive Properties
This example defines a Room concept using several primitive properties. The property name is a string that identifies the room. The property area is an integer representing the surface in square meters. The property hasWindow is a boolean with a default value of true, indicating whether the room has natural light. Finally, ceilingHeight is a double with a unit of measurement in centimeters (cm), and a default value of 300.
Concept Room
def string name
def integer area
def boolean hasWindow = true
def double:cm ceilingHeight = 300
Word Properties
This concept uses multiple enumerated properties to define categorical characteristics. Each property restricts the valid values to a predefined list.
Concept Device
def word:{Online, Offline, Maintenance} status = Online
def word:{Low, Medium, High} batteryLevel
def word:{Sensor, Actuator} type = empty
List Properties
This example defines two properties. tags is a list of strings used to label or categorize an element (e.g., "public", "featured"). status is an enumerated property restricted to three valid values, ensuring consistent classification across instances.
def string[] tags = ["public", "featured"]
def word:{Active, Inactive, Pending} status
Relational Property
This example shows how to define a property that links an object to another instance in the model. Here, an Incident is associated with a specific Building< using a reference-type property.
Concept Incident
def string description
def instant timestamp
def Building building
Rules and Notes
- Supported types include primitives, lists of primitives, and constrained enumerated sets using
word:{...}. - Default values are optional and must conform to the type (a literal or a list).
- List values use square brackets and blank-separated literals, e.g.,
["a" "b" "c"]. - Each property name must be unique within its concept or metaconcept scope.
- Semantic metadata such as immutability, measurement units, or cardinality must be declared separately via constraints.
Tip: Use[]to declare list-based properties, andword:{...}when you need a fixed set of valid values.
Concept
Syntax
concept ::= "Concept" [ cardinality ][ IDENTIFIER ][ extension ][ modifierList ]
{ INDENT conceptBody }
conceptBody ::= property
| composition
| specialization
| facet
composition ::= "has" [cardinality] IDENTIFIER | concept
extension ::= "extends" IDENTIFIER
specialization ::= "sub" IDENTIFIER [ modifierList ]
{ INDENT conceptBody }
facet ::= "facet" IDENTIFIER
{ INDENT conceptBody }
cardinality ::= "{" min ".." max "}"
modifierList ::= "is" modifier { modifier }
modifier ::= "final" | "component" | "abstract" | "required"
IDENTIFIER ::= ? valid identifier name ?
INDENT ::= ? newline and indentation ?
Examples
Basic Concept
This example defines a basic concept called Sensor, marked as a component, meaning it is designed to be included inside other concepts rather than instantiated independently. It has two string properties: id, which uniquely identifies the sensor within the system, and manufacturer, which records the name of the company or entity that produced the device. This concept can be reused across different models where sensing elements are required, such as in buildings, vehicles, or environments.
Concept Sensor is component
def string id
def string manufacturer
Concept including component
This example defines a concept named Floor, which includes a nested concept called Room. Inside Room, there is a composition reference to Sensor using the has keyword. This illustrates the two main ways to express composition in Metta. The first is structural composition, where a concept is declared inside another — as Room is declared inside Floor. The second is referential composition, where one concept includes another via has — as Room includes Sensor. The referenced concept (Sensor) is typically marked with is component to indicate that it is meant to be embedded rather than used independently.
Concept Floor
def integer level
Concept Room
def integer area
has Sensor
Concept with Cardinality and Modifier
This example defines a concept named Building. The cardinality declaration {1..*} indicates that at least one instance of Building must exist wherever it is used (e.g., within a parent concept like Campus). The concept is also marked as abstract, which means it cannot be instantiated directly. Instead, it is intended to be specialized by other concepts (e.g., ResidentialBuilding, OfficeBuilding) that inherit its structure and extend it. This is useful for enforcing a shared base structure while requiring domain-specific variants.
Concept:{1..*} Building is abstract
def string address
def integer yearBuilt
Facet Declaration
Defines a facet that can be applied to Room entities to indicate emergency access availability.
Concept Room
facet EmergencyAccess
def boolean enabled = false
Rules and Notes
- Concept is used to declare domain abstractions and their structure.
- A concept may contain properties, components, nested sub-concepts, and facet declarations.
- Cardinality can be used to enforce how many instances of a sub-concept or component are expected.
- Concept names must be unique within the same context. Nested concepts are scoped locally.
- Facet declarations inside a concept define optional extensions applicable to other concepts or entities.
Tip: Use concept nesting to structure complex domains hierarchically and reuse concepts viahasorfacet.
Use Cases
Below are practical examples showing how metamodels written in Metta give rise to usable DSLs, and how those DSLs are then used to describe concrete scenarios.
Smart Campus
This metamodel defines a campus composed of buildings, which contain floors and rooms. Each room may include sensors of various types. Once committed and forged, it produces a DSL (e.g., brico) that users can apply to model real environments such as a university or office complex.
Metamodel
Concept Campus
def string manager
def string location
Concept:{1..*} Building
def string address
def integer yearBuilt
has Sensor
Concept:{1..*} Floor
def integer level
Concept:{1..*} Room
def integer area
has Sensor
Concept Sensor is component
facet Type
sub Temperature
sub Humidity
sub CO2
Model
Campus North
manager = "Alice Rivera"
location = "North Zone"
Building Alpha
address = "123 Innovation Blvd"
yearBuilt = 2012
Floor(level = 1)
Room(area = 35)
Sensor is Temperature
Sensor is CO2
Room(area = 28)
Sensor is Humidity
Floor(level = 2)
Room(area = 42)
Sensor is Temperature
Patient Monitoring
This metamodel defines a hospital system with patients, rooms, and vital signs. Patients are associated with rooms and include vital signs as components. Each vital sign facet declares a threshold and expects a measured value that may be used for alerts or clinical analysis.
Metamodel
Concept Hospital
def string name
Concept:{1..*} Room
def integer number
Concept Patient
def string fullName
def integer age
def Room room
has VitalSign
Concept VitalSign is component
facet Type
sub Temperature
def double:°C value
def double:°C threshold = 38.0
sub HeartRate
def integer:bpm value
def integer:bpm threshold = 100
sub SpO2
def integer:% value
def integer:% threshold = 90
Model
Hospital General
name = "St. Mary Hospital"
Room(number = 101) R101
Room(number = 102) R102
Patient
fullName = "Laura Gómez"
age = 46
room = General.R101
VitalSign is Temperature
value = 37.4
VitalSign is SpO2
value = 92
Patient
fullName = "Tomás Ibáñez"
age = 72
room = General.R101
VitalSign is HeartRate(value = 108)
Patient
fullName = "Lina Ruiz"
age = 35
room = General.R102
VitalSign is Temperature(value = 39.1)
VitalSign is HeartRate(value = 95)
Syntax Sugar
To keep models concise and readable, DSLs generated from Metta support a few syntax shortcuts. These are syntactic sugars that make writing models faster without changing their meaning.
1. Property values can be written in the constructor or in the body
You can assign values to properties either inside the constructor or as indented assignments in the body. Both styles are equivalent and can be mixed as needed.
Person pau
age = 35
Person(age = 35) pau
Person(35) pau
In the last form, the value is assigned positionally, according to the order of properties in the concept definition.
2. Single child blocks can be shortened with >
When a block contains exactly one indented element, you can replace the block with a single-line version using the > symbol. This keeps the model clean when nesting is minimal.
Concept Person
def int age
Person > age = 35
Person
age = 35
Both forms are equivalent. The > is especially useful when a concept includes just one property, component, or nested element.
3. Instance names are optional
In most cases, you can omit the name of an instance if it's not needed for reference. This makes the model cleaner when working with anonymous or throwaway objects.
Room
number = 101
Patient
fullName = "Laura Gómez"
age = 46
If needed, you can still assign a name for later reference:
Patient laura
fullName = "Laura Gómez"
age = 46
Tip: These shortcuts improve fluency, but you can always fall back to the full form for clarity or consistency.
Best Practices
To get the most out of Metta and build DSLs that are maintainable, expressive, and reusable, it's important to follow a few design principles when creating your metamodels.
-
Focus on the domain, not the implementation.
Capture the core concepts, structure, and logic of your domain. Avoid including technical details like data formats, algorithms, or user interfaces in the metamodel. -
Keep concepts focused and cohesive.
Each concept should represent a single, well-defined idea. If it grows too broad, consider splitting it or using facets to modularize optional features. -
Use facets for reusable or optional traits.
When a property or behavior is relevant across multiple concepts, define it as a facet instead of duplicating the same fields. -
Prefer composition over inheritance.
Use has relationships to represent structure and avoid deep hierarchies. This keeps your models modular and easier to evolve. -
Declare constraints explicitly.
Use formal rules like instantiation lock, component lock, or immutability to express your design intent clearly. Don't rely only on naming or documentation. -
Use clear and domain-specific names.
Avoid generic terms like item, object, or thing. Choose names that reflect how people in the domain actually speak. -
Provide thoughtful defaults and enumerations.
When possible, define sensible default values. If you use enumerations (word:{...}), make sure the list of options is complete and unambiguous. -
Begin at the metaconcept level.
Start by identifying the core types of concepts your DSL will need. This helps organize the model and makes the language easier to generate and extend. -
Validate early and iterate often.
Don't wait until the model is finished to test it. Generate and test DSL examples as you go to verify that your structure behaves as expected.
Tip: You don't need to design the perfect model on day one. With Metta, you can evolve your language safely as your understanding of the domain deepens.
Appendices
Glossary
- Concept
- A structural abstraction that defines a category of elements in the domain, including its properties, subcomponents, and internal logic.
- Property
- A named attribute defined with def, which describes characteristics of a concept or metaconcept. Properties can be scalar, enumerated, or lists, and may have default values and constraints.
- Facet
- An optional extension that adds additional properties or behavior to a concept or entity. Facets are reusable and can be applied across different concepts.
- Component
- A relationship defined with has that indicates one concept is composed of another. Components form hierarchical structures between domain elements.
- Cardinality
- A constraint indicating the number of allowed instances for a concept or component (e.g. {1..*}).
- Modifier
- Semantic annotations added with is that restrict or influence behavior, such as final, immutable, or component lock.
- Literal
- A concrete value used to assign defaults to properties. Supported types include strings, integers, booleans, doubles, and lists of literals.
- Tara
- The mother language that provides the common grammar, base syntax, and foundational semantics shared by all DSLs generated from Metta.
- Specialization
- The process by which a DSL is derived from Tara using a domain-specific metamodel defined in Metta. Each specialization produces a new, tailored DSL.