Skip to content

How Mate Works

Federico Lochbaum edited this page Mar 19, 2026 · 2 revisions

Mate is a grammar-driven framework for generating, parsing, and validating object graphs. It provides a declarative language to define the structure (types, fields, constraints, and relationships) of interconnected object instances. Much like a traditional grammar defines valid sentences in a language, a Mate grammar defines valid object graphs in a software system.

Core Concepts

Object Graph Grammar

A Mate grammar (MateOGGrammar) is a collection of type declarations that describe how objects relate to one another. Each type declaration maps a class to its expected structure: what instance variables it has, what types those variables hold, and what constraints apply.

Player -> {
  name: ByteString,
  characterClass: Warrior | Rogue | Mage,
  level: { type: SmallInteger, between: 0 and: 99 },
  missingExperienceForNextLevel: { type: SmallInteger, greaterThan: 0 }
}

This declaration states that a Player has four fields: name is a ByteString, characterClass is one of three possible classes (a union type), level is a SmallInteger constrained between 0 and 99, and missingExperienceForNextLevel is a SmallInteger greater than 0.

Three Core Operations

Mate performs three core operations over a grammar:

  1. Fuzzing — Generating random, grammar-conforming object graphs (MateGenerator)
  2. Parsing — Taking an existing object and producing its derivation tree (MateParser)
  3. Validation — Checking that an object conforms to the grammar's type and constraint rules (implicit in parsing)

Each of these operations is implemented as a visitor over the grammar's declaration tree. Mate uses the Visitor pattern: each declaration node (MateInstDecl, MateInstVarDecl, MateInstArrayVarDecl, etc.) dispatches to the appropriate visit* method on the active visitor.

Grammar Definition

Grammars can be defined in two ways:

Programmatically, by constructing declaration objects directly:

MatePersonGrammar >> initialize
  super initialize.
  self addTypeDeclaration: (MateInstDecl new 
    type: MatePerson; 
    instanceVariableDeclarations: {
      MateInstVarDecl new name: 'age'; type: MateAge 
    }).

Declaratively, using the Mate language (a textual DSL parsed by MateLanguageParser):

MatePersonGrammarByLang >> defineObjectGraph
  ^ '
    MatePerson -> { age: MateAge }
    MateAge -> { value: SmallInteger }
  '

Both approaches create the same internal representation. When a grammar subclass implements defineObjectGraph, the base class automatically parses the returned string and populates the type declarations.

The Visitor Architecture

Every grammar operation follows the same pattern:

Grammar → TypeDeclaration → visit:from:constraint: → Visitor method

The MateGrammarVisitor defines the abstract visitor interface with these methods:

Visitor Method Declaration Node Purpose
visitInstanceDeclaration:from: MateInstDecl Composite object with named fields
visitInstVarDecl:from: MateInstVarDecl A single typed field
visitArrayDecl:from: MateInstArrayVarDecl A collection field with element type and size constraints
visitOneOfDecl:from: MateInstOneOfVarDecl A field with a fixed set of literal options
visitInstRefDecl:from: MateInstRefVarDecl A back-reference to a parent object
visitBuiltinDeclaration:from:constraint: MateBuiltInDecl Built-in types (SmallInteger, ByteString, etc.)
visitClassDeclaration:from: MateClassDecl Class-level declarations

Concrete visitors (MateGenerator, MateParser, MateWriter) implement each of these methods to perform their specific operation.

Built-in Types

Mate recognizes the following built-in types, each backed by a specialized generator:

Type Generator
SmallInteger MateSmallIntegerGenerator
Float / SmallFloat64 MateFloatGenerator
Boolean MateBooleanGenerator
ByteString MateByteStringGenerator
Color MateColorGenerator
Point MatePointGenerator

Built-in types don't need explicit declarations in the grammar — they are automatically registered.

Advanced Features

  • Union types: A field can accept multiple types (Warrior | Rogue | Mage), represented internally by MateOptionalType
  • Constraints: Numeric fields can be bounded (between: 0 and: 99, greaterThan: 0), represented by MateConstraint
  • Arrays: Collection fields with element type and size bounds ({ type: [ BlElement ], sizeBetween: 0 and: 10 })
  • Self-references: Cyclic relationships where a child references its parent (selfReferences: { children.array[ .parent ] })
  • Reference types: Fields that point back to an existing object rather than creating a new one ({ refType: BlElement })
  • Reward back-propagation: The derivation tree supports feedback propagation for grammar-guided fuzzing (see Derivation Model and Object Graph Fuzzing)

Clone this wiki locally