Documentation
¶
Overview ¶
Package core holds Rune's locally-nameless core: the elaborated term language (Tm), the glued NbE value domain (Val, shape only in Phase 0), and structural Merkle hashing.
Three representations, one rule (see CLAUDE.md): the surface is named, the core is locally nameless, and the pretty-printer turns core back into named surface for display. Bound variables are de Bruijn indices; references to top-level definitions are content hashes (Ref), never names.
Phase 0 implements only the term shapes, name resolution's target, and hashing. Type checking, normalization, conversion, and type-directed elaboration are Phase 1 and MUST NOT appear here.
Index ¶
- type Ann
- type App
- type Cast
- type CtorSig
- type DataInfo
- type ElimSig
- type Env
- type Eq
- type EqStratum
- type Globals
- type Hash
- type Icit
- type Lam
- type Let
- type Machine
- func (m *Machine) Apply(fn, arg Val) Val
- func (m *Machine) ApplyIcit(fn, arg Val, icit Icit) Val
- func (m *Machine) Conv(lvl int, a, b Val) bool
- func (m *Machine) DepList() []Hash
- func (m *Machine) Eval(env Env, t Tm) Val
- func (m *Machine) EvalCast(a, b, p, x Val) Val
- func (m *Machine) EvalEq(ty, l, r Val) Val
- func (m *Machine) EvalSubst(a, x, y, prf, pmot, px Val) Val
- func (m *Machine) Force(v Val) Val
- func (m *Machine) Normalize(t Tm) Tm
- func (m *Machine) NormalizeUnfold(t Tm) Tm
- func (m *Machine) Quote(lvl int, v Val) Tm
- func (m *Machine) QuoteUnfold(lvl int, v Val) Tm
- func (m *Machine) Sub(lvl int, a, b Val) bool
- type Meta
- type MetaSolver
- type NApp
- type NCast
- type NMeta
- type NRef
- type NSubst
- type NVar
- type Neutral
- type Pi
- type Prop
- type Qty
- type Ref
- type Refl
- type Scope
- type Subst
- type Tm
- type Univ
- type VEq
- type VLam
- type VNeu
- type VPi
- type VProp
- type VRefl
- type VU
- type Val
- type Var
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Ann ¶
Ann is a type annotation (Term : Ty). Phase 0 keeps annotations in the core so that the surface round-trips; Phase 1 elaboration will consume them.
type Cast ¶ added in v1.0.0
Cast transports a term along a type equality: Cast A B P X : B, given A B : U, P : Eq U A B, X : A. Cast computes on the structure of A and B and never inspects P (proof irrelevance).
type CtorSig ¶ added in v1.0.0
CtorSig describes one constructor's arguments: its arity (after the data type's parameters) and which of those arguments are recursive occurrences of the datatype (the positions that get induction hypotheses).
type DataInfo ¶ added in v1.0.0
DataInfo gives the evaluator the datatype roles of stored hashes (Phase 4). store.Store implements it. Nil means no datatypes (ι never fires).
type ElimSig ¶ added in v1.0.0
ElimSig describes an eliminator: the datatype it eliminates, the number of datatype parameters, and the constructor signatures in declaration order. The eliminator's argument layout is
elim p1..pk motive case1..casen scrutinee
and the ι-rule fires when the scrutinee forces to a saturated constructor.
type Env ¶ added in v1.0.0
type Env []Val
Env is the evaluation environment: index 0 is the innermost binder's value, matching Var's de Bruijn indices.
type Eq ¶ added in v1.0.0
Eq is the observational equality type former: Eq Ty L R, the proposition that L and R are equal elements of Ty. It computes on the structure of Ty (Eq over a function type unfolds to pointwise equality — funext is a REDUCTION, not an axiom). Lives in Prop.
type EqStratum ¶ added in v1.0.0
type EqStratum interface {
// EvalEq computes the value of Eq ty l r, applying the stratum's
// type-directed reductions (e.g. funext: Eq over a Pi unfolds pointwise).
EvalEq(m *Machine, ty, l, r Val) Val
// EvalCast computes cast a b p x, never inspecting p.
EvalCast(m *Machine, a, b, p, x Val) Val
// EvalSubst computes subst a x y prf P px, never inspecting prf.
EvalSubst(m *Machine, a, x, y, prf, pmot, px Val) Val
}
EqStratum is the EQUALITY STRATUM's reduction hooks (Phase 3). The conversion checker and evaluator call these when they reach an equality former; the one v1 implementation is equality.Observational (Pujet–Tabareau). Nil means the formers are stuck (pre-Phase-3 behavior).
type Globals ¶ added in v1.0.0
Globals is eval/conversion's view of the definition store. store.Store satisfies it. TypeOf is pure — a referenced definition's type is part of the content hash any referencing term already carries, so reading it logs nothing. Unfold is the body gateway; every Machine access to it is logged.
type Hash ¶
type Hash [32]byte
Hash is a content hash: the Merkle digest of a piece of elaborated core.
Hashing uses BLAKE3 (goforge.dev/blake3sum); blake3.New(32, nil) is an unkeyed 256-bit streaming hasher implementing hash.Hash. The digest width and algorithm are an implementation detail behind this type — changing them changes every content hash, which is what the preimage tag (hashFormatVersion) versions.
func HashTerm ¶
HashTerm computes the structural Merkle hash of a core term.
THE STANDING RULE (CLAUDE.md): hashing operates structurally on the core term and MUST NEVER call eval, normalize, or a future conversion routine. A definition's identity is its SYNTAX, never its meaning modulo conversion. Because the core is de Bruijn, alpha-equivalent terms are literally equal here and therefore hash equal; Scope.Name is a pretty-printing hint and is deliberately not fed to the digest.
type Icit ¶ added in v1.0.0
type Icit byte
Icit is the plicity of a binder or application: explicit (the default) or implicit (Phase 2; surface syntax {x : A}). Implicit arguments are inserted by elaboration, so the core is always fully applied and plicity is part of a term's identity (it is hashed).
type Let ¶
Let is let x = Val in Body, with an optional annotation Ty (nil when absent). Body is a Scope binding x. The bound value is in-band: it lives in the term and is part of the term's content hash (it is not a global definition, so it is not reached through store.Unfold).
type Machine ¶ added in v1.0.0
type Machine struct {
G Globals
Deps map[Hash]struct{}
// Metas, when non-nil, resolves metavariable solutions (Phase 2). It is set
// only during elaboration; pure core runs (the cached checker judgment, REPL
// normalization) operate on zonked, meta-free terms and leave it nil.
Metas MetaSolver
// EqS, when non-nil, supplies the equality stratum's reduction rules.
EqS EqStratum
// Data, when non-nil, supplies datatype roles for ι-reduction.
Data DataInfo
}
Machine carries one checking/evaluation run: the store view and the write-only dependency log (the ConvM accumulator of the proof-cache semantics). A Machine is created per judgment run — its Deps, read after the run, are exactly the definitional dependency set U the certificate is keyed on. Machines and the values they produce must not be shared across runs, or a memoized forced thunk would swallow a later run's dependency.
func NewMachine ¶ added in v1.0.0
NewMachine returns a Machine over g with an empty dependency log.
func (*Machine) Apply ¶ added in v1.0.0
Apply applies fn to an explicit arg (the common external entry point).
func (*Machine) Conv ¶ added in v1.0.0
Conv reports whether a and b are definitionally equal (βδη) at level lvl.
func (*Machine) DepList ¶ added in v1.0.0
DepList returns the logged dependency set as an unordered slice.
func (*Machine) Eval ¶ added in v1.0.0
Eval evaluates t in env. Precondition: t is well-scoped in env (every Var index is < len(env)) and well-typed; eval of ill-typed core may panic (the checker runs first).
func (*Machine) EvalCast ¶ added in v1.0.0
EvalCast applies the equality stratum's cast reduction, or leaves it stuck.
func (*Machine) EvalEq ¶ added in v1.0.0
EvalEq applies the equality stratum's Eq reduction, or leaves the type stuck.
func (*Machine) EvalSubst ¶ added in v1.0.0
EvalSubst applies the equality stratum's transport, or leaves it stuck.
func (*Machine) Force ¶ added in v1.0.0
Force unfolds a glued neutral to its delta-reduced value, repeatedly, logging each unfolded definition (forcing the thunk is store.Unfold). A flexible neutral whose meta is unsolved is returned as-is (its Unfold yields itself). Non-neutrals and neutrals with nothing to unfold are returned as-is.
func (*Machine) Normalize ¶ added in v1.0.0
Normalize is quote ∘ eval on a closed term: β-normal, references kept folded.
func (*Machine) NormalizeUnfold ¶ added in v1.0.0
NormalizeUnfold is Normalize with full δ-unfolding of definition references.
func (*Machine) Quote ¶ added in v1.0.0
Quote reads v back into a term. lvl is the number of binders in scope: a free variable at level l quotes to index lvl-1-l.
func (*Machine) QuoteUnfold ¶ added in v1.0.0
QuoteUnfold is Quote after forcing every glued unfolding: full βδ-normal form. Each forced definition is logged, like any force. It terminates on the acyclic stores Phase 1 admits (recursive definitions arrive with Phase-4 totality).
func (*Machine) Sub ¶ added in v1.0.0
Sub reports a <: b — definitional conversion extended with cumulativity: Prop <: U, and function types are covariant in their codomain (domains stay invariant, which is sound and keeps the relation decidable without antisymmetry games). Used where a Prop-valued thing is supplied at a U-valued expectation (e.g. Prop-valued eliminator motives).
type Meta ¶ added in v1.0.0
type Meta struct {
ID int
}
Meta is an unsolved metavariable, identified within one elaboration run. It is ELABORATION-INTERNAL: a meta must never reach the store or the hash boundary — HashTerm panics on it, and the session asserts elaborated definitions are meta-free (zonked) before storing.
type MetaSolver ¶ added in v1.0.0
MetaSolver resolves a metavariable to its solution value, if solved.
type NCast ¶ added in v1.0.0
type NCast struct {
A, B, P, X Val
}
NCast is a stuck cast: transport along an equality whose endpoint types are not yet concrete enough to reduce. P is carried for quotation only — conversion compares A, B, and X and SKIPS P (proof irrelevance).
type NMeta ¶ added in v1.0.0
type NMeta struct {
ID int
}
NMeta is a stuck metavariable head (Phase 2, elaboration-internal). A neutral headed by an NMeta is FLEXIBLE: solving the meta can wake it. The Machine's Metas solver is consulted when forcing.
type NRef ¶
type NRef struct {
Hash Hash
}
NRef is a stuck reference to a top-level definition (one whose body has not been unfolded on the fast path).
type NSubst ¶ added in v1.0.0
type NSubst struct {
A, X, Y, Prf, P, Px Val
}
NSubst is a stuck Leibniz transport: its equality's endpoints are not yet convertible. Prf is carried for quotation only; conversion skips it.
type NVar ¶
type NVar struct {
Lvl int
}
NVar is a free variable, identified by de Bruijn LEVEL (not index) so the head is stable as the value is reused under deeper binders.
type Neutral ¶
type Neutral interface {
// contains filtered or unexported methods
}
Neutral is the un-unfolded spine of a stuck computation: a head (a free variable at a de Bruijn level, or a definition reference) under a stack of eliminators.
type Pi ¶
Pi is the dependent function type (x : Dom) -> Cod (explicit) or {x : Dom} -> Cod (implicit). Cod is a Scope: it binds one variable (the argument), reachable as Var{0} inside it.
type Prop ¶ added in v1.0.0
type Prop struct{}
Prop is the universe of propositions (Phase 3, the observational equality stratum): proof-irrelevant, with Prop : U. Equality types live here.
type Qty ¶ added in v1.0.0
type Qty byte
Qty is a binder's usage annotation, drawn from the 0/1/ω semiring the quantity stratum supplies (Phase 5). The zero value is QMany (ω, unrestricted) so unannotated binders cost nothing. The 0-fragment is the erasure boundary codegen reads. Quantities are part of a Pi type's identity and are hashed.
type Ref ¶
type Ref struct {
Hash Hash
}
Ref is a reference to a top-level definition, named by the content hash of that definition's elaborated core (a Pitts constant). References are by hash, never by name, so the core carries no nominal dependency.
type Refl ¶ added in v1.0.0
type Refl struct {
Tm Tm
}
Refl is the reflexivity proof: Refl x : Eq A x x. Proofs are definitionally irrelevant; Refl's payload exists for type inference, not for computation.
type Scope ¶
Scope is the body of a binder. Under locally-nameless representation a Scope is just a term with one additional bound variable in scope (reachable as Var{0}).
Name is a pretty-printing hint ONLY. It is NOT part of a term's identity and is never hashed: alpha-equivalent terms are de Bruijn-equal and therefore hash equal. The pretty-printer may freshen Name to avoid capture.
type Subst ¶ added in v1.0.0
Subst is Leibniz transport along an equality (Phase 4's induction workhorse): Subst A X Y Prf P Px : P Y, given X Y : A, Prf : Eq A X Y, P : A -> s, Px : P X. It computes to Px when X ≡ Y (in particular at refl) and never inspects Prf.
type Tm ¶
type Tm interface {
// contains filtered or unexported methods
}
Tm is an elaborated core term. It is a sealed interface: the unexported marker method isTm makes the constructor set closed, so every consumer matches by type switch and the compiler flags an unhandled case. This is the one AST encoding used throughout Rune; do not mix in another.
type Univ ¶
type Univ struct {
Lvl int
}
Univ is a universe U_Lvl in the predicative hierarchy (Phase 6): U_i : U_{i+1}, with cumulativity U_i <: U_j for i ≤ j supplied by Sub. The surface writes `U` for U_0 and `U1`, `U2`, … for higher levels. The type-in-type stance is gone.
type VEq ¶ added in v1.0.0
type VEq struct {
Ty, L, R Val
}
VEq is a STUCK observational equality type: the stratum's EvalEq could not reduce it further (Ty is not a function type, and not enough structure is known). Values of a VEq type are proofs and are definitionally irrelevant.
type VLam ¶
VLam is a lambda value, carrying its meaning as a Go closure. Name is a display hint only, like VPi.Name.
type VNeu ¶
VNeu is a neutral value: a variable or definition reference stuck under eliminators it cannot yet reduce.
Spine is the un-unfolded neutral (the fast-path representative). Unfold is the lazy unfolding: forcing it is store.Unfold and is where the proof-cache dependency is logged. Phase 1 supplies real thunks; Phase 0 fixes the shape only.
type VPi ¶
VPi is a dependent function type value (x : Dom) -> Cod. Cod is a Go closure: the NbE meaning function. Name is a pretty-printing hint for the binder, like Scope.Name — never part of identity, never hashed (quote drops it into a Scope).
type VProp ¶ added in v1.0.0
type VProp struct{}
VProp is the universe of propositions as a value (Phase 3).
type VRefl ¶ added in v1.0.0
type VRefl struct {
V Val
}
VRefl is the reflexivity proof as a value. Its payload is carried for quotation only; conversion never inspects it (proof irrelevance).
type Val ¶
type Val interface {
// contains filtered or unexported methods
}
Val is the glued NbE value domain. SHAPE ONLY in Phase 0: the constructors are fixed here so the Phase-1 evaluator and quoter have a target, but eval and quote are NOT implemented.
"Glued" (after smalltt): a neutral value carries both its un-unfolded spine AND a lazy unfolding. Conversion takes a fast syntactic path over spines and forces the lazy unfolding only on mismatch, so errors print near the source the user wrote.
The coincidence that earns its keep (see ref_docs/rune-proof-cache-semantics.md): forcing a neutral's lazy unfolding is the SAME operation as store.Unfold. The proof-cache dependency log hooks exactly there — the fast path compares spines and logs nothing; forcing logs the unfolded definition's hash. The instrumentation rides on the machinery built for speed. This is on purpose; keep them coincident.