Surface syntax #
Programs have so far been written as abstract syntax: .div (.mul (.mul pi pi) (.mul hbar hbar)) (.mul (.mul (lit 2) mass) (.mul 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. Making the user write it would be both tedious
and unsafe. 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.