Developers Guide¶
This guide is for developers who want to contribute to RIDDL itself—the compiler, tools, and ecosystem. If you're looking to use RIDDL to specify systems, see the Author's Guide or Implementor's Guide.
Prerequisites¶
To work on RIDDL development, you'll need:
- JDK 25 or later (Temurin recommended)
- Scala 3.3.x LTS (managed by sbt)
- sbt 1.10+ (Scala Build Tool)
- Git for version control
Getting Started¶
Clone the Repository¶
Build the Project¶
The staged executable will be at riddlc/target/universal/stage/bin/riddlc.
Project Structure¶
RIDDL is organized as a multi-module sbt project:
riddl/
├── language/ # Core language model and AST
├── passes/ # Compiler passes (parsing, validation, etc.)
├── commands/ # riddlc command implementations
├── riddlc/ # Command-line interface
├── testkit/ # Testing utilities
└── project/ # sbt build configuration
Key Modules¶
language - The foundation of RIDDL:
- AST definitions in
com.ossuminc.riddl.language.AST - Parser combinators using fastparse
- Source location tracking
passes - Compiler transformation passes:
- Parsing pass (text → AST)
- Resolution pass (resolve references)
- Validation pass (semantic checks)
- Symbol table construction
commands - The riddlc CLI:
- Command parsing and dispatch
- Option handling
- Output formatting
Code Generation
Code and documentation generation is available through
Synapify. The riddlc compiler focuses
on parsing and validation.
Development Workflow¶
Running Tests¶
# Run all tests
sbt test
# Run tests for a specific module
sbt "language/test"
sbt "passes/test"
# Run a specific test class
sbt "testOnly com.ossuminc.riddl.language.ParserSpec"
# Run tests continuously on file changes
sbt ~test
Code Coverage¶
Coverage reports are generated in target/scala-3.x/scoverage-report/.
Code Formatting¶
RIDDL uses scalafmt for consistent formatting:
# Format all code
sbt scalafmt test:scalafmt
# Check formatting without changes
sbt scalafmtCheck test:scalafmtCheck
Architecture Overview¶
Compiler Pipeline¶
RIDDL compilation follows a multi-pass architecture:
Source Text
│
▼
┌─────────┐
│ Parsing │ → AST (Abstract Syntax Tree)
└────┬────┘
▼
┌────────────┐
│ Resolution │ → Resolved references
└─────┬──────┘
▼
┌────────────┐
│ Validation │ → Errors/Warnings
└────────────┘
AST Design¶
The AST is defined in language/src/main/scala/com/ossuminc/riddl/language/AST.scala.
Key design principles:
- Immutable - All AST nodes are immutable case classes
- Hierarchical - Nodes form a tree with
Definitionas the base - Location-tracked - Every node carries source location information
Parser Design¶
RIDDL uses fastparse for its parser, defined in
language/src/main/scala/com/ossuminc/riddl/language/parsing/.
The parser is organized by language construct:
CommonParser.scala- Shared parsing utilitiesTypeParser.scala- Type expression parsingStatementParser.scala- Statement parsingDefinitionParser.scala- Definition parsing
Adding New Features¶
Adding a New Statement Type¶
-
Define the AST node in
AST.scala: -
Add parser rule in
StatementParser.scala: -
Add validation in the validation pass
-
Write tests covering parsing and validation
Adding a New Pass¶
-
Create a new pass class extending
Pass: -
Register the pass in the compiler pipeline
-
Write tests for the pass behavior
Testing Guidelines¶
Test Organization¶
- Unit tests - Test individual components in isolation
- Integration tests - Test component interactions
- Example tests - Test full RIDDL specifications
Writing Parser Tests¶
class MyParserSpec extends ParsingTestBase {
"MyParser" should {
"parse valid input" in {
val input = """my construct { ... }"""
parseDefinition(input) shouldBe a[MyConstruct]
}
"report errors for invalid input" in {
val input = """invalid syntax"""
parseDefinition(input) shouldBe a[ParsingError]
}
}
}
Writing Validation Tests¶
class MyValidationSpec extends ValidatingTestBase {
"MyValidation" should {
"detect invalid references" in {
val input = """domain D { context C { entity E { ??? } } }"""
val messages = validate(input)
messages should contain(a[MissingError])
}
}
}
Contributing¶
Contribution Process¶
- Fork the repository
- Create a branch for your feature:
git checkout -b feature/my-feature - Make changes with tests and documentation
- Ensure tests pass:
sbt test - Format code:
sbt scalafmt - Submit a pull request to the
developmentbranch
Code Review¶
Pull requests are reviewed for:
- Correctness and test coverage
- Code style consistency
- Documentation completeness
- Performance considerations
Commit Messages¶
Follow conventional commit style:
feat: add new statement type for async operations
Add AsyncStatement to support asynchronous message handling.
Includes parser and validation support.
Co-Authored-By: Your Name <email>
Debugging Tips¶
Parser Debugging¶
Enable parse tracing for detailed output:
AST Inspection¶
Use the dump command to see parsed AST:
Logging¶
RIDDL uses SLF4J logging. Configure log levels in logback.xml: