import Lean open Lean inductive Entry | name (n : Name) | level (n : Level) | expr (n : Expr) | defn (n : Name) deriving Inhabited structure Alloc (α) [BEq α] [Hashable α] where map : Std.HashMap α Nat next : Nat deriving Inhabited namespace Export structure State where names : Alloc Name := ⟨(∅ : Std.HashMap Name Nat).insert Name.anonymous 0, 1⟩ levels : Alloc Level := ⟨(∅ : Std.HashMap Level Nat).insert Level.zero 0, 1⟩ exprs : Alloc Expr defs : Std.HashSet Name stk : Array (Bool × Entry) deriving Inhabited class OfState (α : Type) [BEq α] [Hashable α] where get : State → Alloc α modify : (Alloc α → Alloc α) → State → State instance : OfState Name where get s := s.names modify f s := { s with names := f s.names } instance : OfState Level where get s := s.levels modify f s := { s with levels := f s.levels } instance : OfState Expr where get s := s.exprs modify f s := { s with exprs := f s.exprs } end Export abbrev ExportM := StateT Export.State CoreM namespace Export def alloc {α} [BEq α] [Hashable α] [OfState α] (a : α) : ExportM Nat := do let n := (OfState.get (α := α) (← get)).next modify $ OfState.modify (α := α) fun s => {map := s.map.insert a n, next := n+1} pure n def exportName (n : Name) : ExportM Nat := do match (← get).names.map[n]? with | some i => pure i | none => match n with | .anonymous => pure 0 | .num p a => let i ← alloc n; IO.println s!"{i} #NI {← exportName p} {a}"; pure i | .str p s => let i ← alloc n; IO.println s!"{i} #NS {← exportName p} {s}"; pure i attribute [simp] exportName def exportLevel (L : Level) : ExportM Nat := do match (← get).levels.map[L]? with | some i => pure i | none => match L with | Level.zero => pure 0 | Level.succ l => let i ← alloc L; IO.println s!"{i} #US {← exportLevel l}"; pure i | Level.max l₁ l₂ => let i ← alloc L; IO.println s!"{i} #UM {← exportLevel l₁} {← exportLevel l₂}"; pure i | Level.imax l₁ l₂ => let i ← alloc L; IO.println s!"{i} #UIM {← exportLevel l₁} {← exportLevel l₂}"; pure i | Level.param n => let i ← alloc L; IO.println s!"{i} #UP {← exportName n}"; pure i | Level.mvar _ => unreachable! -- TODO: this test has been broken for a while with a panic that was ignored by the test suite --attribute [simp] exportLevel