|
|
|
@ -15,64 +15,64 @@ open Lean Meta Elab Command Term
|
|
|
|
|
|
|
|
|
|
/-- Create a game with the given identifier as name. -/
|
|
|
|
|
elab "Game" n:str : command => do
|
|
|
|
|
gameExt.set {name := n.getString}
|
|
|
|
|
let name := n.getString
|
|
|
|
|
setCurGameId name
|
|
|
|
|
if (← getGame? name).isNone then
|
|
|
|
|
insertGame name {name}
|
|
|
|
|
|
|
|
|
|
/-- Create a World -/
|
|
|
|
|
elab "World" n:str : command => do
|
|
|
|
|
let name := n.getString
|
|
|
|
|
setCurWorldId name
|
|
|
|
|
if ¬ (← getCurGame).worlds.nodes.contains name then
|
|
|
|
|
addWorld {name}
|
|
|
|
|
|
|
|
|
|
/-- Define the current level number. -/
|
|
|
|
|
elab "Level" n:num : command => do
|
|
|
|
|
let idx := n.getNat
|
|
|
|
|
setCurLevelIdx idx
|
|
|
|
|
levelsExt.insert idx {index := idx}
|
|
|
|
|
elab "Level" level:num : command => do
|
|
|
|
|
let level := level.getNat
|
|
|
|
|
setCurLevelIdx level
|
|
|
|
|
addLevel {index := level}
|
|
|
|
|
|
|
|
|
|
/-- Define the title of the current game or current level if some
|
|
|
|
|
building a level. -/
|
|
|
|
|
/-- Define the title of the current game/world/level. -/
|
|
|
|
|
elab "Title" t:str : command => do
|
|
|
|
|
let lvlIdx ← getCurLevelIdx
|
|
|
|
|
if lvlIdx > 0 then
|
|
|
|
|
let some lvl := (← levelsExt.find? lvlIdx) | throwError "Unable to find level"
|
|
|
|
|
levelsExt.update lvlIdx {lvl with title := t.getString}
|
|
|
|
|
else
|
|
|
|
|
gameExt.set {← gameExt.get with title := t.getString}
|
|
|
|
|
match ← getCurLayer with
|
|
|
|
|
| .Level => modifyCurLevel fun level => pure {level with title := t.getString}
|
|
|
|
|
| .World => modifyCurWorld fun world => pure {world with title := t.getString}
|
|
|
|
|
| .Game => modifyCurGame fun game => pure {game with title := t.getString}
|
|
|
|
|
|
|
|
|
|
/-- Define the introduction of the current game or current level if some
|
|
|
|
|
building a level. -/
|
|
|
|
|
/-- Define the introduction of the current game/world/level. -/
|
|
|
|
|
elab "Introduction" t:str : command => do
|
|
|
|
|
let lvlIdx ← getCurLevelIdx
|
|
|
|
|
if lvlIdx > 0 then
|
|
|
|
|
let some lvl := (← levelsExt.find? lvlIdx) | throwError "Unable to find level"
|
|
|
|
|
levelsExt.update lvlIdx {lvl with introduction := t.getString}
|
|
|
|
|
else
|
|
|
|
|
gameExt.set {← gameExt.get with introduction := t.getString}
|
|
|
|
|
match ← getCurLayer with
|
|
|
|
|
| .Level => modifyCurLevel fun level => pure {level with introduction := t.getString}
|
|
|
|
|
| .World => modifyCurWorld fun world => pure {world with introduction := t.getString}
|
|
|
|
|
| .Game => modifyCurGame fun game => pure {game with introduction := t.getString}
|
|
|
|
|
|
|
|
|
|
/-- Define the statement of the current level. -/
|
|
|
|
|
elab "Statement" sig:declSig val:declVal : command => do
|
|
|
|
|
let lvlIdx ← getCurLevelIdx
|
|
|
|
|
let declName : Name := (← gameExt.get).name ++ ("level" ++ toString lvlIdx : String)
|
|
|
|
|
let declName : Name := (← getCurGame).name ++ (← getCurWorld).name ++ ("level" ++ toString lvlIdx : String)
|
|
|
|
|
elabCommand (← `(theorem $(mkIdent declName) $sig $val))
|
|
|
|
|
levelsExt.update lvlIdx {← getCurLevel with goal := sig}
|
|
|
|
|
|
|
|
|
|
modifyCurLevel fun level => pure {level with goal := sig}
|
|
|
|
|
|
|
|
|
|
/-- Define the conclusion of the current game or current level if some
|
|
|
|
|
building a level. -/
|
|
|
|
|
elab "Conclusion" t:str : command => do
|
|
|
|
|
let lvlIdx ← getCurLevelIdx
|
|
|
|
|
if lvlIdx > 0 then
|
|
|
|
|
let some lvl := (← levelsExt.find? lvlIdx) | throwError "Unable to find level"
|
|
|
|
|
levelsExt.update lvlIdx {lvl with conclusion := t.getString}
|
|
|
|
|
else
|
|
|
|
|
gameExt.set {← gameExt.get with conclusion := t.getString}
|
|
|
|
|
match ← getCurLayer with
|
|
|
|
|
| .Level => modifyCurLevel fun level => pure {level with conclusion := t.getString}
|
|
|
|
|
| .World => modifyCurWorld fun world => pure {world with conclusion := t.getString}
|
|
|
|
|
| .Game => modifyCurGame fun game => pure {game with conclusion := t.getString}
|
|
|
|
|
|
|
|
|
|
/-- Print current game for debugging purposes. -/
|
|
|
|
|
elab "PrintCurGame" : command => do
|
|
|
|
|
logInfo (repr (← gameExt.get))
|
|
|
|
|
-- /-- Print current game for debugging purposes. -/
|
|
|
|
|
-- elab "PrintCurGame" : command => do
|
|
|
|
|
-- logInfo (toJson (← getCurGame))
|
|
|
|
|
|
|
|
|
|
/-- Print current level for debugging purposes. -/
|
|
|
|
|
elab "PrintCurLevel" : command => do
|
|
|
|
|
match ← levelsExt.find? (← getCurLevelIdx) with
|
|
|
|
|
| some lvl => logInfo (repr lvl)
|
|
|
|
|
| none => logInfo "Could not find level"
|
|
|
|
|
logInfo (repr (← getCurLevel))
|
|
|
|
|
|
|
|
|
|
/-- Print levels for debugging purposes. -/
|
|
|
|
|
-- /-- Print levels for debugging purposes. -/
|
|
|
|
|
elab "PrintLevels" : command => do
|
|
|
|
|
logInfo $ repr $ (levelsExt.getState (← getEnv)).toList.map (·.fst)
|
|
|
|
|
logInfo $ repr $ (← getCurWorld).levels.toArray
|
|
|
|
|
|
|
|
|
|
end metadata
|
|
|
|
|
|
|
|
|
@ -93,7 +93,7 @@ def getType : TSyntax `mydecl → Term
|
|
|
|
|
|
|
|
|
|
/-- From a term `s` and a list of pairs `(i, t) ; Ident × Term`, create the syntax
|
|
|
|
|
where `s` is preceded with universal quantifiers `∀ i : t`. -/
|
|
|
|
|
def mkGoalSyntax (s : Term) : List (Ident × Term) → MacroM Term
|
|
|
|
|
def mkGoalSyntax (s : Term) : List (Ident × Term) → MacroM Term
|
|
|
|
|
| (n, t)::tail => do return (← `(∀ $n : $t, $(← mkGoalSyntax s tail)))
|
|
|
|
|
| [] => return s
|
|
|
|
|
|
|
|
|
@ -103,12 +103,10 @@ local elab "Message'" decls:mydecl* ":" goal:term "=>" msg:str : command => do
|
|
|
|
|
let g ← liftTermElabM do (return ← instantiateMVars (← elabTerm g none))
|
|
|
|
|
let (ctx_size, normalized_goal) ← liftTermElabM do
|
|
|
|
|
let msg_mvar ← mkFreshExprMVar g MetavarKind.syntheticOpaque
|
|
|
|
|
msg_mvar.mvarId!.withContext do
|
|
|
|
|
msg_mvar.mvarId!.withContext do
|
|
|
|
|
let (_, msg_mvar) ← msg_mvar.mvarId!.introNP decls.size
|
|
|
|
|
return ((← msg_mvar.getDecl).lctx.size, (← normalizedRevertExpr msg_mvar))
|
|
|
|
|
let lvlIdx ← getCurLevelIdx
|
|
|
|
|
let lvl ← getCurLevel
|
|
|
|
|
levelsExt.update lvlIdx {lvl with messages := lvl.messages.push {
|
|
|
|
|
modifyCurLevel fun level => pure {level with messages := level.messages.push {
|
|
|
|
|
ctx_size := ctx_size,
|
|
|
|
|
normalized_goal := normalized_goal,
|
|
|
|
|
intro_nb := decls.size,
|
|
|
|
@ -123,12 +121,12 @@ macro "Message" decls:mydecl* ":" goal:term "=>" msg:str : command => do
|
|
|
|
|
|
|
|
|
|
/-- Declare a documentation entry for some tactic.
|
|
|
|
|
Expect an identifier and then a string literal. -/
|
|
|
|
|
elab "TacticDoc" name:ident content:str : command =>
|
|
|
|
|
elab "TacticDoc" name:ident content:str : command =>
|
|
|
|
|
modifyEnv (tacticDocExt.addEntry · {
|
|
|
|
|
name := name.getId,
|
|
|
|
|
name := name.getId,
|
|
|
|
|
content := content.getString })
|
|
|
|
|
|
|
|
|
|
/-- Declare a set of tactic documentation entries.
|
|
|
|
|
/-- Declare a set of tactic documentation entries.
|
|
|
|
|
Expect an identifier used as the set name then `:=` and a
|
|
|
|
|
space separated list of identifiers.
|
|
|
|
|
-/
|
|
|
|
@ -141,13 +139,13 @@ elab "TacticSet" name:ident ":=" args:ident* : command => do
|
|
|
|
|
| some doc => entries := entries.push doc
|
|
|
|
|
| none => throwError "Documentation for tactic {name} wasn't found."
|
|
|
|
|
modifyEnv (tacticSetExt.addEntry · {
|
|
|
|
|
name := name.getId,
|
|
|
|
|
name := name.getId,
|
|
|
|
|
tactics := entries })
|
|
|
|
|
|
|
|
|
|
instance : Quote TacticDocEntry `term :=
|
|
|
|
|
⟨λ entry => Syntax.mkCApp ``TacticDocEntry.mk #[quote entry.name, quote entry.content]⟩
|
|
|
|
|
|
|
|
|
|
/-- Declare the list of tactics that will be displayed in the current level.
|
|
|
|
|
/-- Declare the list of tactics that will be displayed in the current level.
|
|
|
|
|
Expects a space separated list of identifiers that refer to either a tactic doc
|
|
|
|
|
entry or a tactic doc set. -/
|
|
|
|
|
elab "Tactics" args:ident* : command => do
|
|
|
|
@ -162,12 +160,7 @@ elab "Tactics" args:ident* : command => do
|
|
|
|
|
| none => match sets.find? (·.name = name) with
|
|
|
|
|
| some entry => tactics := tactics ++ entry.tactics
|
|
|
|
|
| none => throwError "Tactic doc or tactic set {name} wasn't found."
|
|
|
|
|
let lvlIdx ← getCurLevelIdx
|
|
|
|
|
if lvlIdx > 0 then
|
|
|
|
|
let some lvl := (← levelsExt.find? lvlIdx) | throwError "Unable to find level"
|
|
|
|
|
levelsExt.update lvlIdx {lvl with tactics := tactics}
|
|
|
|
|
else
|
|
|
|
|
throwError "This command can be used only while building a level."
|
|
|
|
|
modifyCurLevel fun level => pure {level with tactics := tactics}
|
|
|
|
|
|
|
|
|
|
/-! ## Lemmas -/
|
|
|
|
|
|
|
|
|
@ -175,14 +168,14 @@ elab "Tactics" args:ident* : command => do
|
|
|
|
|
Expect two identifiers and then a string literal. The first identifier is meant
|
|
|
|
|
as the real name of the lemma while the second is the displayed name. Currently
|
|
|
|
|
the real name isn't used. -/
|
|
|
|
|
elab "LemmaDoc" name:ident "as" userName:ident "in" category:str content:str : command =>
|
|
|
|
|
elab "LemmaDoc" name:ident "as" userName:ident "in" category:str content:str : command =>
|
|
|
|
|
modifyEnv (lemmaDocExt.addEntry · {
|
|
|
|
|
name := name.getId,
|
|
|
|
|
name := name.getId,
|
|
|
|
|
userName := userName.getId,
|
|
|
|
|
category := category.getString,
|
|
|
|
|
content := content.getString })
|
|
|
|
|
|
|
|
|
|
/-- Declare a set of lemma documentation entries.
|
|
|
|
|
/-- Declare a set of lemma documentation entries.
|
|
|
|
|
Expect an identifier used as the set name then `:=` and a
|
|
|
|
|
space separated list of identifiers. -/
|
|
|
|
|
elab "LemmaSet" name:ident ":" title:str ":=" args:ident* : command => do
|
|
|
|
@ -201,7 +194,7 @@ elab "LemmaSet" name:ident ":" title:str ":=" args:ident* : command => do
|
|
|
|
|
instance : Quote LemmaDocEntry `term :=
|
|
|
|
|
⟨λ entry => Syntax.mkCApp ``LemmaDocEntry.mk #[quote entry.name, quote entry.userName, quote entry.category, quote entry.content]⟩
|
|
|
|
|
|
|
|
|
|
/-- Declare the list of lemmas that will be displayed in the current level.
|
|
|
|
|
/-- Declare the list of lemmas that will be displayed in the current level.
|
|
|
|
|
Expects a space separated list of identifiers that refer to either a lemma doc
|
|
|
|
|
entry or a lemma doc set. -/
|
|
|
|
|
elab "Lemmas" args:ident* : command => do
|
|
|
|
@ -216,9 +209,4 @@ elab "Lemmas" args:ident* : command => do
|
|
|
|
|
| none => match sets.find? (·.name = name) with
|
|
|
|
|
| some entry => lemmas := lemmas ++ entry.lemmas
|
|
|
|
|
| none => throwError "Lemma doc or lemma set {name} wasn't found."
|
|
|
|
|
let lvlIdx ← getCurLevelIdx
|
|
|
|
|
if lvlIdx > 0 then
|
|
|
|
|
let some lvl := (← levelsExt.find? lvlIdx) | throwError "Unable to find level"
|
|
|
|
|
levelsExt.update lvlIdx {lvl with lemmas := lemmas}
|
|
|
|
|
else
|
|
|
|
|
throwError "This command can be used only while building a level."
|
|
|
|
|
modifyCurLevel fun level => pure {level with lemmas := lemmas}
|
|
|
|
|