The Quassar foundational DSL for generating DSLs

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.

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:

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

Tip: Use [] to declare list-based properties, and word:{...} 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

Tip: Use concept nesting to structure complex domains hierarchically and reuse concepts via has or facet.

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.

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.

Resources