Surface syntax #
Programs have so far been written as abstract syntax: .div (.mul (.mul (.mul pi pi) hbar) hbar) (.mul (.mul (.mul (lit 2) mass) width) width). That is a
faithful way to describe a calculus and a terrible way to write physics.
This file adds a bracket ⟪ … ⟫ with the usual arithmetic notation inside, so
the same term reads
⟪ (pi * pi * hbar * hbar) / (2 * mass * width * width) ⟫
Identifiers inside the bracket are ordinary Lean names bound to terms, so the
notation composes with definitions rather than replacing them. It is a
convenience layer over Tm and nothing more: no separate parser, no separate
AST, and every guard elsewhere still checks the same core terms.
Elaboration, and where convert gets its annotation #
Tm.convert carries the unit it converts from, because the evaluator must
recover the factor from the term and the unit environment alone. Writing it by
hand would be tedious, though a wrong one is rejected: HasTy.convert demands
the subject at exactly Q u. elabConvert supplies it by running the
verified checker: it
checks the subject, reads the unit off the type it derived, and builds the
annotated term.
This is what makes conversion-as-a-core-constructor tenable. elabConvert
returns the elaborated term together with its derivation, so a surface in
cannot produce a core term the checker would reject: the annotation is not
merely machine-generated but machine-justified.
The bracket #
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- LambdaS.lamS_ = Lean.ParserDescr.node `LambdaS.lamS_ 1024 (Lean.ParserDescr.const `ident)
Instances For
Equations
- LambdaS.lamS__1 = Lean.ParserDescr.node `LambdaS.lamS__1 1024 (Lean.ParserDescr.const `num)
Instances For
Equations
- LambdaS.lamS__2 = Lean.ParserDescr.node `LambdaS.lamS__2 1024 (Lean.ParserDescr.const `scientific)
Instances For
A unit constant, as in ‹meter›. Guillemets rather than a prefix marker
because ! is a legal identifier character in Lean, so u!m would lex as one
name.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A de Bruijn value variable.
Equations
- LambdaS.«lamS%_» = Lean.ParserDescr.node `LambdaS.«lamS%_» 1024 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "%") (Lean.ParserDescr.const `num))
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
A constant rational power, e ^ q with q a Lean-level rational literal.
Tighter than *, so a * b ^ q is a * (b ^ q).
Equations
- LambdaS.«lamS_^_» = Lean.ParserDescr.trailingNode `LambdaS.«lamS_^_» 75 75 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ^ ") (Lean.ParserDescr.cat `term 1024))
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Abstraction, annotated with a Lean-level type.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Component of a vector.
Equations
- LambdaS.lamS_!_ = Lean.ParserDescr.trailingNode `LambdaS.lamS_!_ 80 80 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "!") (Lean.ParserDescr.const `num))
Instances For
Row of a linear map: one ! reads a component out of a vector, two read a
row out of a map.
Equations
- LambdaS.lamS_!!_ = Lean.ParserDescr.trailingNode `LambdaS.lamS_!!_ 80 80 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "!!") (Lean.ParserDescr.const `num))
Instances For
A linear map applied to a vector.
Equations
- LambdaS.«lamS_⊙_» = Lean.ParserDescr.trailingNode `LambdaS.«lamS_⊙_» 80 80 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ⊙ ") (Lean.ParserDescr.cat `lamS 81))
Instances For
Ordinary application.
Equations
- LambdaS.«lamS_◃_» = Lean.ParserDescr.trailingNode `LambdaS.«lamS_◃_» 80 80 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ◃ ") (Lean.ParserDescr.cat `lamS 81))
Instances For
Equations
- LambdaS.«lamS_*_» = Lean.ParserDescr.trailingNode `LambdaS.«lamS_*_» 70 70 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " * ") (Lean.ParserDescr.cat `lamS 71))
Instances For
Equations
- LambdaS.«lamS_/_» = Lean.ParserDescr.trailingNode `LambdaS.«lamS_/_» 70 70 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " / ") (Lean.ParserDescr.cat `lamS 71))
Instances For
Equations
- LambdaS.«lamS_+_» = Lean.ParserDescr.trailingNode `LambdaS.«lamS_+_» 65 65 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " + ") (Lean.ParserDescr.cat `lamS 66))
Instances For
Equations
- LambdaS.«lamS_-_» = Lean.ParserDescr.trailingNode `LambdaS.«lamS_-_» 65 65 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " - ") (Lean.ParserDescr.cat `lamS 66))
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Elaborating a conversion #
Insert a conversion's source annotation by type inference.
The paper abbreviates a conversion to e in v; the core needs convert e u v
with u the unit of e. This runs the verified checker to find it, so the annotation is derived
rather than trusted, and convert's own typing rule still checks it.
Equations
- LambdaS.elabConvert Δ Γ e v = match LambdaS.check Δ Γ e with | some ⟨LambdaS.Ty.Q u, d⟩ => if h : LambdaS.SameDim Δ u v then some ⟨e.convert u v, d.convert h⟩ else none | x => none
Instances For
Elaboration succeeds exactly when the surface syntax is meaningful: the subject is a scalar, and its unit shares the target's dimension.
That is the whole specification, in both directions. There is no companion
theorem saying the elaborated term typechecks, because elabConvert returns
the derivation: a surface in cannot produce a core term the checker would
reject.