Lean2Js.Compile
Core to JS, type checking and code generation in one pass #
The translation from Core to JS. This function is what the correctness proofs are about.
Type checking and code generation are a single pass because emitting even one + needs the type of its
operands. Keeping them apart would put the same typing rules on the compiler's trusted base twice.
Lean2Js.Compile.Ctx
sourceEquations
Instances For
Used by
Lean2Js.Compile.scrutName
sourceThe scrutinee that match binds. It starts with __, so it never collides with a user's name.
Equations
- Lean2Js.Compile.scrutName = "__s"
Instances For
Used by
Lean2Js.Compile.wfTy
sourceWhether a type is one this program can talk about: every name is declared, applied to as many arguments as it takes, and every type variable is bound by the declaration the type is written in.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.wfTy p scope Lean2Js.Core.Ty.bool = Except.ok ()
- Lean2Js.Compile.wfTy p scope Lean2Js.Core.Ty.int53 = Except.ok ()
- Lean2Js.Compile.wfTy p scope Lean2Js.Core.Ty.uint32 = Except.ok ()
- Lean2Js.Compile.wfTy p scope Lean2Js.Core.Ty.string = Except.ok ()
- Lean2Js.Compile.wfTy p scope Lean2Js.Core.Ty.bigint = Except.ok ()
- Lean2Js.Compile.wfTy p scope (Lean2Js.Core.Ty.var n) = if scope.contains n = true then Except.ok () else Except.error (toString "unbound type parameter: " ++ toString n)
- Lean2Js.Compile.wfTy p scope t.option = Lean2Js.Compile.wfTy p scope t
- Lean2Js.Compile.wfTy p scope t.array = Lean2Js.Compile.wfTy p scope t
- Lean2Js.Compile.wfTy p scope v.dict = Lean2Js.Compile.wfTy p scope v
- Lean2Js.Compile.wfTy p scope v.dictObj = Lean2Js.Compile.wfTy p scope v
- Lean2Js.Compile.wfTy p scope (ok.result err) = do Lean2Js.Compile.wfTy p scope ok Lean2Js.Compile.wfTy p scope err
- Lean2Js.Compile.wfTy p scope (Lean2Js.Core.Ty.fn params ret) = Except.error "a function type is only allowed as a parameter of a declaration"
Instances For
Used by
Lean2Js.Compile.wfTyArgs
sourceEquations
- Lean2Js.Compile.wfTyArgs p scope [] = Except.ok ()
- Lean2Js.Compile.wfTyArgs p scope (t :: rest) = do Lean2Js.Compile.wfTy p scope t Lean2Js.Compile.wfTyArgs p scope rest
Instances For
Used by
Lean2Js.Compile.wfParamTy
sourceA parameter is the one place a function type may sit. Its own parameters and result go through
wfTy, which rejects a function type, so the types stay first order and the entry check never has to
look inside one.
Equations
- Lean2Js.Compile.wfParamTy p (Lean2Js.Core.Ty.fn params ret) = do params.forM (Lean2Js.Compile.wfTy p []) Lean2Js.Compile.wfTy p [] ret
- Lean2Js.Compile.wfParamTy p x✝ = Lean2Js.Compile.wfTy p [] x✝
Instances For
Used by
Lean2Js.Compile.numericHelper
sourceEquations
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.int53 Lean2Js.Core.BinOp.add a b = some (Lean2Js.Js.Expr.call "__i53" [Lean2Js.Js.Expr.binary "+" a b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.int53 Lean2Js.Core.BinOp.sub a b = some (Lean2Js.Js.Expr.call "__i53" [Lean2Js.Js.Expr.binary "-" a b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.int53 Lean2Js.Core.BinOp.mul a b = some (Lean2Js.Js.Expr.call "__i53" [Lean2Js.Js.Expr.binary "*" a b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.int53 Lean2Js.Core.BinOp.div a b = some (Lean2Js.Js.Expr.call "__i53div" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.int53 Lean2Js.Core.BinOp.mod a b = some (Lean2Js.Js.Expr.call "__i53mod" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.int53 Lean2Js.Core.BinOp.min a b = some (Lean2Js.Js.Expr.call "__min" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.int53 Lean2Js.Core.BinOp.max a b = some (Lean2Js.Js.Expr.call "__max" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.uint32 Lean2Js.Core.BinOp.add a b = some (Lean2Js.Js.Expr.binary ">>>" (Lean2Js.Js.Expr.binary "+" a b) (Lean2Js.Js.Expr.num 0))
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.uint32 Lean2Js.Core.BinOp.sub a b = some (Lean2Js.Js.Expr.binary ">>>" (Lean2Js.Js.Expr.binary "-" a b) (Lean2Js.Js.Expr.num 0))
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.uint32 Lean2Js.Core.BinOp.mul a b = some (Lean2Js.Js.Expr.call "__u32mul" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.uint32 Lean2Js.Core.BinOp.div a b = some (Lean2Js.Js.Expr.call "__u32div" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.uint32 Lean2Js.Core.BinOp.mod a b = some (Lean2Js.Js.Expr.call "__u32mod" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.uint32 Lean2Js.Core.BinOp.min a b = some (Lean2Js.Js.Expr.call "__min" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.uint32 Lean2Js.Core.BinOp.max a b = some (Lean2Js.Js.Expr.call "__max" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.bigint Lean2Js.Core.BinOp.add a b = some (Lean2Js.Js.Expr.binary "+" a b)
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.bigint Lean2Js.Core.BinOp.sub a b = some (Lean2Js.Js.Expr.binary "-" a b)
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.bigint Lean2Js.Core.BinOp.mul a b = some (Lean2Js.Js.Expr.binary "*" a b)
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.bigint Lean2Js.Core.BinOp.div a b = some (Lean2Js.Js.Expr.call "__bigdiv" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.bigint Lean2Js.Core.BinOp.mod a b = some (Lean2Js.Js.Expr.call "__bigmod" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.bigint Lean2Js.Core.BinOp.min a b = some (Lean2Js.Js.Expr.call "__min" [a, b])
- Lean2Js.Compile.numericHelper Lean2Js.Core.Ty.bigint Lean2Js.Core.BinOp.max a b = some (Lean2Js.Js.Expr.call "__max" [a, b])
- Lean2Js.Compile.numericHelper ty op a b = none
Instances For
Used by
Lean2Js.Compile.strUnHelper
sourceEquations
Instances For
Used by
Lean2Js.Compile.strUnResult
sourceEquations
- Lean2Js.Compile.strUnResult Lean2Js.Core.StrUnOp.trim = Lean2Js.Core.Ty.string
- Lean2Js.Compile.strUnResult Lean2Js.Core.StrUnOp.upper = Lean2Js.Core.Ty.string
- Lean2Js.Compile.strUnResult Lean2Js.Core.StrUnOp.lower = Lean2Js.Core.Ty.string
- Lean2Js.Compile.strUnResult Lean2Js.Core.StrUnOp.toInt = Lean2Js.Core.Ty.int53.option
Instances For
Used by
Lean2Js.Compile.strBinHelper
sourceEquations
- Lean2Js.Compile.strBinHelper Lean2Js.Core.StrBinOp.startsWith = "__startsWith"
- Lean2Js.Compile.strBinHelper Lean2Js.Core.StrBinOp.endsWith = "__endsWith"
- Lean2Js.Compile.strBinHelper Lean2Js.Core.StrBinOp.includes = "__includes"
- Lean2Js.Compile.strBinHelper Lean2Js.Core.StrBinOp.split = "__split"
- Lean2Js.Compile.strBinHelper Lean2Js.Core.StrBinOp.indexOf = "__indexOf"
- Lean2Js.Compile.strBinHelper Lean2Js.Core.StrBinOp.join = "__join"
- Lean2Js.Compile.strBinHelper Lean2Js.Core.StrBinOp.repeat = "__repeat"
Instances For
Used by
Lean2Js.Compile.strBinResult
sourceEquations
- Lean2Js.Compile.strBinResult Lean2Js.Core.StrBinOp.startsWith = Lean2Js.Core.Ty.bool
- Lean2Js.Compile.strBinResult Lean2Js.Core.StrBinOp.endsWith = Lean2Js.Core.Ty.bool
- Lean2Js.Compile.strBinResult Lean2Js.Core.StrBinOp.includes = Lean2Js.Core.Ty.bool
- Lean2Js.Compile.strBinResult Lean2Js.Core.StrBinOp.split = Lean2Js.Core.Ty.string.array
- Lean2Js.Compile.strBinResult Lean2Js.Core.StrBinOp.indexOf = Lean2Js.Core.Ty.int53.option
- Lean2Js.Compile.strBinResult Lean2Js.Core.StrBinOp.join = Lean2Js.Core.Ty.string
- Lean2Js.Compile.strBinResult Lean2Js.Core.StrBinOp.repeat = Lean2Js.Core.Ty.string
Instances For
Used by
Lean2Js.Compile.strBinArgTys
sourceWhat each operation takes, rather than two Strings for all of them: an operation whose operands are
not both Strings is then an arm here, not a new form of Core.Expr.
Equations
- Lean2Js.Compile.strBinArgTys Lean2Js.Core.StrBinOp.startsWith = (Lean2Js.Core.Ty.string, Lean2Js.Core.Ty.string)
- Lean2Js.Compile.strBinArgTys Lean2Js.Core.StrBinOp.endsWith = (Lean2Js.Core.Ty.string, Lean2Js.Core.Ty.string)
- Lean2Js.Compile.strBinArgTys Lean2Js.Core.StrBinOp.includes = (Lean2Js.Core.Ty.string, Lean2Js.Core.Ty.string)
- Lean2Js.Compile.strBinArgTys Lean2Js.Core.StrBinOp.split = (Lean2Js.Core.Ty.string, Lean2Js.Core.Ty.string)
- Lean2Js.Compile.strBinArgTys Lean2Js.Core.StrBinOp.indexOf = (Lean2Js.Core.Ty.string, Lean2Js.Core.Ty.string)
- Lean2Js.Compile.strBinArgTys Lean2Js.Core.StrBinOp.join = (Lean2Js.Core.Ty.string.array, Lean2Js.Core.Ty.string)
- Lean2Js.Compile.strBinArgTys Lean2Js.Core.StrBinOp.repeat = (Lean2Js.Core.Ty.string, Lean2Js.Core.Ty.int53)
Instances For
Used by
Lean2Js.Compile.orderSymbol
sourceEquations
Instances For
Used by
Lean2Js.Compile.isOrdered
sourceEquations
Instances For
Used by
Lean2Js.Compile.isScalar
sourceScalars can be compared with ===, but constructor values and arrays would end up compared by
reference.
Equations
- Lean2Js.Compile.isScalar Lean2Js.Core.Ty.bool = true
- Lean2Js.Compile.isScalar Lean2Js.Core.Ty.int53 = true
- Lean2Js.Compile.isScalar Lean2Js.Core.Ty.uint32 = true
- Lean2Js.Compile.isScalar Lean2Js.Core.Ty.string = true
- Lean2Js.Compile.isScalar Lean2Js.Core.Ty.bigint = true
- Lean2Js.Compile.isScalar x✝ = false
Instances For
Used by
Lean2Js.Compile.dictValueTy
sourceThe value type of a dictionary receiver, at whichever of the two spellings it was declared. A
dictionary operation reads this rather than matching on .dict, because the two spellings differ only in
the shape the boundary writes: inside the module both run on the same Map, so both take the same
generated call.
Equations
- Lean2Js.Compile.dictValueTy value.dict = some value
- Lean2Js.Compile.dictValueTy value.dictObj = some value
- Lean2Js.Compile.dictValueTy x✝ = none
Instances For
Used by
Lean2Js.Compile.Head
sourceWhat a value's shape can be tested against at one position: a constructor's tag, or a literal it may equal.
Instances For
Used by
Lean2Js.Compile.instBEqHead
sourceEquations
Used by
Lean2Js.Compile.instBEqHead.beq
sourceEquations
Instances For
Used by
Lean2Js.Compile.signature
sourceEvery head a value of this type can take, each with the fields it carries. none where the values
cannot be enumerated, so nothing short of a wildcard covers them.
Takes the type declarations rather than the program: a declaration is compiled against the prefix before
it, and reading only the types is what lets the proof see that the prefix decides a match the same way
the whole program does.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.signature types t.option = some [(Lean2Js.Compile.Head.ctor "none", []), (Lean2Js.Compile.Head.ctor "some", [("value", t)])]
- Lean2Js.Compile.signature types (ok.result err) = some [(Lean2Js.Compile.Head.ctor "ok", [("value", ok)]), (Lean2Js.Compile.Head.ctor "error", [("error", err)])]
- Lean2Js.Compile.signature types Lean2Js.Core.Ty.bool = some [(Lean2Js.Compile.Head.lit (Lean2Js.Core.Lit.bool true), []), (Lean2Js.Compile.Head.lit (Lean2Js.Core.Lit.bool false), [])]
- Lean2Js.Compile.signature types x✝ = none
Instances For
Used by
Lean2Js.Compile.foldFieldTys
sourceA constructor's fields as a fold's alternative sees them: a field that came round is bound to the answer for it and not to the field, so it is typed at the fold's result.
Equations
Instances For
Used by
Lean2Js.Compile.foldFieldTys_map_fst
sourceRetyping a constructor's fields for a fold's alternative leaves their names alone, so the paths the
alternative reads are the declared field names — the same ones patParts reads.
Used by
Lean2Js.Compile.jsFoldKind
sourceEquations
Instances For
Used by
Lean2Js.Compile.foldSpecOf
sourceWhat __fold is told about the declared type: its constructors by name, each with which of its
fields come round. Read off the same foldKindOf the evaluator walks by.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Compile.fieldTysOf
sourceEquations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.fieldTysOf none h = []
Instances For
Used by
Lean2Js.Compile.headOf
sourceEquations
Instances For
Used by
Lean2Js.Compile.specialize
sourceThe rows left once the first column is known to have head h, with that head's own fields spliced in
front of the rest. A constructor pattern of the wrong width is dropped rather than spliced: the compiler
type checks the patterns before asking about usefulness, so this drops nothing a program can write, and
dropping a row only ever makes the answer "useful" — the answer that reports a match as not
exhaustive.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.specialize h arity [] = []
- Lean2Js.Compile.specialize h arity ([] :: rows) = Lean2Js.Compile.specialize h arity rows
- Lean2Js.Compile.specialize h arity ((Lean2Js.Core.Pat.wild :: ps) :: rows) = (List.replicate arity Lean2Js.Core.Pat.wild ++ ps) :: Lean2Js.Compile.specialize h arity rows
- Lean2Js.Compile.specialize h arity ((Lean2Js.Core.Pat.bind name :: ps) :: rows) = (List.replicate arity Lean2Js.Core.Pat.wild ++ ps) :: Lean2Js.Compile.specialize h arity rows
Instances For
Used by
Lean2Js.Compile.defaultRows
sourceThe rows left once the first column is known to have none of the heads already listed.
Equations
- Lean2Js.Compile.defaultRows [] = []
- Lean2Js.Compile.defaultRows ((Lean2Js.Core.Pat.wild :: ps) :: rows) = ps :: Lean2Js.Compile.defaultRows rows
- Lean2Js.Compile.defaultRows ((Lean2Js.Core.Pat.bind name :: ps) :: rows) = ps :: Lean2Js.Compile.defaultRows rows
- Lean2Js.Compile.defaultRows (row :: rows) = Lean2Js.Compile.defaultRows rows
Instances For
Used by
Lean2Js.Compile.useful
sourceMaranget's usefulness test: is there a value vector that q matches and no row of rows does?
Exhaustiveness is this asked of an all-wildcard q, and an unreachable arm is this asked of that arm
against the arms before it, so one function answers both.
Patterns are type-checked before this runs, so a head that does not belong to its column's type cannot reach here.
budget is what makes this a total function, and a total function is what lets a proof unfold it. Each
step either drops a column or expands a type into one constructor's fields; running out answers true,
which fails an exhaustiveness check rather than passing one.
Equations
Instances For
Used by
Lean2Js.Compile.usefulBudget
sourceHow far useful may descend on the columns it starts with. Each expansion either descends one edge
of the declaration graph, which validateType keeps acyclic, or lands in a type argument the column
carries; tyDescBudget counts the same thing for the entry check.
Equations
- Lean2Js.Compile.usefulBudget types tys = List.foldr (fun (t : Lean2Js.Core.Ty) (acc : Nat) => (t.size + 1) * (types.length + 1) + acc) 1 tys
Instances For
Used by
Lean2Js.Compile.foldHeads
sourceThe constructors of the type a fold walks, each carrying its fields at the types a fold's
alternative reads them: a field that came round is bound to the answer for it. This is the signature the
alternatives are type-checked against, and signature cannot give it — the rebuilt node is the declared
type with every folded field replaced by the answer for it, which is not a type this language writes.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Compile.usefulFold
sourceuseful of one column whose signature is handed over rather than read off its type.
A fold's alternatives are matched against the rebuilt node, so the column they sit at has foldHeads
and not signature. Reading it at the declared type instead is not conservative: two types may declare
constructors of the same name, so a nested pattern typed at the fold's result can name every constructor
the declared type has and still leave a rebuilt node uncovered. Below the one column the types are
ordinary and useful takes over.
Each branch is useful's own step at one column with signature types ty replaced by some heads, so
what it settles is the same thing: a head no row names sends the rows through defaultRows, where only
a row that is wild at the column survives. Where that step leaves no column, it is written as the
.isEmpty useful answers there rather than as a call at a budget that would have to be unfolded.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.usefulFold types heads rows (Lean2Js.Core.Pat.lit l) = (Lean2Js.Compile.specialize (Lean2Js.Compile.Head.lit l) 0 rows).isEmpty
Instances For
Used by
Lean2Js.Compile.Arm
sourceOne lowered match arm: what the generated code tests before taking it, the names it binds and where
it reads each from, and the body under those bindings.
Instances For
Used by
Lean2Js.Compile.objOf
sourceA constructor value, under the key its name is carried under. Agree.encodeValue reads the key the
same way, from the constructor's name alone, so the object the compiler writes and the object the
reference semantics is encoded to are the same one.
Equations
- Lean2Js.Compile.objOf ctor fields = Lean2Js.Js.Expr.objLit ((Lean2Js.Core.keyFor ctor, Lean2Js.Js.Expr.str ctor) :: fields)
Instances For
Used by
Lean2Js.Compile.litJs
sourceA literal pattern is held to the same rules as a literal expression: an Int53 outside the safe range is no more matchable than it is writable.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Compile.patParts
sourceType-checks one pattern against the type at its position and lowers it to the tests the generated code runs and the names it binds, each paired with the path it is read from.
The tests are conjoined left to right by the caller, so an inner test is only reached once the tag it sits under has been confirmed and the path it reads is known to exist.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.patParts types ty path Lean2Js.Core.Pat.wild = Except.ok ([], [])
- Lean2Js.Compile.patParts types ty path (Lean2Js.Core.Pat.bind name) = do Lean2Js.validateIdent "pattern" name Except.ok ([], [(name, path, ty)])
- Lean2Js.Compile.patParts types ty path (Lean2Js.Core.Pat.lit l) = do let __do_lift ← Lean2Js.Compile.litJs ty l Except.ok ([Lean2Js.Js.Expr.binary "===" path __do_lift], [])
Instances For
Used by
Lean2Js.Compile.patPartsList
sourceEquations
Instances For
Used by
Lean2Js.Compile.foldPatParts
sourceThe top of a fold's alternative. Only the fields are typed differently from a match's, and only at
this one level — what a folded field binds is an ordinary type, so anything nested inside reads through
patPartsList unchanged.
Naming the node itself is refused rather than typed: the rebuilt node is the declared type with every field that came round replaced by the answer for it, and that is not a type this language can write.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.foldPatParts types typeName tyArgs result path Lean2Js.Core.Pat.wild = Except.ok ([], [])
- Lean2Js.Compile.foldPatParts types typeName tyArgs result path (Lean2Js.Core.Pat.bind name) = Except.error "a fold's alternative may name a constructor's fields but not the node itself"
- Lean2Js.Compile.foldPatParts types typeName tyArgs result path (Lean2Js.Core.Pat.lit l) = Except.error "a fold is over a declared type, so its alternatives match on constructors"
Instances For
Used by
Lean2Js.Compile.mentions
sourceWhether a type's fields can reach target through the declarations they name. Type arguments are
searched too, so Tree (Tree Int53) is caught the same way a field of type Tree is.
Used by
Lean2Js.Compile.recursiveType
sourceWhether a declared type can reach itself through the types its fields name. Only such a type binds where it is expanded; one that cannot is written out where it is used, exactly as every declared type was before a type could name itself.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Compile.Stack
sourceThe declared types whose expansion the walk is inside, nearest first, at the arguments they were
applied to. A name met again at the same arguments is the knot: it becomes a ref back to the binder
rather than an expansion that would not end.
Equations
Instances For
Used by
Lean2Js.Compile.tyDescIn
sourceExpands a declared type into the shape the generated code checks an argument against. Recursion is
what would make this diverge, and validateType has already rejected it, so no occurs check is needed
here — one by name would reject Paginated (Paginated Int53), which is not recursive.
budget counts the name expansions still allowed. A name expansion substitutes the type arguments into
the field types, so the result can be larger than what was expanded and the structure alone does not
measure the recursion; tyDescBudget is what bounds it from above. Exhausting it is a compile error, so a
budget that turns out to be too small loses the artifact rather than weakening the check it emits.
The constructor and field lists recurse through helpers rather than mapM so that a proof about the
entry check can unfold them.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.tyDescIn p st x✝ Lean2Js.Core.Ty.bool = Except.ok Lean2Js.Js.TyDesc.bool
- Lean2Js.Compile.tyDescIn p st x✝ Lean2Js.Core.Ty.int53 = Except.ok Lean2Js.Js.TyDesc.int53
- Lean2Js.Compile.tyDescIn p st x✝ Lean2Js.Core.Ty.uint32 = Except.ok Lean2Js.Js.TyDesc.uint32
- Lean2Js.Compile.tyDescIn p st x✝ Lean2Js.Core.Ty.string = Except.ok Lean2Js.Js.TyDesc.string
- Lean2Js.Compile.tyDescIn p st x✝ Lean2Js.Core.Ty.bigint = Except.ok Lean2Js.Js.TyDesc.bigint
- Lean2Js.Compile.tyDescIn p st x✝ (Lean2Js.Core.Ty.var n) = Except.error (toString "unbound type parameter: " ++ toString n)
- Lean2Js.Compile.tyDescIn p st x✝ t.option = do let __do_lift ← Lean2Js.Compile.tyDescIn p st x✝ t Except.ok __do_lift.option
- Lean2Js.Compile.tyDescIn p st x✝ t.array = do let __do_lift ← Lean2Js.Compile.tyDescIn p st x✝ t Except.ok __do_lift.array
- Lean2Js.Compile.tyDescIn p st x✝ v.dict = do let __do_lift ← Lean2Js.Compile.tyDescIn p st x✝ v Except.ok __do_lift.dict
- Lean2Js.Compile.tyDescIn p st x✝ (Lean2Js.Core.Ty.fn params ret) = Except.error "a function type has no shape to check at the boundary"
- Lean2Js.Compile.tyDescIn p st x✝ v.dictObj = do let __do_lift ← Lean2Js.Compile.tyDescIn p st x✝ v Except.ok __do_lift.dictObj
Instances For
Used by
Lean2Js.Compile.tyDescAlts
sourceEquations
Instances For
Used by
Lean2Js.Compile.tyDescFields
sourceEquations
Instances For
Used by
Lean2Js.Compile.tyDesc
sourceThe descriptor a type crosses the boundary as: expanded from nothing, so the only binders in it are the ones the types themselves put there.
Equations
- Lean2Js.Compile.tyDesc p budget ty = Lean2Js.Compile.tyDescIn p [] budget ty
Instances For
Used by
Lean2Js.Compile.tyDescBudget
sourceEvery name expansion either descends one edge of the declaration graph, which validateType keeps
acyclic and so is at most p.types.length long, or lands in a type argument, of which the type carries at
most sizeOf ty.
Instances For
Used by
Lean2Js.Compile.compileExpr
sourceEquations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.compileExpr p ctx (Lean2Js.Core.Expr.lit (Lean2Js.Core.Lit.bool b)) = Except.ok (Lean2Js.Js.Expr.bool b, Lean2Js.Core.Ty.bool)
- Lean2Js.Compile.compileExpr p ctx (Lean2Js.Core.Expr.lit (Lean2Js.Core.Lit.uint32 n)) = Except.ok (Lean2Js.Js.Expr.num ↑n.toNat, Lean2Js.Core.Ty.uint32)
- Lean2Js.Compile.compileExpr p ctx (Lean2Js.Core.Expr.lit (Lean2Js.Core.Lit.str s)) = Except.ok (Lean2Js.Js.Expr.str s, Lean2Js.Core.Ty.string)
- Lean2Js.Compile.compileExpr p ctx (Lean2Js.Core.Expr.lit (Lean2Js.Core.Lit.bigint i)) = Except.ok (Lean2Js.Js.Expr.bigLit i, Lean2Js.Core.Ty.bigint)
- Lean2Js.Compile.compileExpr p ctx (Lean2Js.Core.Expr.noneE elem) = do Lean2Js.Compile.wfTy p [] elem Except.ok (Lean2Js.Compile.objOf "none" [], elem.option)
Instances For
Used by
Lean2Js.Compile.compileExpr.chain
sourceEquations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.compileExpr.chain [] = Lean2Js.Js.Expr.bool false
- Lean2Js.Compile.compileExpr.chain [a] = Lean2Js.Compile.compileExpr.apply a
Instances For
Used by
Lean2Js.Compile.compileExpr.apply
sourceEquations
Instances For
Used by
Lean2Js.Compile.compileArgs
sourceEquations
- Lean2Js.Compile.compileArgs p ctx [] = Except.ok []
- Lean2Js.Compile.compileArgs p ctx (e :: rest) = do let head ← Lean2Js.Compile.compileExpr p ctx e let tail ← Lean2Js.Compile.compileArgs p ctx rest Except.ok (head :: tail)
Instances For
Used by
Lean2Js.Compile.compileValues
sourceEquations
- Lean2Js.Compile.compileValues p ctx [] = Except.ok []
- Lean2Js.Compile.compileValues p ctx ((fst, e) :: rest) = do let head ← Lean2Js.Compile.compileExpr p ctx e let tail ← Lean2Js.Compile.compileValues p ctx rest Except.ok (head :: tail)
Instances For
Used by
Lean2Js.Compile.compileAlts
sourceEquations
Instances For
Used by
Lean2Js.Compile.compileFoldAlts
sourceEquations
Instances For
Used by
Lean2Js.Compile.compileFinish
sourceUnfolds a tail let into a const statement. A let appearing mid-expression has to be wrapped in
an immediately invoked arrow to preserve evaluation order, but wrapping the lets lined up at the head of
a function as well would make the output unreadable.
Equations
- Lean2Js.Compile.compileFinish p ctx e acc = do let __x ← Lean2Js.Compile.compileExpr p ctx e match __x with | (je, te) => Except.ok (acc.reverse ++ [Lean2Js.Js.Stmt.ret je], te)
Instances For
Used by
Lean2Js.Compile.compileBody
sourceEquations
- One or more equations did not get rendered due to their size.
- Lean2Js.Compile.compileBody p ctx e acc = Lean2Js.Compile.compileFinish p ctx e acc
Instances For
Used by
Lean2Js.Compile.rawParam
sourceThe name an exported function takes its argument under, before the entry check hands it to the body under the declared name. The reserved prefix is what keeps it out of reach of a declared name.
Equations
- Lean2Js.Compile.rawParam i = toString "__p" ++ toString i
Instances For
Used by
Lean2Js.Compile.rawParams
sourceEquations
- Lean2Js.Compile.rawParams x✝ [] = []
- Lean2Js.Compile.rawParams x✝ (head :: rest) = Lean2Js.Compile.rawParam x✝ :: Lean2Js.Compile.rawParams (x✝ + 1) rest
Instances For
Used by
Lean2Js.Compile.paramChecks
sourceThe const per parameter that an exported function opens with: the declared name bound to the raw
argument, checked against the declared type unless the type is a function, which has no shape to check.
Recursing rather than zipIdx.mapM for the reason tyDesc does: a proof about the entry has to unfold
this to see what the body runs under.
Equations
Instances For
Used by
Lean2Js.Compile.declSigRest
sourceEquations
- Lean2Js.Compile.declSigRest [] = ""
- Lean2Js.Compile.declSigRest (param :: rest) = ", " ++ param.name ++ " : " ++ param.ty.render ++ Lean2Js.Compile.declSigRest rest
Instances For
Used by
Lean2Js.Compile.declSig
sourceThe parameter list as it appears in the doc comment. String.intercalate walks an accumulator, which
a proof about the characters the doc contains cannot unfold.
Equations
- Lean2Js.Compile.declSig [] = ""
- Lean2Js.Compile.declSig (param :: rest) = param.name ++ " : " ++ param.ty.render ++ Lean2Js.Compile.declSigRest rest
Instances For
Used by
Lean2Js.Compile.paramIdents
sourceThe arguments the entry hands the body: every parameter under its declared name, which is what the checks above it have just bound.
Equations
- Lean2Js.Compile.paramIdents [] = []
- Lean2Js.Compile.paramIdents (param :: rest) = Lean2Js.Js.Expr.ident param.name :: Lean2Js.Compile.paramIdents rest
Instances For
Used by
Lean2Js.Compile.retWalk
sourceThe result, read back out through the type the declaration was declared to return. A dictionary declared to cross as a plain object is the only node the walk moves, so where the expanded descriptor reaches none nothing is emitted and the entry is byte-for-byte what it is without a walk.
Equations
Instances For
Used by
Lean2Js.Compile.compileDecl
sourceA declaration becomes two functions: the body, which is where the compiled expression goes and which
every call from inside the package lands on, and the entry, which checks its arguments and hands them to
the body under their declared names. The entry is what a consumer imports and what decl_correct,
decl_traps and decl_refuses are statements about; the split is what keeps a call from inside the
package from walking an argument that is already good.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Compile.keyDeclared
sourceA constructor is carried under the key its own type declares. Written as its own step rather than
as an if in the walk below so that the reading can be taken back out of a validated program.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Compile.validateType
sourceThe key a type's constructors are told apart by has to stay free as a field name, and it has to be the key the constructor's name is carried under: a value carries that name and not the type it came from, so two types declaring a constructor of the same name cannot key it differently.
A type naming itself is not refused here. tyDescIn ties the knot where the name comes round again at the
same arguments; a type whose expansion has no such fixed point — one applied to a bigger argument each
time round — runs out of budget instead, and is refused by name.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Compile.compileDecls
sourceEquations
Instances For
Used by
Lean2Js.Compile.compileProgram
sourceA declaration is compiled against the whole program and callsPrecede is what keeps a function from
calling itself or a later one. That is what keeps nontermination out of the subset: eval's fuel bounds
the proof, not the language. Traversal is map / filter / reduce, which are syntax and cannot
recur.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Compile.compileDeclared
sourceThe module a program compiles to under the reading its own types declare. compileProgram takes a
reading as given, because what is proved about it holds for any; this is where a program's own one is
installed, and where a program whose keys are no reading at all is refused.
Equations
- Lean2Js.Compile.compileDeclared p = do let _keys ← p.discriminators? Lean2Js.Compile.compileProgram p