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 : Lake.Name
- type : Lean.Expr
- borrow : Bool
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedParam = { default := { fvarId := default, binderName := default, type := default, borrow := default } }
Equations
Equations
- p.toExpr = Lean.Expr.fvar p.fvarId
Instances For
- alt: {Code : Type} → Lake.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 }
- natVal: Nat → Lean.Compiler.LCNF.LitValue
- strVal: String → Lean.Compiler.LCNF.LitValue
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedLitValue = { default := Lean.Compiler.LCNF.LitValue.natVal default }
Equations
Equations
- x.toExpr = match x with | Lean.Compiler.LCNF.LitValue.natVal v => Lean.Expr.lit (Lean.Literal.natVal v) | Lean.Compiler.LCNF.LitValue.strVal v => Lean.Expr.lit (Lean.Literal.strVal v)
Instances For
- erased: Lean.Compiler.LCNF.Arg
- fvar: Lean.FVarId → Lean.Compiler.LCNF.Arg
- type: Lean.Expr → Lean.Compiler.LCNF.Arg
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedArg = { default := Lean.Compiler.LCNF.Arg.erased }
Equations
Equations
Equations
- p.toArg = Lean.Compiler.LCNF.Arg.fvar p.fvarId
Instances For
Equations
- arg.toExpr = match arg with | Lean.Compiler.LCNF.Arg.erased => Lean.Compiler.LCNF.erasedExpr | Lean.Compiler.LCNF.Arg.fvar fvarId => Lean.Expr.fvar fvarId | Lean.Compiler.LCNF.Arg.type e => e
Instances For
- value: Lean.Compiler.LCNF.LitValue → Lean.Compiler.LCNF.LetValue
- erased: Lean.Compiler.LCNF.LetValue
- proj: Lake.Name → Nat → Lean.FVarId → Lean.Compiler.LCNF.LetValue
- const: Lake.Name → List Lean.Level → Array Lean.Compiler.LCNF.Arg → Lean.Compiler.LCNF.LetValue
- fvar: Lean.FVarId → Array Lean.Compiler.LCNF.Arg → Lean.Compiler.LCNF.LetValue
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedLetValue = { default := Lean.Compiler.LCNF.LetValue.value default }
Equations
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
- fvarId : Lean.FVarId
- binderName : Lake.Name
- type : Lean.Expr
- value : Lean.Compiler.LCNF.LetValue
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedLetDecl = { default := { fvarId := default, binderName := default, type := default, value := default } }
Equations
- fvarId : Lean.FVarId
- binderName : Lake.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
- decl.getArity = decl.params.size
Instances For
- typeName : Lake.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.Compiler.LCNF.Arg → 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 }
Instances For
Instances For
Instances For
Return the constructor names that have an explicit (non-default) alternative.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Lean.Compiler.LCNF.instInhabitedCodeDecl = { default := Lean.Compiler.LCNF.CodeDecl.let default }
Equations
- x.fvarId = match x with | Lean.Compiler.LCNF.CodeDecl.let decl => decl.fvarId | Lean.Compiler.LCNF.CodeDecl.fun decl => decl.fvarId | Lean.Compiler.LCNF.CodeDecl.jp decl => decl.fvarId
Instances For
Equations
- Lean.Compiler.LCNF.attachCodeDecls decls code = Lean.Compiler.LCNF.attachCodeDecls.go decls decls.size code
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
Equations
Equations
- Lean.Compiler.LCNF.AltCore.getCode x = match x with | Lean.Compiler.LCNF.AltCore.default k => k | Lean.Compiler.LCNF.AltCore.alt ctorName params k => k
Instances For
Equations
- Lean.Compiler.LCNF.AltCore.getParams x = match x with | Lean.Compiler.LCNF.AltCore.default code => #[] | Lean.Compiler.LCNF.AltCore.alt ctorName ps code => ps
Instances For
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
Instances For
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.
Instances For
Equations
- Lean.Compiler.LCNF.AltCore.mapCodeM alt f = do let __do_lift ← f (Lean.Compiler.LCNF.AltCore.getCode alt) pure (Lean.Compiler.LCNF.AltCore.updateCode alt __do_lift)
Instances For
Equations
- x.isDecl = match x with | Lean.Compiler.LCNF.Code.let decl k => true | Lean.Compiler.LCNF.Code.fun decl k => true | Lean.Compiler.LCNF.Code.jp decl k => true | x => false
Instances For
Equations
- x.isFun = match x with | Lean.Compiler.LCNF.Code.fun decl k => true | x => false
Instances For
Equations
- x✝.isReturnOf x = match x✝, x with | Lean.Compiler.LCNF.Code.return fvarId, fvarId' => fvarId == fvarId' | x, x_1 => false
Instances For
Equations
- c.size = Lean.Compiler.LCNF.Code.size.go c 0
Instances For
Return true iff c.size ≤ n
Equations
- c.sizeLe n = match (Lean.Compiler.LCNF.Code.sizeLe.go n c).run 0 with | EStateM.Result.ok a a_1 => true | EStateM.Result.error a a_1 => false
Instances For
Equations
- c.forM f = Lean.Compiler.LCNF.Code.forM.go f c
Instances For
Declaration being processed by the Lean to Lean compiler passes.
- name : Lake.Name
The name of the declaration from the
Environment
it came from Universe level parameter names.
- type : Lean.Expr
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
. - params : Array Lean.Compiler.LCNF.Param
Parameters.
- value : Lean.Compiler.LCNF.Code
The body of the declaration, usually changes as it progresses through compiler passes.
- recursive : Bool
We set this flag to true during LCNF conversion. When we receive a block of functions to be compiled, we set this flag to
true
if 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. - safe : Bool
We 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
.partial
andunsafe
functions may not be terminating, but Lean functions terminate, and some static analyzers exploit this fact. So, we use the following semantics. Suppose we have 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 consumingC
recursion tokens all partial functions must be called as normal. Once the model has used upC
recursion 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 ofC
yield less nondeterminism in the model, but even the intersection of all choices ofC
yields nondeterminism wheredef loop : A := loop
returns 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. - inlineAttr? : Option Lean.Compiler.InlineAttributeKind
We store the inline attribute at LCNF declarations to make sure we can set them for auxiliary declarations created during compilation.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Equations
Equations
- decl.size = decl.value.size
Instances For
Equations
- decl.getArity = decl.params.size
Instances For
Equations
- decl.inlineAttr = match decl.inlineAttr? with | some Lean.Compiler.InlineAttributeKind.inline => true | x => false
Instances For
Equations
- decl.noinlineAttr = match decl.inlineAttr? with | some Lean.Compiler.InlineAttributeKind.noinline => true | x => false
Instances For
Equations
- decl.inlineIfReduceAttr = match decl.inlineAttr? with | some Lean.Compiler.InlineAttributeKind.inlineIfReduce => true | x => false
Instances For
Equations
- decl.alwaysInlineAttr = match decl.inlineAttr? with | some Lean.Compiler.InlineAttributeKind.alwaysInline => true | x => false
Instances For
Return true
if the given declaration has been annotated with [inline]
, [inline_if_reduce]
, [macro_inline]
, or [always_inline]
Equations
Instances For
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
[inline_if_reduce]
or not.
Equations
- decl.isCasesOnParam? = Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl decl.value
Instances For
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) = decl.params.findIdx? fun (param : Lean.Compiler.LCNF.Param) => param.fvarId == c.discr
- Lean.Compiler.LCNF.Decl.isCasesOnParam?.go decl code = none
Instances For
Equations
- decl.instantiateTypeLevelParams us = decl.type.instantiateLevelParamsNoCache decl.levelParams us
Instances For
Equations
- decl.instantiateParamsLevelParams us = decl.params.mapMono fun (param : Lean.Compiler.LCNF.Param) => param.updateCore (param.type.instantiateLevelParamsNoCache decl.levelParams us)
Instances For
Equations
- decl.instantiateValueLevelParams us = Lean.Compiler.LCNF.Decl.instantiateValueLevelParams.instCode decl us decl.value
Instances For
Equations
- Lean.Compiler.LCNF.Decl.instantiateValueLevelParams.instLevel decl us u = u.instantiateParams decl.levelParams us
Instances For
Equations
- Lean.Compiler.LCNF.Decl.instantiateValueLevelParams.instExpr decl us e = e.instantiateLevelParamsNoCache decl.levelParams us
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
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
Return true
if the arrow type contains an instance implicit argument.
Equations
- Lean.Compiler.LCNF.hasLocalInst (Lean.Expr.forallE binderName binderType b bi) = (bi.isInstImplicit || Lean.Compiler.LCNF.hasLocalInst b)
- Lean.Compiler.LCNF.hasLocalInst type = false
Instances For
Return true
if decl
is supposed to be inlined/specialized.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
Instances For
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.
Instances For
Equations
- Lean.Compiler.LCNF.markRecDecls.go decls = Array.forM (fun (decl : Lean.Compiler.LCNF.Decl) => Lean.Compiler.LCNF.markRecDecls.visit decls decl.value) decls
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.