Let the Baboon do the monkey job.
Baboon is a minimal Data Modeling Language and compiler that provides ergonomic, declarative schemas and enforces reliable schema evolution. The compiler runs as a fast immutable multi-phase DAG transform, and is easy to understand and maintain.
- Set-based structural inheritance with
+,-, and^operators - Automatic codec derivation for JSON and UEBA (Ultra-Efficient Binary Aggregate, a custom tagless binary format)
- Evolution-aware codegen: derives migrations when possible, emits stubs when manual work is required
- Structural and nominal inheritance (contracts)
- Namespaces, includes, and imports
- Collections (
opt,lst,set,map) and timestamps/UID primitives - Codegen targets: C#, Scala, will be more.
- Deduplicated C# output (reuse as much code as possible for lower binary footprint)
Detailed language walkthrough with copy-paste examples: docs/language-features.md.
- No templates
- Only Enums, DTOs and ADTs
- Nominal inheritance support is limited to trait model
- Generic/type constructor support is limited to builtin collections
- (*) This is a DML, not an IDL, service/interface definitions support is extremely limited at the moment
- (*) Comments are not preserved in the cogen output
- (*) No structural inheritance information is preserved in the transpiler output
- (*) Only integer constants may be associated with enum members
- (*) No newtypes/type aliases
- (*) No inheritance-based lenses/projections/conversions
Points marked with (*) will/may be improved in the future.
See build configuration in .mdl/defs/actions.md and test configuration in .mdl/defs/tests.md.
- All the types which are not transitively referenced by
roottypes will be eliminated from the compiler output. - Usages in structural inheritance are not considered references, so structural parents which are not directly referenced as fields and not marked as
roots will be eliminated
Be careful about foreign types. It is your responsibility to wire codecs correctly.
For every foreign type:
- Create a custom codec
- Override the generated dummy codec with
BaboonCodecs#Register - Override the generated dummy codec using the setter on
${Foreign_Type_Name}_UEBACodec#Instance - Override the generated dummy codec using the setter on
${Foreign_Type_Name}_JsonCodec#Instance
Make sure your foreign types are NOT primitive types or other generated types. It's a funny idea, but it will explode in runtime.
Foreign types may hold any position in generics but it's up to you to ensure correctness.
This project uses mudyla for build orchestration.
# Format code
direnv exec . mdl :fmt
# Build the compiler
direnv exec . mdl :build
# Run complete test suite
direnv exec . mdl :build :test
# Run full build pipeline (format, build, test)
direnv exec . mdl :full-build
# Run specific test suites
direnv exec . mdl :build :test-gen-regular-adt :test-cs-regular :test-scala-regular
direnv exec . mdl :build :test-gen-wrapped-adt :test-cs-wrapped :test-scala-wrapped
direnv exec . mdl :build :test-gen-manual :test-gen-compat-scala :test-gen-compat-cs :test-manual-cs :test-manual-scala
# Create distribution packages
direnv exec . mdl :build :mkdist
# Build with custom distribution paths
direnv exec . mdl --mkdist-source=./custom/path --mkdist-target=./output :build :mkdist# Enter the nix development shell
nix develop
# Or use direnv for automatic shell activation
direnv allow