|
|
|
@ -341,11 +341,36 @@ elab "LemmaTab" category:str : command => do
|
|
|
|
|
|
|
|
|
|
|
|
/-! # Exercise Statement -/
|
|
|
|
/-! # Exercise Statement -/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/-- You can write `Statement add_comm (preample := simp) .... := by` which
|
|
|
|
|
|
|
|
will automatically execute the given tactic sequence before the exercise
|
|
|
|
|
|
|
|
is handed to the player.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A common example is to use
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
refine { carrier := M, ?.. }
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
in exercises, where the statement is a structure, to fill in all the data fields.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For example in "Show that all matrices with first column zero form a submodule",
|
|
|
|
|
|
|
|
you could provide the set of all these matrices as `carrier` and the player will receive
|
|
|
|
|
|
|
|
all the `Prop`-valued fields as goals.
|
|
|
|
|
|
|
|
-/
|
|
|
|
|
|
|
|
syntax preampleArg := atomic(" (preample := " withoutPosition(tacticSeq) ")")
|
|
|
|
|
|
|
|
|
|
|
|
/-- Define the statement of the current level. -/
|
|
|
|
/-- Define the statement of the current level. -/
|
|
|
|
elab doc:docComment ? attrs:Parser.Term.attributes ?
|
|
|
|
elab doc:docComment ? attrs:Parser.Term.attributes ?
|
|
|
|
"Statement" statementName:ident ? sig:declSig val:declVal : command => do
|
|
|
|
"Statement" statementName:ident ? preample:preampleArg ? sig:declSig val:declVal : command => do
|
|
|
|
let lvlIdx ← getCurLevelIdx
|
|
|
|
let lvlIdx ← getCurLevelIdx
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- add an optional tactic sequence that the engine executes before the game starts
|
|
|
|
|
|
|
|
let preampleSeq : TSyntax `Lean.Parser.Tactic.tacticSeq ← match preample with
|
|
|
|
|
|
|
|
| none => `(Parser.Tactic.tacticSeq|skip)
|
|
|
|
|
|
|
|
| some x => match x with
|
|
|
|
|
|
|
|
| `(preampleArg| (preample := $tac)) => pure tac
|
|
|
|
|
|
|
|
| _ => `(Parser.Tactic.tacticSeq|skip)
|
|
|
|
|
|
|
|
|
|
|
|
let docContent ← parseDocComment doc
|
|
|
|
let docContent ← parseDocComment doc
|
|
|
|
let docContent ← match docContent with
|
|
|
|
let docContent ← match docContent with
|
|
|
|
| none => pure none
|
|
|
|
| none => pure none
|
|
|
|
@ -383,17 +408,17 @@ elab doc:docComment ? attrs:Parser.Term.attributes ?
|
|
|
|
-- in that case.
|
|
|
|
-- in that case.
|
|
|
|
logWarningAt name (m!"Environment already contains {fullName}! Only the existing " ++
|
|
|
|
logWarningAt name (m!"Environment already contains {fullName}! Only the existing " ++
|
|
|
|
m!"statement will be available in later levels:\n\n{origType}")
|
|
|
|
m!"statement will be available in later levels:\n\n{origType}")
|
|
|
|
let thmStatement ← `(command| $[$doc]? $[$attrs:attributes]? theorem $defaultDeclName $sig := by {let_intros; $(⟨tacticStx⟩)})
|
|
|
|
let thmStatement ← `(command| $[$doc]? $[$attrs:attributes]? theorem $defaultDeclName $sig := by {let_intros; $(⟨preampleSeq⟩); $(⟨tacticStx⟩)})
|
|
|
|
elabCommand thmStatement
|
|
|
|
elabCommand thmStatement
|
|
|
|
-- Check that statement has a docs entry.
|
|
|
|
-- Check that statement has a docs entry.
|
|
|
|
checkInventoryDoc .Lemma name (name := fullName) (template := docContent)
|
|
|
|
checkInventoryDoc .Lemma name (name := fullName) (template := docContent)
|
|
|
|
else
|
|
|
|
else
|
|
|
|
let thmStatement ← `(command| $[$doc]? $[$attrs:attributes]? theorem $name $sig := by {let_intros; $(⟨tacticStx⟩)})
|
|
|
|
let thmStatement ← `(command| $[$doc]? $[$attrs:attributes]? theorem $name $sig := by {let_intros; $(⟨preampleSeq⟩); $(⟨tacticStx⟩)})
|
|
|
|
elabCommand thmStatement
|
|
|
|
elabCommand thmStatement
|
|
|
|
-- Check that statement has a docs entry.
|
|
|
|
-- Check that statement has a docs entry.
|
|
|
|
checkInventoryDoc .Lemma name (name := fullName) (template := docContent)
|
|
|
|
checkInventoryDoc .Lemma name (name := fullName) (template := docContent)
|
|
|
|
| none =>
|
|
|
|
| none =>
|
|
|
|
let thmStatement ← `(command| $[$doc]? $[$attrs:attributes]? theorem $defaultDeclName $sig := by {let_intros; $(⟨tacticStx⟩)})
|
|
|
|
let thmStatement ← `(command| $[$doc]? $[$attrs:attributes]? theorem $defaultDeclName $sig := by {let_intros; $(⟨preampleSeq⟩); $(⟨tacticStx⟩)})
|
|
|
|
elabCommand thmStatement
|
|
|
|
elabCommand thmStatement
|
|
|
|
|
|
|
|
|
|
|
|
let msgs := (← get).messages
|
|
|
|
let msgs := (← get).messages
|
|
|
|
@ -468,6 +493,7 @@ elab doc:docComment ? attrs:Parser.Term.attributes ?
|
|
|
|
modifyCurLevel fun level => pure { level with
|
|
|
|
modifyCurLevel fun level => pure { level with
|
|
|
|
module := env.header.mainModule
|
|
|
|
module := env.header.mainModule
|
|
|
|
goal := sig,
|
|
|
|
goal := sig,
|
|
|
|
|
|
|
|
preample := preampleSeq
|
|
|
|
scope := scope,
|
|
|
|
scope := scope,
|
|
|
|
descrText := docContent
|
|
|
|
descrText := docContent
|
|
|
|
statementName := match statementName with
|
|
|
|
statementName := match statementName with
|
|
|
|
@ -477,7 +503,8 @@ elab doc:docComment ? attrs:Parser.Term.attributes ?
|
|
|
|
hints := hints
|
|
|
|
hints := hints
|
|
|
|
tactics := {level.tactics with used := usedInventory.tactics.toArray}
|
|
|
|
tactics := {level.tactics with used := usedInventory.tactics.toArray}
|
|
|
|
definitions := {level.definitions with used := usedInventory.definitions.toArray}
|
|
|
|
definitions := {level.definitions with used := usedInventory.definitions.toArray}
|
|
|
|
lemmas := {level.lemmas with used := usedInventory.lemmas.toArray} }
|
|
|
|
lemmas := {level.lemmas with used := usedInventory.lemmas.toArray}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/-! # Hints -/
|
|
|
|
/-! # Hints -/
|
|
|
|
|
|
|
|
|
|
|
|
|