import Lean.MetavarContext open Lean def mkLambdaTest (mctx : MetavarContext) (ngen : NameGenerator) (lctx : LocalContext) (xs : Array Expr) (e : Expr) : Except MetavarContext.MkBinding.Exception (MetavarContext × NameGenerator × Expr) := match MetavarContext.mkLambda xs e false true lctx { mctx := mctx, ngen := ngen } with | EStateM.Result.ok e s => Except.ok (s.mctx, s.ngen, e) | EStateM.Result.error e s => Except.error e def check (b : Bool) : IO Unit := unless b do throw $ IO.userError "error" def f := mkConst `f def g := mkConst `g def a := mkConst `a def b := mkConst `b def c := mkConst `c def b0 := mkBVar 0 def b1 := mkBVar 1 def b2 := mkBVar 2 def u := mkLevelParam `u def typeE := mkSort levelOne def natE := mkConst `Nat def boolE := mkConst `Bool def vecE := mkConst `Vec [levelZero] def α := mkFVar `α def x := mkFVar `x def y := mkFVar `y def z := mkFVar `z def w := mkFVar `w def m1 := mkMVar `m1 def m2 := mkMVar `m2 def m3 := mkMVar `m3 def bi := BinderInfo.default def arrow (d b : Expr) := mkForall `_ bi d b def lctx1 : LocalContext := {} def lctx2 := lctx1.mkLocalDecl `α `α typeE def lctx3 := lctx2.mkLocalDecl `x `x m1 def lctx4 := lctx3.mkLocalDecl `y `y (arrow natE m2) def mctx1 : MetavarContext := {} def mctx2 := mctx1.addExprMVarDecl `m1 `m1 lctx2 #[] typeE def mctx3 := mctx2.addExprMVarDecl `m2 `m2 lctx3 #[] natE def mctx4 := mctx3.addExprMVarDecl `m3 `m3 lctx3 #[] natE def mctx4' := mctx3.addExprMVarDecl `m3 `m3 lctx3 #[] natE MetavarKind.syntheticOpaque def R1 := match mkLambdaTest mctx4 {namePrefix := `n} lctx4 #[α, x, y] $ mkAppN f #[m3, x] with | Except.ok s => s | Except.error e => panic! (toString e) def e1 := R1.2.2 def mctx5 := R1.1 def sortNames (xs : List Name) : List Name := (xs.toArray.qsort Name.lt).toList def sortNamePairs {α} [Inhabited α] (xs : List (Name × α)) : List (Name × α) := (xs.toArray.qsort (fun a b => Name.lt a.1 b.1)).toList #eval toString $ sortNames $ mctx5.decls.toList.map Prod.fst #eval toString $ sortNamePairs $ mctx5.eAssignment.toList #eval e1 #eval check (!e1.hasFVar) def R2 := match mkLambdaTest mctx4' {namePrefix := `n} lctx4 #[α, x, y] $ mkAppN f #[m3, y] with | Except.ok s => s | Except.error e => panic! (toString e) def e2 := R2.2.2 def mctx6 := R2.1 #eval toString $ sortNames $ mctx6.decls.toList.map Prod.fst #eval toString $ sortNamePairs $ mctx6.eAssignment.toList -- ?n.2 was delayed assigned because ?m.3 is synthetic #eval toString $ sortNames $ mctx6.dAssignment.toList.map Prod.fst #eval e2 #print "assigning ?m1 and ?n.1" def R3 := let mctx := mctx6.assignExpr `m3 x; let mctx := mctx.assignExpr (Name.mkNum `n 1) (mkLambda `_ bi typeE natE); -- ?n.2 is instantiated because we have the delayed assignment `?n.2 α x := ?m1` (mctx.instantiateMVars e2) def e3 := R3.1 def mctx7 := R3.2 #eval e3