Get started
A model, its artifact, and generated code.
You write one .mox file. The compiler checks it, compiles it to Core IR, and every backend reads that artifact.
Confirm the binary is on your PATH:
pherolang --versionYou should see pherolang 0.3.0 and the target triple it was built for.
1 / Design
Design a domain
A .mox file declares a package and the classes inside it. Every other surface reads this one.
This is lines 1–32 ofexamples/support/support.mox, unchanged:
package nz.example.support
enum TicketState {
Open as "open" = 0
InProgress as "in_progress" = 1
Resolved as "resolved" = 2
}
class User {
id readonly String userId
String name
boolean active
refers Ticket[] assignedTickets opposite assignee
}
class Ticket {
id readonly String ticketNo
String title
boolean internal
int refundCents
TicketState state
refers User[0..1] assignee opposite assignedTickets
derived boolean needsRefund {
expr { refundCents > 0 }
}
op boolean raiseRefund(int cents) {
expr { refundCents + cents <= 5000 }
}
op boolean approveRefund(int cents) {
expr { refundCents + cents <= 100000 }
}
}Three lines in that excerpt do most of the work:
refers User[0..1] assignee opposite assignedTicketsdeclares both ends of one relation. The compiler checks that the two ends agree.derived boolean needsRefundis computed, not stored — it has a body and no stored value.op boolean raiseRefund(int cents)declares an operation whose body is written in the expression language and type-checked againstintarithmetic.
Declarations are checked, not annotated: a misspelt feature inside that body is a compile error. The grammar is inLANGUAGE.md; the expression rules are inEXPRESSIONS.md.
2 / Compile
Check, compile, generate
Four commands. Each one exits 0 on the example above.
Check
check parses, resolves, validates and type-checks the file. It reports each problem with the file and the exact span that caused it.
pherolang check examples/support/support.moxIt prints OK examples/support/support.mox and nothing else.
Compile to Core IR
ir writes the artifact and prints nothing when it succeeds. The second command reads the file back: artifact check validates the serialized JSON on its own — it opens no model, resolves no import, and runs no compiler.
pherolang ir examples/support/support.mox -o support.phero.json
pherolang artifact check support.phero.jsonThe first command produces no output; the second printsOK support.phero.json.
Generate
A backend reads the compiled model and writes code. Here is the Rust one, over the same source:
pherolang gen rust examples/support/support.mox -o support-genIt prints generated Rust model code into support-gen. You now havesupport-gen/models.rs: arena-based Rust model code, generated from the model rather than from the compiler's syntax tree.
3 / Understand
What you just built
The artifact is the product. The compiler's job ends at Core IR.
Parsing, name resolution, validation and lowering all happen before an artifact exists. Backends consume the artifact and nothing else — never the syntax tree. That is why an in-tree generator and an out-of-tree backend cannot disagree about a model's shape: they read the same Core IR, either in process or as the serialized artifact. The contract for writing one isBACKENDS.md.
{
"formatVersion": 2,
"pheroVersion": "0.3.0",
"packages": [
{
"name": "nz.example.support",
"annotations": [],
"enums": [
{
"name": "TicketState",
"literals": [ … ]
}
],
"classes": [ … ]
}
]
}Two fields do the work. formatVersion is the compatibility gate: a reader accepts that number or refuses the file. pheroVersion is provenance — which compiler wrote it, and nothing more.VERSIONING.mdstates the rule: readers gate on formatVersion only.
A second backend, over the same model:
pherolang gen json-schema examples/support/support.mox --profile wire -o support-schemaIt prints generated JSON Schema into support-schema. One model, two targets, one shape.
4 / Continue
Where to go next
The .mox domain is one of nine surfaces. They compile together into one semantic graph.
The example tree exercises every surface — designs, policies, decisions, event contracts, use cases, cases, interaction flows, deployments. check prints oneOK line per file:
pherolang check examples/graph build compiles that tree into one artifact instead of one per file: applications, every surface's nodes, and the edges between them. It is derived after compilation, never parsed.
pherolang graph build examples -o examples.graph.jsonLanguages
The other eight surfaces
Architecture
What the graph contains
Docs
The reference
Examples