Lean Compiler Normal Form (LCNF) #
It is based on the A-normal form, and the approach described in the paper Compiling without continuations.
- fvarId : Lean.FVarId
- binderName : Lean.Name
- type : Lean.Expr
- borrow : Bool
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedParam = { default := { fvarId := default, binderName := default, type := default, borrow := default } }
Equations
Equations
- Lean.Compiler.LCNF.Param.toExpr p = Lean.Expr.fvar p.fvarId
- alt: {Code : Type} → Lean.Name → Array Lean.Compiler.LCNF.Param → Code → Lean.Compiler.LCNF.AltCore Code
- default: {Code : Type} → Code → Lean.Compiler.LCNF.AltCore Code
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedAltCore = { default := Lean.Compiler.LCNF.AltCore.alt default default default }
- fvarId : Lean.FVarId
- binderName : Lean.Name
- type : Lean.Expr
- value : Lean.Expr
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedLetDecl = { default := { fvarId := default, binderName := default, type := default, value := default } }
Equations
- fvarId : Lean.FVarId
- binderName : Lean.Name
- params : Array Lean.Compiler.LCNF.Param
- type : Lean.Expr
- value : Code
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedFunDeclCore = { default := { fvarId := default, binderName := default, params := default, type := default, value := default } }
Equations
- Lean.Compiler.LCNF.FunDeclCore.getArity decl = Array.size decl.params
- typeName : Lean.Name
- resultType : Lean.Expr
- discr : Lean.FVarId
- alts : Array (Lean.Compiler.LCNF.AltCore Code)
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedCasesCore = { default := { typeName := default, resultType := default, discr := default, alts := default } }
- let: Lean.Compiler.LCNF.LetDecl → Lean.Compiler.LCNF.Code → Lean.Compiler.LCNF.Code
- fun: Lean.Compiler.LCNF.FunDeclCore Lean.Compiler.LCNF.Code → Lean.Compiler.LCNF.Code → Lean.Compiler.LCNF.Code
- jp: Lean.Compiler.LCNF.FunDeclCore Lean.Compiler.LCNF.Code → Lean.Compiler.LCNF.Code → Lean.Compiler.LCNF.Code
- jmp: Lean.FVarId → Array Lean.Expr → Lean.Compiler.LCNF.Code
- cases: Lean.Compiler.LCNF.CasesCore Lean.Compiler.LCNF.Code → Lean.Compiler.LCNF.Code
- return: Lean.FVarId → Lean.Compiler.LCNF.Code
- unreach: Lean.Expr → Lean.Compiler.LCNF.Code
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedCode = { default := Lean.Compiler.LCNF.Code.jmp default default }
Return the constructor names that have an explicit (non-default) alternative.
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.Compiler.LCNF.instInhabitedCodeDecl = { default := Lean.Compiler.LCNF.CodeDecl.let default }
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.Compiler.LCNF.attachCodeDecls decls code = Lean.Compiler.LCNF.attachCodeDecls.go decls (Array.size decls) code
Equations
- One or more equations did not get rendered due to their size.
Equations
Equations
Equations
- Lean.Compiler.LCNF.AltCore.getCode _fun_discr = match _fun_discr with | Lean.Compiler.LCNF.AltCore.default k => k | Lean.Compiler.LCNF.AltCore.alt ctorName params k => k
Equations
- Lean.Compiler.LCNF.AltCore.forCodeM alt f = match alt with | Lean.Compiler.LCNF.AltCore.default k => f k | Lean.Compiler.LCNF.AltCore.alt ctorName params k => f k
Low-level update Param function. It does not update the local context.
Consider using Param.update : Param → Expr → CompilerM Param if you want the local context
to be updated.
Low-level update LetDecl function. It does not update the local context.
Consider using LetDecl.update : LetDecl → Expr → Expr → CompilerM LetDecl if you want the local context
to be updated.
Low-level update FunDecl function. It does not update the local context.
Consider using FunDecl.update : LetDecl → Expr → Array Param → Code → CompilerM FunDecl if you want the local context
to be updated.
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.Compiler.LCNF.AltCore.mapCodeM alt f = do let a ← f (Lean.Compiler.LCNF.AltCore.getCode alt) pure (Lean.Compiler.LCNF.AltCore.updateCode alt a)
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.Compiler.LCNF.Code.isFun _fun_discr = match _fun_discr with | Lean.Compiler.LCNF.Code.fun decl k => true | x => false
Equations
- Lean.Compiler.LCNF.Code.isReturnOf _fun_discr _fun_discr = match _fun_discr, _fun_discr with | Lean.Compiler.LCNF.Code.return fvarId, fvarId' => fvarId == fvarId' | x, x_1 => false
Equations
Return true iff c.size ≤ n
Equations
- Lean.Compiler.LCNF.Code.sizeLe c n = match EStateM.run (Lean.Compiler.LCNF.Code.sizeLe.go n c) 0 with | EStateM.Result.ok a a_1 => true | EStateM.Result.error a a_1 => false
Equations
The name of the declaration from the
Environmentit came fromname : Lean.NameUniverse level parameter names.
The type of the declaration. Note that this is an erased LCNF type instead of the fully dependent one that might have been the original type of the declaration in the
Environment.type : Lean.ExprParameters.
params : Array Lean.Compiler.LCNF.ParamThe body of the declaration, usually changes as it progresses through compiler passes.
value : Lean.Compiler.LCNF.CodeWe set this flag to true during LCNF conversion. When we receive a block of functions to be compiled, we set this flag to
trueif there is an application to the function in the block containing it. This is an approximation, but it should be good enough because in the frontend, we invoke the compiler with blocks of strongly connected components only. We use this information to control inlining.recursive : BoolWe set this flag to false during LCNF conversion if the Lean function associated with this function was tagged as partial or unsafe. This information affects how static analyzers treat function applications of this kind. See
DefinitionSafety.partialandunsafefunctions may not be terminating, but Lean functions terminate, and some static analyzers exploit this fact. So, we use the following semantics. Suppose whe hav a (large) natural numberC. We consider a nondeterministic model for computation of Lean expressions as follows: Each call to a partial/unsafe function uses up one "recursion token". Prior to consumingCrecursion tokens all partial functions must be called as normal. Once the model has used upCrecursion tokens, a subsequent call to a partial function has the following nondeterministic options: it can either call the function again, or return any value of the target type (even a noncomputable one). Larger values ofCyield less nondeterminism in the model, but even the intersection of all choices ofCyields nondeterminism wheredef loop : A := loopreturns any value of typeA. The compiler fixes a choice forC. This is a fixed constant greater than 2^2^64, which is allowed to be compiler and architecture dependent, and promises that it will produce an execution consistent with every possible nondeterministic outcome of theC-model. In the event that different nondeterministic executions disagree, the compiler is required to exhaust resources or output a looping computation.safe : Bool
Declaration being processed by the Lean to Lean compiler passes.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Equations
Equations
- Lean.Compiler.LCNF.Decl.size decl = Lean.Compiler.LCNF.Code.size decl.value
Equations
- Lean.Compiler.LCNF.Decl.getArity decl = Array.size decl.params
Return some i if decl is of the form
def f (a_0 ... a_i ...) :=
...
cases a_i
| ...
| ...
That is, f is a sequence of declarations followed by a cases on the parameter i.
We use this function to decide whether we should inline a declaration tagged with
[inlineIfReduce] or not.
Equations
- Lean.Compiler.LCNF.Decl.isCasesOnParam? decl = Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl decl.value
Equations
- Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl (Lean.Compiler.LCNF.Code.let decl_1 k) = Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl k
- Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl (Lean.Compiler.LCNF.Code.jp decl_1 k) = Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl k
- Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl (Lean.Compiler.LCNF.Code.fun decl_1 k) = Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl k
- Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl (Lean.Compiler.LCNF.Code.cases c) = Array.findIdx? decl.params fun param => param.fvarId == c.discr
- Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl code = none
Equations
- Lean.Compiler.LCNF.Decl.instantiateTypeLevelParams decl us = Lean.Expr.instantiateLevelParams decl.type decl.levelParams us
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.Compiler.LCNF.Decl.instantiateValueLevelParams decl us = Lean.Compiler.LCNF.Decl.instantiateValueLevelParams.instCode decl us decl.value
Equations
- Lean.Compiler.LCNF.Decl.instantiateValueLevelParams.instExpr decl us e = Lean.Expr.instantiateLevelParams e decl.levelParams us
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
Equations
Traverse the given block of potentially mutually recursive functions
and mark a declaration f as recursive if there is an application
f ... in the block.
This is an overapproximation, and relies on the fact that our frontend
computes strongly connected components.
See comment at recursive field.
Equations
- One or more equations did not get rendered due to their size.
Equations
- Lean.Compiler.LCNF.markRecDecls.go decls = Array.forM (fun decl => Lean.Compiler.LCNF.markRecDecls.visit decls decl.value) decls 0 (Array.size decls)