docs(grammar): ratify spec block, use spec, refines#44
Merged
Conversation
Adds the language constructs discussed in PR #42's review thread and proven out by the canonical types in PR #43. A `spec` block is a `type` with prose, examples, and reuse semantics — mechanically identical to a `type` after compilation, but prose-rich and shareable across projects. Reads like `policy` (`intent:` + `examples:`); produces a type. Same fixed set of underlying primitives (`int`, `string`, `opaque`, `bool`, `bytes`, `instant`, `decimal`). A consumer brings specs into scope with `use spec X, Y, Z`, optionally pinning required parameters: `use spec Money(currency: USD)`. The toolchain resolves `X` against project-local `spec X` declarations first, then `candy.toml` `[deps]`. Local always shadows imported. A consumer extends or overrides an imported spec with `spec X primitive refines { ... }` — meta-fields not mentioned carry over from the original; the underlying primitive must match. Adds `spec` to the ENTITY word-axis and `refines` as an ENTITY modifier. Both updates land in §"The five word-axes" and the "Block types at a glance" table. The dep-fetch resolver is future tooling — v0.1 is local-only. The grammar is the contract; tooling lands later. Refs #42, #43.
Adds a §spec subsection to the universal block-mapping contract.
Codegen now compiles `spec X primitive { ... }`, `use spec X`, and
`spec X primitive refines { ... }` identically to a `type` block —
the prose and examples produce unit tests the same way `policy`
examples do.
Resolution rules mirror GRAMMAR.md: project-local declarations win,
then `candy.toml` `[deps]`, in declaration order. Unresolved
`use spec` references refuse generation with a clear error.
A spec with a `parameter` field cannot be used as a type until the
parameter is pinned at the consumption site (`use spec X(field: value)`)
or substituted via `refines`. Generation fails otherwise.
Target overlays remain spec-unaware — translation to `type` happens
before the overlay runs.
Refs #42, #43.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ratifies the language constructs discussed in PR #42's review thread
and proven out by the canonical types in PR #43.
The grammar gains three things:
semantics. Reads like `policy` (`intent:` + `examples:`);
produces a type. Same fixed set of underlying primitives.
specs into a file's scope. Supports parameterization via
`use spec Money(currency: USD)`.
imported spec; meta-fields not mentioned carry over.
What changed
ENTITY modifier.
parameters, `use spec` resolution rules, `refines` semantics,
and the compilation contract.
identically to a `type` block before target overlays run.
examples do.
Resolution rules (locked)
For `use spec X`:
The dep-fetch resolver is future tooling — v0.1 is local-only.
What this enables
consumable via `use spec Email, Hash, Token, Password, Phone` and
`use spec Money(currency: USD)`.
each currently carries (separate migration PR — see feat(commons): scaffold commons/ with canonical type specs #43's
"Future structure").
Out of scope
ignores `spec` and `use spec` as unknown top-level keywords; this
PR doesn't change that. Once feat(cli): Rust candy CLI scaffold + candy lint + npm wrapper #42 merges, a follow-up PR teaches
the parser to recognise `spec`/`use spec`/`refines` and adds two
new lint rules: `spec-required-intent` and
`unresolved-use-spec`.
`use spec` works when the dep is on the local filesystem but
`candy install` doesn't exist yet.
this PR and feat(commons): scaffold commons/ with canonical type specs #43 merge, a separate PR migrates each example to
`use spec ...`.
Test plan
changes are internally consistent with the rest of base.md.
and migrates one example as proof-point.
Refs