Luce / engineering
Learn Luce LuciaOS

What a language change costs

Adding syntax is rarely just a parser edit. If the feature changes behavior, its meaning must reach HIR, MIR, the runtime or backend, both execution tests, documentation, and sometimes an artifact version.

Change matrix

ChangeRequired surfacesVersion consequence
syntax or keywordtoken vocabulary, lexer, parser/AST, highlighting, positive/refusal specs, Guide/referencenone unless downstream wire meaning also changes
type or semantic rulesupport types, resolver/checker, HIR, MIR/verifier as needed, both-path spec, diagnostics, docsMIR bump if encoded types or instructions change
dynamic operationruntime body/export, MIR instruction or intrinsic, interpreter dispatch, codegen lowering, effect metadata, specsMIR bump; ABI only if host-facing table changes
MIR tag, trap/error code, layout fielddefs, encoding/decoding, verifier, fingerprint, hostile-input tests, every consumerbump MIR format
host table field or signatureABI struct/slots, generated access, every host, oracle host, stale-artifact testsbump host ABI
standard module/API.luc source, embedded roster, specs, host fixture if needed, Library page and coverage auditABI only for a new/changed host primitive
public artifact behaviorCLI, loader/linker, product tests, Guide/Tools/Status, archive and installer smoketag/generator/ABI according to the changed seam

Example: add one dynamic collection operation

  1. SurfaceDecide the signature, element constraints, mutation, result, bounds behavior, and public documentation.
  2. MeaningTeach semantic call selection and HIR recording the exact receiver/result ownership.
  3. ProtocolAdd or reuse a MIR intrinsic, verifier rule, print/encode/decode arm, and format fingerprint.
  4. One semantic bodyImplement the operation in runtime/containers.zig with rollback and trap behavior.
  5. Two callersDispatch it from the interpreter and lower it to the checked runtime export in LLVM.
  6. EvidenceCompare success, boundaries, trap, element ownership, aliasing, and zero live objects on both paths.

Version the representation that changed

MIR format · 62Bump when an older decoder would read bytes with a new meaning, including instructions, intrinsic/type tags, codes, or encoded fields.
Host ABI · 29Bump when the generated artifact ↔ host table contract changes. Internal runtime work leaves this protocol unchanged.
Generator identityComputed automatically from codegen/runtime inputs; it catches implementation changes that leave protocol versions alone.
Release version · 0.18User-facing toolchain label; separate from both compatibility protocols.

Put evidence where its claim lives

A Luce program's observable behavior belongs in src/luce/specs/ and runs on native and oracle paths. Tests of internal structures live beside their implementations. New spec files enter the spec import roster and one owner suite; new language packages enter the language re-export and test rosters.

Documentation is an executable surface

Repository documentation checks execute current luce snippets and validate expected diagnostics and traps. The public site stores separately generated source, MIR, LLVM, and assembly traces; its build validates the trace inventory, source links, internal links, and standard/compiler rosters. Planned syntax remains plain text. A feature is ready when its implementation, tests, examples, and public reference describe the same behavior.

Before calling the change complete

  • Can one stage clearly own each new decision?
  • Do both native and oracle paths reach the same runtime semantic?
  • Do tests cover success, the relevant boundary, diagnostic or trap behavior, and cleanup?
  • Do hostile serialized inputs remain reject-or-run-cleanly total?
  • Did each changed protocol receive its corresponding version update?
  • Do the Guide, Library, status boundary, examples, and editor vocabulary agree?
  • Does the repository gate pass after the focused test lanes?