From 98ad1ae2831c3136d7ff3c56869272323625a111 Mon Sep 17 00:00:00 2001 From: Leni Aniva <v@leni.sh> Date: Fri, 14 Mar 2025 16:54:34 -0700 Subject: [PATCH 1/8] feat(delate): Tracing tags --- Pantograph/Delate.lean | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Pantograph/Delate.lean b/Pantograph/Delate.lean index ad923aa..44c09a9 100644 --- a/Pantograph/Delate.lean +++ b/Pantograph/Delate.lean @@ -85,13 +85,13 @@ This function ensures any metavariable in the result is either 1. Delayed assigned with its pending mvar not assigned in any form 2. Not assigned (delay or not) -/ -partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := do +partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := --let padding := String.join $ List.replicate level "│ " - --IO.println s!"{padding}Starting {toString eOrig}" + withTraceNode `Pantograph.Delate (λ _ex => return m!":= {← Meta.ppExpr eOrig}") do let mut result ← Meta.transform (← instantiateMVars eOrig) (pre := fun e => e.withApp fun f args => do let .mvar mvarId := f | return .continue - --IO.println s!"{padding}├V {e}" + trace[Pantograph.Delate] "V {e}" let mvarDecl ← mvarId.getDecl -- This is critical to maintaining the interdependency of metavariables. @@ -109,12 +109,13 @@ partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := do panic! s!"In the context of {mvarId.name}, there are local context variable violations: {violations}" if let .some assign ← getExprMVarAssignment? mvarId then - --IO.println s!"{padding}├A ?{mvarId.name}" + trace[Pantograph.Delate] "A ?{mvarId.name}" assert! !(← mvarId.isDelayedAssigned) return .visit (mkAppN assign args) else if let some { fvars, mvarIdPending } ← getDelayedMVarAssignment? mvarId then - --let substTableStr := String.intercalate ", " $ Array.zipWith fvars args (λ fvar assign => s!"{fvar.fvarId!.name} := {assign}") |>.toList - --IO.println s!"{padding}├MD ?{mvarId.name} := ?{mvarIdPending.name} [{substTableStr}]" + if ← isTracingEnabledFor `Pantograph.Delate then + let substTableStr := String.intercalate ", " $ Array.zipWith fvars args (λ fvar assign => s!"{fvar.fvarId!.name} := {assign}") |>.toList + trace[Pantograph.Delate]"MD ?{mvarId.name} := ?{mvarIdPending.name} [{substTableStr}]" if args.size < fvars.size then throwError "Not enough arguments to instantiate a delay assigned mvar. This is due to bad implementations of a tactic: {args.size} < {fvars.size}. Expr: {toString e}; Origin: {toString eOrig}" @@ -124,18 +125,18 @@ partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := do --if !args.isEmpty then --IO.println s!"{padding}├── Arguments End" if !(← mvarIdPending.isAssignedOrDelayedAssigned) then - --IO.println s!"{padding}├T1" + trace[Pantograph.Delate] "T1" let result := mkAppN f args return .done result let pending ← mvarIdPending.withContext do let inner ← instantiateDelayedMVars (.mvar mvarIdPending) --(level := level + 1) - --IO.println s!"{padding}├Pre: {inner}" + trace[Pantograph.Delate] "Pre: {inner}" pure <| (← inner.abstractM fvars).instantiateRev args -- Tail arguments let result := mkAppRange pending fvars.size args.size args - --IO.println s!"{padding}├MD {result}" + trace[Pantograph.Delate] "MD {result}" return .done result else assert! !(← mvarId.isAssigned) @@ -146,9 +147,9 @@ partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := do --if !args.isEmpty then -- IO.println s!"{padding}├── Arguments End" - --IO.println s!"{padding}├M ?{mvarId.name}" + trace[Pantograph.Delate] "M ?{mvarId.name}" return .done (mkAppN f args)) - --IO.println s!"{padding}└Result {result}" + trace[Pantoraph.Delate] "Result {result}" return result where self e := instantiateDelayedMVars e --(level := level + 1) @@ -594,4 +595,7 @@ protected def GoalState.diag (goalState: GoalState) (parent?: Option GoalState : | other => s!"[{other}]" parentHasMVar (mvarId: MVarId): Bool := parent?.map (λ state => state.mctx.decls.contains mvarId) |>.getD true +initialize + registerTraceClass `Pantograph.Delate + end Pantograph From 78485ae6e23ee1d5a4e2bb15c610b5543c2535d3 Mon Sep 17 00:00:00 2001 From: Leni Aniva <v@leni.sh> Date: Fri, 14 Mar 2025 20:07:31 -0700 Subject: [PATCH 2/8] doc(frontend): Update documentation for `frontend.process` --- Pantograph/Protocol.lean | 5 ++--- doc/repl.md | 7 ++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Pantograph/Protocol.lean b/Pantograph/Protocol.lean index 164b72a..7924db7 100644 --- a/Pantograph/Protocol.lean +++ b/Pantograph/Protocol.lean @@ -346,10 +346,9 @@ structure FrontendProcess where -- One of these two must be supplied: Either supply the file name or the content. fileName?: Option String := .none file?: Option String := .none - -- If set to true, read the header (otherwise discards the header) + -- Whether to read the header readHeader : Bool := false - -- If set to true, Pantograph's environment will be altered to whatever is - -- after the compilation units. + -- Alter the REPL environment after the compilation units. inheritEnv : Bool := false -- collect tactic invocations invocations: Bool := false diff --git a/doc/repl.md b/doc/repl.md index a86c01b..93eb6ab 100644 --- a/doc/repl.md +++ b/doc/repl.md @@ -46,14 +46,15 @@ See `Pantograph/Protocol.lean` for a description of the parameters and return va Save/Load a goal state to/from a file. The environment is not carried with the state. The user is responsible to ensure the sender/receiver instances share the same environment. -* `frontend.process { ["fileName": <fileName>,] ["file": <str>], invocations: +* `frontend.process { ["fileName": <fileName>,] ["file": <str>], readHeader: <bool>, inheritEnv: <bool>, invocations: <bool>, sorrys: <bool>, typeErrorsAsGoals: <bool>, newConstants: <bool> }`: Executes the Lean frontend on a file, collecting the tactic invocations (`"invocations": true`), the sorrys and type errors into goal states (`"sorrys": true`), and new constants (`"newConstants": true`). In the case of `sorrys`, this command additionally outputs the position of each captured - `sorry`. Warning: Behaviour is unstable in case of multiple `sorry`s. Use the - draft tactic if possible. + `sorry`. Conditionally inherit the environment from executing the file. + Warning: Behaviour is unstable in case of multiple `sorry`s. Use the draft + tactic if possible. ## Errors From dc29d48b774cc32c3f67219746a6b4539348c700 Mon Sep 17 00:00:00 2001 From: Leni Aniva <v@leni.sh> Date: Mon, 17 Mar 2025 09:31:39 -0700 Subject: [PATCH 3/8] chore: Remove IO.println for trace --- Pantograph/Delate.lean | 18 +++++++++--------- Pantograph/Frontend/MetaTranslate.lean | 9 ++++++--- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Pantograph/Delate.lean b/Pantograph/Delate.lean index 44c09a9..2fff009 100644 --- a/Pantograph/Delate.lean +++ b/Pantograph/Delate.lean @@ -119,11 +119,11 @@ partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := if args.size < fvars.size then throwError "Not enough arguments to instantiate a delay assigned mvar. This is due to bad implementations of a tactic: {args.size} < {fvars.size}. Expr: {toString e}; Origin: {toString eOrig}" - --if !args.isEmpty then - --IO.println s!"{padding}├── Arguments Begin" + if !args.isEmpty then + trace[Pantograph.Delate] "─ Arguments Begin" let args ← args.mapM self - --if !args.isEmpty then - --IO.println s!"{padding}├── Arguments End" + if !args.isEmpty then + trace[Pantograph.Delate] "─ Arguments End" if !(← mvarIdPending.isAssignedOrDelayedAssigned) then trace[Pantograph.Delate] "T1" let result := mkAppN f args @@ -141,18 +141,18 @@ partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := else assert! !(← mvarId.isAssigned) assert! !(← mvarId.isDelayedAssigned) - --if !args.isEmpty then - -- IO.println s!"{padding}├── Arguments Begin" + if !args.isEmpty then + trace[Pantograph.Delate] "─ Arguments Begin" let args ← args.mapM self - --if !args.isEmpty then - -- IO.println s!"{padding}├── Arguments End" + if !args.isEmpty then + trace[Pantograph.Delate] "─ Arguments End" trace[Pantograph.Delate] "M ?{mvarId.name}" return .done (mkAppN f args)) trace[Pantoraph.Delate] "Result {result}" return result where - self e := instantiateDelayedMVars e --(level := level + 1) + self e := instantiateDelayedMVars e /-- Convert an expression to an equiavlent form with diff --git a/Pantograph/Frontend/MetaTranslate.lean b/Pantograph/Frontend/MetaTranslate.lean index c6592d2..8067d17 100644 --- a/Pantograph/Frontend/MetaTranslate.lean +++ b/Pantograph/Frontend/MetaTranslate.lean @@ -62,7 +62,7 @@ private partial def translateExpr (srcExpr: Expr) : MetaTranslateM Expr := do let sourceMCtx ← getSourceMCtx -- We want to create as few mvars as possible let (srcExpr, _) := instantiateMVarsCore (mctx := sourceMCtx) srcExpr - --IO.println s!"Transform src: {srcExpr}" + trace[Pantograph.Frontend.MetaTranslate] "Transform src: {srcExpr}" let result ← Core.transform srcExpr λ e => do let state ← get match e with @@ -100,10 +100,10 @@ partial def translateLocalDecl (srcLocalDecl: LocalDecl) : MetaTranslateM LocalD addTranslatedFVar srcLocalDecl.fvarId fvarId match srcLocalDecl with | .cdecl index _ userName type bi kind => do - --IO.println s!"[CD] {userName} {toString type}" + trace[Pantograph.Frontend.MetaTranslate] "[CD] {userName} {toString type}" return .cdecl index fvarId userName (← translateExpr type) bi kind | .ldecl index _ userName type value nonDep kind => do - --IO.println s!"[LD] {toString type} := {toString value}" + trace[Pantograph.Frontend.MetaTranslate] "[LD] {toString type} := {toString value}" return .ldecl index fvarId userName (← translateExpr type) (← translateExpr value) nonDep kind partial def translateLCtx : MetaTranslateM LocalContext := do @@ -162,4 +162,7 @@ end MetaTranslate export MetaTranslate (MetaTranslateM) +initialize + registerTraceClass `Pantograph.Frontend.MetaTranslate + end Pantograph.Frontend From a28ad9b239553ed9cd9d776daf14ef8e10f5954d Mon Sep 17 00:00:00 2001 From: Leni Aniva <v@leni.sh> Date: Mon, 17 Mar 2025 10:47:11 -0700 Subject: [PATCH 4/8] feat(delate): Expand matcher applications --- Pantograph/Delate.lean | 9 ++++++++- Test/Common.lean | 4 ++-- Test/Delate.lean | 13 ++++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Pantograph/Delate.lean b/Pantograph/Delate.lean index 2fff009..1a4af5d 100644 --- a/Pantograph/Delate.lean +++ b/Pantograph/Delate.lean @@ -66,7 +66,7 @@ def exprProjToApp (env: Environment) (e: Expr): Expr := def _root_.Lean.Name.isAuxLemma (n : Lean.Name) : Bool := n matches .num (.str _ "_auxLemma") _ /-- Unfold all lemmas created by `Lean.Meta.mkAuxLemma`. These end in `_auxLemma.nn` where `nn` is a number. -/ -@[export pantograph_unfold_aux_lemmas] +@[export pantograph_unfold_aux_lemmas_m] def unfoldAuxLemmas (e : Expr) : CoreM Expr := do Lean.Meta.deltaExpand e Lean.Name.isAuxLemma @@ -164,6 +164,13 @@ Convert an expression to an equiavlent form with def instantiateAll (e: Expr): MetaM Expr := do let e ← instantiateDelayedMVars e let e ← unfoldAuxLemmas e + let e ← Core.transform e λ e' => do + match ← Meta.matchMatcherApp? e' with + | .none => return .continue e' + | .some mapp => + let .some matcherInfo := (← getEnv).find? mapp.matcherName | panic! "Matcher must exist" + let f ← Meta.instantiateValueLevelParams matcherInfo mapp.matcherLevels.toList + return .visit (f.betaRev e'.getAppRevArgs (useZeta := true)) return e structure DelayedMVarInvocation where diff --git a/Test/Common.lean b/Test/Common.lean index 5274bad..c32d62d 100644 --- a/Test/Common.lean +++ b/Test/Common.lean @@ -108,7 +108,7 @@ def strToTermSyntax (s: String): CoreM Syntax := do (input := s) (fileName := ← getFileName) | panic! s!"Failed to parse {s}" return stx -def parseSentence (s: String): Elab.TermElabM Expr := do +def parseSentence (s : String) (expectedType? : Option Expr := .none) : Elab.TermElabM Expr := do let stx ← match Parser.runParserCategory (env := ← MonadEnv.getEnv) (catName := `term) @@ -116,7 +116,7 @@ def parseSentence (s: String): Elab.TermElabM Expr := do (fileName := ← getFileName) with | .ok syn => pure syn | .error error => throwError "Failed to parse: {error}" - Elab.Term.elabTerm (stx := stx) .none + Elab.Term.elabTerm (stx := stx) expectedType? def runTacticOnMVar (tacticM: Elab.Tactic.TacticM Unit) (goal: MVarId): Elab.TermElabM (List MVarId) := do let (_, newGoals) ← tacticM { elaborator := .anonymous } |>.run { goals := [goal] } diff --git a/Test/Delate.lean b/Test/Delate.lean index 517a394..7c5eec3 100644 --- a/Test/Delate.lean +++ b/Test/Delate.lean @@ -3,10 +3,9 @@ import Pantograph.Delate import Test.Common import Lean -open Lean -namespace Pantograph.Test.Delate +open Lean Pantograph -open Pantograph +namespace Pantograph.Test.Delate deriving instance Repr, DecidableEq for Protocol.BoundExpression @@ -113,6 +112,13 @@ def test_projection_exists (env: Environment) : IO LSpec.TestSeq:= runTest do checkEq "numParams" numParams 2 checkEq "numFields" numFields 2 +def test_matcher : TestT Elab.TermElabM Unit := do + let t ← parseSentence "Nat → Nat" + let e ← parseSentence "fun (n : Nat) => match n with | 0 => 0 | k => k" (.some t) + let .some _ ← Meta.matchMatcherApp? e.bindingBody! | fail "Must be a matcher app" + let e' ← instantiateAll e + checkTrue "ok" <| ← Meta.isTypeCorrect e' + def suite (env: Environment): List (String × IO LSpec.TestSeq) := [ ("serializeName", do pure test_serializeName), @@ -123,6 +129,7 @@ def suite (env: Environment): List (String × IO LSpec.TestSeq) := ("Instance", test_instance env), ("Projection Prod", test_projection_prod env), ("Projection Exists", test_projection_exists env), + ("Matcher", runTestTermElabM env test_matcher), ] end Pantograph.Test.Delate From 3b4b196a302c3c74c0ebabea0435fa8e1e602950 Mon Sep 17 00:00:00 2001 From: Leni Aniva <v@leni.sh> Date: Mon, 17 Mar 2025 11:20:38 -0700 Subject: [PATCH 5/8] feat(delate): Add mdata annotation for matcher --- Pantograph/Delate.lean | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Pantograph/Delate.lean b/Pantograph/Delate.lean index 1a4af5d..5060d25 100644 --- a/Pantograph/Delate.lean +++ b/Pantograph/Delate.lean @@ -170,7 +170,8 @@ def instantiateAll (e: Expr): MetaM Expr := do | .some mapp => let .some matcherInfo := (← getEnv).find? mapp.matcherName | panic! "Matcher must exist" let f ← Meta.instantiateValueLevelParams matcherInfo mapp.matcherLevels.toList - return .visit (f.betaRev e'.getAppRevArgs (useZeta := true)) + let mdata := KVMap.empty.insert `matcher (DataValue.ofName mapp.matcherName) + return .visit $ .mdata mdata (f.betaRev e'.getAppRevArgs (useZeta := true)) return e structure DelayedMVarInvocation where From 4643992c3bb18b4a96b1cf755b709123b6137f63 Mon Sep 17 00:00:00 2001 From: Leni Aniva <v@leni.sh> Date: Mon, 17 Mar 2025 11:26:13 -0700 Subject: [PATCH 6/8] refactor(delate): Unfold matchers into function --- Pantograph/Delate.lean | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Pantograph/Delate.lean b/Pantograph/Delate.lean index 5060d25..3ef2c35 100644 --- a/Pantograph/Delate.lean +++ b/Pantograph/Delate.lean @@ -67,8 +67,17 @@ def _root_.Lean.Name.isAuxLemma (n : Lean.Name) : Bool := n matches .num (.str _ /-- Unfold all lemmas created by `Lean.Meta.mkAuxLemma`. These end in `_auxLemma.nn` where `nn` is a number. -/ @[export pantograph_unfold_aux_lemmas_m] -def unfoldAuxLemmas (e : Expr) : CoreM Expr := do - Lean.Meta.deltaExpand e Lean.Name.isAuxLemma +def unfoldAuxLemmas : Expr → CoreM Expr := + (Lean.Meta.deltaExpand · Lean.Name.isAuxLemma) +/-- Unfold all matcher applications -/ +@[export pantograph_unfold_matchers_m] +def unfoldMatchers (expr : Expr) : CoreM Expr := + Core.transform expr λ e' => do + let .some mapp ← Meta.matchMatcherApp? e' | return .continue e' + let .some matcherInfo := (← getEnv).find? mapp.matcherName | panic! "Matcher must exist" + let f ← Meta.instantiateValueLevelParams matcherInfo mapp.matcherLevels.toList + let mdata := KVMap.empty.insert `matcher (DataValue.ofName mapp.matcherName) + return .visit $ .mdata mdata (f.betaRev e'.getAppRevArgs (useZeta := true)) /-- Force the instantiation of delayed metavariables even if they cannot be fully @@ -157,28 +166,21 @@ partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := /-- Convert an expression to an equiavlent form with 1. No nested delayed assigned mvars -2. No aux lemmas +2. No aux lemmas or matchers 3. No assigned mvars -/ @[export pantograph_instantiate_all_m] -def instantiateAll (e: Expr): MetaM Expr := do +def instantiateAll (e : Expr) : MetaM Expr := do let e ← instantiateDelayedMVars e let e ← unfoldAuxLemmas e - let e ← Core.transform e λ e' => do - match ← Meta.matchMatcherApp? e' with - | .none => return .continue e' - | .some mapp => - let .some matcherInfo := (← getEnv).find? mapp.matcherName | panic! "Matcher must exist" - let f ← Meta.instantiateValueLevelParams matcherInfo mapp.matcherLevels.toList - let mdata := KVMap.empty.insert `matcher (DataValue.ofName mapp.matcherName) - return .visit $ .mdata mdata (f.betaRev e'.getAppRevArgs (useZeta := true)) + let e ← unfoldMatchers e return e structure DelayedMVarInvocation where - mvarIdPending: MVarId - args: Array (FVarId × (Option Expr)) + mvarIdPending : MVarId + args : Array (FVarId × (Option Expr)) -- Extra arguments applied to the result of this substitution - tail: Array Expr + tail : Array Expr -- The pending mvar of any delayed assigned mvar must not be assigned in any way. @[export pantograph_to_delayed_mvar_invocation_m] From 678cc9b3c0d7dc759791b6934a4d8c0df859aa26 Mon Sep 17 00:00:00 2001 From: Leni Aniva <v@leni.sh> Date: Mon, 17 Mar 2025 11:30:24 -0700 Subject: [PATCH 7/8] chore: Code cleanup --- Pantograph/Delate.lean | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Pantograph/Delate.lean b/Pantograph/Delate.lean index 3ef2c35..6e47799 100644 --- a/Pantograph/Delate.lean +++ b/Pantograph/Delate.lean @@ -37,7 +37,7 @@ def analyzeProjection (env: Environment) (e: Expr): Projection := def anonymousLevel : Level := .mvar ⟨.anonymous⟩ @[export pantograph_expr_proj_to_app] -def exprProjToApp (env: Environment) (e: Expr): Expr := +def exprProjToApp (env : Environment) (e : Expr) : Expr := let anon : Expr := .mvar ⟨.anonymous⟩ match analyzeProjection env e with | .field projector numParams => @@ -72,12 +72,12 @@ def unfoldAuxLemmas : Expr → CoreM Expr := /-- Unfold all matcher applications -/ @[export pantograph_unfold_matchers_m] def unfoldMatchers (expr : Expr) : CoreM Expr := - Core.transform expr λ e' => do - let .some mapp ← Meta.matchMatcherApp? e' | return .continue e' + Core.transform expr λ e => do + let .some mapp ← Meta.matchMatcherApp? e | return .continue e let .some matcherInfo := (← getEnv).find? mapp.matcherName | panic! "Matcher must exist" let f ← Meta.instantiateValueLevelParams matcherInfo mapp.matcherLevels.toList let mdata := KVMap.empty.insert `matcher (DataValue.ofName mapp.matcherName) - return .visit $ .mdata mdata (f.betaRev e'.getAppRevArgs (useZeta := true)) + return .visit $ .mdata mdata (f.betaRev e.getAppRevArgs (useZeta := true)) /-- Force the instantiation of delayed metavariables even if they cannot be fully @@ -94,10 +94,9 @@ This function ensures any metavariable in the result is either 1. Delayed assigned with its pending mvar not assigned in any form 2. Not assigned (delay or not) -/ -partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := - --let padding := String.join $ List.replicate level "│ " - withTraceNode `Pantograph.Delate (λ _ex => return m!":= {← Meta.ppExpr eOrig}") do - let mut result ← Meta.transform (← instantiateMVars eOrig) +partial def instantiateDelayedMVars (expr : Expr) : MetaM Expr := + withTraceNode `Pantograph.Delate (λ _ex => return m!":= {← Meta.ppExpr expr}") do + let mut result ← Meta.transform (← instantiateMVars expr) (pre := fun e => e.withApp fun f args => do let .mvar mvarId := f | return .continue trace[Pantograph.Delate] "V {e}" @@ -127,7 +126,7 @@ partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := trace[Pantograph.Delate]"MD ?{mvarId.name} := ?{mvarIdPending.name} [{substTableStr}]" if args.size < fvars.size then - throwError "Not enough arguments to instantiate a delay assigned mvar. This is due to bad implementations of a tactic: {args.size} < {fvars.size}. Expr: {toString e}; Origin: {toString eOrig}" + throwError "Not enough arguments to instantiate a delay assigned mvar. This is due to bad implementations of a tactic: {args.size} < {fvars.size}. Expr: {toString e}; Origin: {toString expr}" if !args.isEmpty then trace[Pantograph.Delate] "─ Arguments Begin" let args ← args.mapM self @@ -139,7 +138,7 @@ partial def instantiateDelayedMVars (eOrig: Expr) : MetaM Expr := return .done result let pending ← mvarIdPending.withContext do - let inner ← instantiateDelayedMVars (.mvar mvarIdPending) --(level := level + 1) + let inner ← instantiateDelayedMVars (.mvar mvarIdPending) trace[Pantograph.Delate] "Pre: {inner}" pure <| (← inner.abstractM fvars).instantiateRev args From cb1082c7c7eea7d117fd17940a4f172278372280 Mon Sep 17 00:00:00 2001 From: Leni Aniva <v@leni.sh> Date: Mon, 17 Mar 2025 12:14:16 -0700 Subject: [PATCH 8/8] chore: More code cleanup --- Pantograph/Delate.lean | 110 ++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/Pantograph/Delate.lean b/Pantograph/Delate.lean index 6e47799..efb1008 100644 --- a/Pantograph/Delate.lean +++ b/Pantograph/Delate.lean @@ -68,7 +68,7 @@ def _root_.Lean.Name.isAuxLemma (n : Lean.Name) : Bool := n matches .num (.str _ /-- Unfold all lemmas created by `Lean.Meta.mkAuxLemma`. These end in `_auxLemma.nn` where `nn` is a number. -/ @[export pantograph_unfold_aux_lemmas_m] def unfoldAuxLemmas : Expr → CoreM Expr := - (Lean.Meta.deltaExpand · Lean.Name.isAuxLemma) + (Meta.deltaExpand · Lean.Name.isAuxLemma) /-- Unfold all matcher applications -/ @[export pantograph_unfold_matchers_m] def unfoldMatchers (expr : Expr) : CoreM Expr := @@ -97,66 +97,66 @@ This function ensures any metavariable in the result is either partial def instantiateDelayedMVars (expr : Expr) : MetaM Expr := withTraceNode `Pantograph.Delate (λ _ex => return m!":= {← Meta.ppExpr expr}") do let mut result ← Meta.transform (← instantiateMVars expr) - (pre := fun e => e.withApp fun f args => do - let .mvar mvarId := f | return .continue - trace[Pantograph.Delate] "V {e}" - let mvarDecl ← mvarId.getDecl + λ e => e.withApp fun f args => do + let .mvar mvarId := f | return .continue + trace[Pantograph.Delate] "V {e}" + let mvarDecl ← mvarId.getDecl - -- This is critical to maintaining the interdependency of metavariables. - -- Without setting `.syntheticOpaque`, Lean's metavariable elimination - -- system will not make the necessary delayed assigned mvars in case of - -- nested mvars. - mvarId.setKind .syntheticOpaque + -- This is critical to maintaining the interdependency of metavariables. + -- Without setting `.syntheticOpaque`, Lean's metavariable elimination + -- system will not make the necessary delayed assigned mvars in case of + -- nested mvars. + mvarId.setKind .syntheticOpaque - mvarId.withContext do - let lctx ← MonadLCtx.getLCtx - if mvarDecl.lctx.any (λ decl => !lctx.contains decl.fvarId) then - let violations := mvarDecl.lctx.decls.foldl (λ acc decl? => match decl? with - | .some decl => if lctx.contains decl.fvarId then acc else acc ++ [decl.fvarId.name] - | .none => acc) [] - panic! s!"In the context of {mvarId.name}, there are local context variable violations: {violations}" + mvarId.withContext do + let lctx ← MonadLCtx.getLCtx + if mvarDecl.lctx.any (λ decl => !lctx.contains decl.fvarId) then + let violations := mvarDecl.lctx.decls.foldl (λ acc decl? => match decl? with + | .some decl => if lctx.contains decl.fvarId then acc else acc ++ [decl.fvarId.name] + | .none => acc) [] + panic! s!"In the context of {mvarId.name}, there are local context variable violations: {violations}" - if let .some assign ← getExprMVarAssignment? mvarId then - trace[Pantograph.Delate] "A ?{mvarId.name}" - assert! !(← mvarId.isDelayedAssigned) - return .visit (mkAppN assign args) - else if let some { fvars, mvarIdPending } ← getDelayedMVarAssignment? mvarId then - if ← isTracingEnabledFor `Pantograph.Delate then - let substTableStr := String.intercalate ", " $ Array.zipWith fvars args (λ fvar assign => s!"{fvar.fvarId!.name} := {assign}") |>.toList - trace[Pantograph.Delate]"MD ?{mvarId.name} := ?{mvarIdPending.name} [{substTableStr}]" + if let .some assign ← getExprMVarAssignment? mvarId then + trace[Pantograph.Delate] "A ?{mvarId.name}" + assert! !(← mvarId.isDelayedAssigned) + return .visit (mkAppN assign args) + else if let some { fvars, mvarIdPending } ← getDelayedMVarAssignment? mvarId then + if ← isTracingEnabledFor `Pantograph.Delate then + let substTableStr := String.intercalate ", " $ Array.zipWith fvars args (λ fvar assign => s!"{fvar.fvarId!.name} := {assign}") |>.toList + trace[Pantograph.Delate]"MD ?{mvarId.name} := ?{mvarIdPending.name} [{substTableStr}]" - if args.size < fvars.size then - throwError "Not enough arguments to instantiate a delay assigned mvar. This is due to bad implementations of a tactic: {args.size} < {fvars.size}. Expr: {toString e}; Origin: {toString expr}" - if !args.isEmpty then - trace[Pantograph.Delate] "─ Arguments Begin" - let args ← args.mapM self - if !args.isEmpty then - trace[Pantograph.Delate] "─ Arguments End" - if !(← mvarIdPending.isAssignedOrDelayedAssigned) then - trace[Pantograph.Delate] "T1" - let result := mkAppN f args - return .done result - - let pending ← mvarIdPending.withContext do - let inner ← instantiateDelayedMVars (.mvar mvarIdPending) - trace[Pantograph.Delate] "Pre: {inner}" - pure <| (← inner.abstractM fvars).instantiateRev args - - -- Tail arguments - let result := mkAppRange pending fvars.size args.size args - trace[Pantograph.Delate] "MD {result}" + if args.size < fvars.size then + throwError "Not enough arguments to instantiate a delay assigned mvar. This is due to bad implementations of a tactic: {args.size} < {fvars.size}. Expr: {toString e}; Origin: {toString expr}" + if !args.isEmpty then + trace[Pantograph.Delate] "─ Arguments Begin" + let args ← args.mapM self + if !args.isEmpty then + trace[Pantograph.Delate] "─ Arguments End" + if !(← mvarIdPending.isAssignedOrDelayedAssigned) then + trace[Pantograph.Delate] "T1" + let result := mkAppN f args return .done result - else - assert! !(← mvarId.isAssigned) - assert! !(← mvarId.isDelayedAssigned) - if !args.isEmpty then - trace[Pantograph.Delate] "─ Arguments Begin" - let args ← args.mapM self - if !args.isEmpty then - trace[Pantograph.Delate] "─ Arguments End" - trace[Pantograph.Delate] "M ?{mvarId.name}" - return .done (mkAppN f args)) + let pending ← mvarIdPending.withContext do + let inner ← instantiateDelayedMVars (.mvar mvarIdPending) + trace[Pantograph.Delate] "Pre: {inner}" + pure <| (← inner.abstractM fvars).instantiateRev args + + -- Tail arguments + let result := mkAppRange pending fvars.size args.size args + trace[Pantograph.Delate] "MD {result}" + return .done result + else + assert! !(← mvarId.isAssigned) + assert! !(← mvarId.isDelayedAssigned) + if !args.isEmpty then + trace[Pantograph.Delate] "─ Arguments Begin" + let args ← args.mapM self + if !args.isEmpty then + trace[Pantograph.Delate] "─ Arguments End" + + trace[Pantograph.Delate] "M ?{mvarId.name}" + return .done (mkAppN f args) trace[Pantoraph.Delate] "Result {result}" return result where