diff --git a/Pantograph.lean b/Pantograph.lean index 97f03f4..70d64b9 100644 --- a/Pantograph.lean +++ b/Pantograph.lean @@ -114,12 +114,15 @@ def execute (command: Protocol.Command): MainM Lean.Json := do match state.goalStates.find? args.stateId with | .none => return .error $ errorIndex s!"Invalid state index {args.stateId}" | .some goalState => do - let nextGoalState?: Except _ GoalState ← match args.tactic?, args.expr? with - | .some tactic, .none => do + let nextGoalState?: Except _ GoalState ← match args.tactic?, args.expr?, args.have? with + | .some tactic, .none, .none => do pure ( Except.ok (← goalTactic goalState args.goalId tactic)) - | .none, .some expr => do - pure ( Except.ok (← goalTryAssign goalState args.goalId expr)) - | _, _ => pure (Except.error <| errorI "arguments" "Exactly one of {tactic, expr} must be supplied") + | .none, .some expr, .none => do + pure ( Except.ok (← goalAssign goalState args.goalId expr)) + | .none, .none, .some type => do + let binderName := args.binderName?.getD "" + pure ( Except.ok (← goalHave goalState args.goalId binderName type)) + | _, _, _ => pure (Except.error <| errorI "arguments" "Exactly one of {tactic, expr, have} must be supplied") match nextGoalState? with | .error error => return .error error | .ok (.success nextGoalState) => diff --git a/Pantograph/Goal.lean b/Pantograph/Goal.lean index 5b6e467..04fa0d5 100644 --- a/Pantograph/Goal.lean +++ b/Pantograph/Goal.lean @@ -1,3 +1,8 @@ +/- +Functions for handling metavariables + +All the functions starting with `try` resume their inner monadic state. +-/ import Pantograph.Protocol import Lean diff --git a/Pantograph/Library.lean b/Pantograph/Library.lean index 1d31e97..04a8d71 100644 --- a/Pantograph/Library.lean +++ b/Pantograph/Library.lean @@ -162,10 +162,14 @@ def goalStartExpr (expr: String): Lean.CoreM (Protocol.CR GoalState) := def goalTactic (state: GoalState) (goalId: Nat) (tactic: String): Lean.CoreM TacticResult := runTermElabM <| GoalState.tryTactic state goalId tactic -@[export pantograph_goal_try_assign_m] -def goalTryAssign (state: GoalState) (goalId: Nat) (expr: String): Lean.CoreM TacticResult := +@[export pantograph_goal_assign_m] +def goalAssign (state: GoalState) (goalId: Nat) (expr: String): Lean.CoreM TacticResult := runTermElabM <| GoalState.tryAssign state goalId expr +@[export pantograph_goal_have_m] +def goalHave (state: GoalState) (goalId: Nat) (binderName: String) (type: String): Lean.CoreM TacticResult := + runTermElabM <| GoalState.tryHave state goalId binderName type + @[export pantograph_goal_continue] def goalContinue (target: GoalState) (branch: GoalState): Except String GoalState := target.continue branch diff --git a/Pantograph/Protocol.lean b/Pantograph/Protocol.lean index 6ee3354..3055136 100644 --- a/Pantograph/Protocol.lean +++ b/Pantograph/Protocol.lean @@ -201,6 +201,11 @@ structure GoalTactic where -- One of the fields here must be filled tactic?: Option String := .none expr?: Option String := .none + have?: Option String := .none + + -- In case of the `have` tactic, the new free variable name + binderName?: Option String := .none + deriving Lean.FromJson structure GoalTacticResult where -- The next goal state id. Existence of this field shows success