This PR removes uses of `Lean.RBMap` in Lean itself. Furthermore some massaging of the import graph is done in order to avoid having `Std.Data.TreeMap.AdditionalOperations` (which is quite expensive) be the critical path for a large chunk of Lean. In particular we can build `Lean.Meta.Simp` and `Lean.Meta.Grind` without it thanks to these changes. We did previously not conduct this change as `Std.TreeMap` was not outperforming `Lean.RBMap` yet, however this has changed with the new code generator.
113 lines
3.7 KiB
Text
113 lines
3.7 KiB
Text
/-
|
||
Copyright (c) 2022 Microsoft Corporation. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Leonardo de Moura
|
||
-/
|
||
prelude
|
||
import Lean.Compiler.LCNF.Basic
|
||
|
||
namespace Lean.Compiler.LCNF
|
||
|
||
namespace ToExpr
|
||
|
||
private abbrev LevelMap := FVarIdMap Nat
|
||
|
||
private def _root_.Lean.FVarId.toExpr (offset : Nat) (m : LevelMap) (fvarId : FVarId) : Expr :=
|
||
match m.get? fvarId with
|
||
| some level => .bvar (offset - level - 1)
|
||
| none => .fvar fvarId
|
||
|
||
private def _root_.Lean.Expr.abstract' (offset : Nat) (m : LevelMap) (e : Expr) : Expr :=
|
||
go offset e
|
||
where
|
||
go (o : Nat) (e : Expr) : Expr :=
|
||
match e with
|
||
| .fvar fvarId => fvarId.toExpr o m
|
||
| .lit .. | .const .. | .sort .. | .mvar .. | .bvar .. => e
|
||
| .app f a => .app (go o f) (go o a)
|
||
| .mdata k b => .mdata k (go o b)
|
||
| .proj s i b => .proj s i (go o b)
|
||
| .forallE n d b bi => .forallE n (go o d) (go (o+1) b) bi
|
||
| .lam n d b bi => .lam n (go o d) (go (o+1) b) bi
|
||
| .letE n t v b nd => .letE n (go o t) (go o v) (go (o+1) b) nd
|
||
|
||
abbrev ToExprM := ReaderT Nat $ StateM LevelMap
|
||
|
||
abbrev mkLambdaM (params : Array Param) (e : Expr) : ToExprM Expr :=
|
||
return go (← read) (← get) params.size e
|
||
where
|
||
go (offset : Nat) (m : LevelMap) (i : Nat) (e : Expr) : Expr :=
|
||
if i > 0 then
|
||
let param := params[i-1]!
|
||
let domain := param.type.abstract' (offset - 1) m
|
||
go (offset - 1) m (i - 1) (.lam param.binderName domain e .default)
|
||
else
|
||
e
|
||
|
||
private abbrev _root_.Lean.FVarId.toExprM (fvarId : FVarId) : ToExprM Expr :=
|
||
return fvarId.toExpr (← read) (← get)
|
||
|
||
abbrev abstractM (e : Expr) : ToExprM Expr :=
|
||
return e.abstract' (← read) (← get)
|
||
|
||
@[inline] def withFVar (fvarId : FVarId) (k : ToExprM α) : ToExprM α := do
|
||
let offset ← read
|
||
modify fun s => s.insert fvarId offset
|
||
withReader (·+1) k
|
||
|
||
@[inline] partial def withParams (params : Array Param) (k : ToExprM α) : ToExprM α :=
|
||
go 0
|
||
where
|
||
@[specialize] go (i : Nat) : ToExprM α := do
|
||
if h : i < params.size then
|
||
withFVar params[i].fvarId (go (i+1))
|
||
else
|
||
k
|
||
|
||
@[inline] def run (x : ToExprM α) (offset : Nat := 0) (levelMap : LevelMap := {}) : α :=
|
||
x |>.run offset |>.run' levelMap
|
||
|
||
@[inline] def run' (x : ToExprM α) (xs : Array FVarId) : α :=
|
||
let map := xs.foldl (init := {}) fun map x => map.insert x map.size
|
||
run x xs.size map
|
||
|
||
end ToExpr
|
||
|
||
open ToExpr
|
||
|
||
private def Arg.toExprM (arg : Arg) : ToExprM Expr :=
|
||
return arg.toExpr.abstract' (← read) (← get)
|
||
|
||
mutual
|
||
partial def FunDecl.toExprM (decl : FunDecl) : ToExprM Expr :=
|
||
withParams decl.params do mkLambdaM decl.params (← decl.value.toExprM)
|
||
|
||
partial def Code.toExprM (code : Code) : ToExprM Expr := do
|
||
match code with
|
||
| .let decl k =>
|
||
let type ← abstractM decl.type
|
||
let value ← abstractM decl.value.toExpr
|
||
let body ← withFVar decl.fvarId k.toExprM
|
||
return .letE decl.binderName type value body true
|
||
| .fun decl k | .jp decl k =>
|
||
let type ← abstractM decl.type
|
||
let value ← decl.toExprM
|
||
let body ← withFVar decl.fvarId k.toExprM
|
||
return .letE decl.binderName type value body true
|
||
| .return fvarId => fvarId.toExprM
|
||
| .jmp fvarId args => return mkAppN (← fvarId.toExprM) (← args.mapM Arg.toExprM)
|
||
| .unreach type => return mkApp (mkConst ``lcUnreachable) (← abstractM type)
|
||
| .cases c =>
|
||
let alts ← c.alts.mapM fun
|
||
| .alt _ params k => withParams params do mkLambdaM params (← k.toExprM)
|
||
| .default k => k.toExprM
|
||
return mkAppN (mkConst `cases) (#[← c.discr.toExprM] ++ alts)
|
||
end
|
||
|
||
def Code.toExpr (code : Code) (xs : Array FVarId := #[]) : Expr :=
|
||
run' code.toExprM xs
|
||
|
||
def FunDecl.toExpr (decl : FunDecl) (xs : Array FVarId := #[]) : Expr :=
|
||
run' decl.toExprM xs
|
||
|
||
end Lean.Compiler.LCNF
|