use json file to get levelInfo

nowatchdog
Alexander Bentkamp 3 years ago
parent 464a2ced90
commit 422f54e8f7

@ -18,7 +18,7 @@ private def mkEOI (pos : String.Pos) : Syntax :=
mkNode ``Command.eoi #[atom]
partial def parseTactic (inputCtx : InputContext) (pmctx : ParserModuleContext)
(mps : ModuleParserState) (messages : MessageLog) (couldBeEndSnap : Bool) :
(mps : ModuleParserState) (messages : MessageLog) :
Syntax × ModuleParserState × MessageLog × String.Pos := Id.run do
let mut pos := mps.pos
let mut recovering := mps.recovering
@ -66,8 +66,7 @@ structure GameWorkerState :=
2: give errors
-/
difficulty : Nat
-- /-- The name of the theorem to be proven in this level. -/
-- statementName : Name
levelInfo : LevelInfo
deriving ToJson, FromJson
abbrev GameWorkerM := StateT GameWorkerState Server.FileWorker.WorkerM
@ -89,20 +88,21 @@ def addErrorMessage (info : SourceInfo) (inputCtx : Parser.InputContext) (s : Me
/-- Find all tactics in syntax object that are forbidden according to a
set `allowed` of allowed tactics. -/
partial def findForbiddenTactics (inputCtx : Parser.InputContext)
(gameWorkerState : GameWorkerState) (level : GameLevel) (stx : Syntax) :
(gameWorkerState : GameWorkerState) (stx : Syntax) :
Elab.Command.CommandElabM Unit := do
let levelInfo := gameWorkerState.levelInfo
match stx with
| .missing => return ()
| .node _info _kind args =>
for arg in args do
findForbiddenTactics inputCtx gameWorkerState level arg
findForbiddenTactics inputCtx gameWorkerState arg
| .atom info val =>
-- ignore syntax elements that do not start with a letter
-- and ignore "with" keyword
let allowed := ["with", "fun", "at", "only", "by", "to"]
if 0 < val.length ∧ val.data[0]!.isAlpha ∧ not (allowed.contains val) then
let val := val.dropRightWhile (fun c => c == '!' || c == '?') -- treat `simp?` and `simp!` like `simp`
match level.tactics.tiles.find? (·.name.toString == val) with
match levelInfo.tactics.find? (·.name.toString == val) with
| none =>
-- Note: This case means that the tactic will never be introduced in the game.
match gameWorkerState.inventory.find? (· == val) with
@ -125,10 +125,10 @@ partial def findForbiddenTactics (inputCtx : Parser.InputContext)
let some (.thmInfo ..) := (← getEnv).find? n
| return () -- not a theorem -> ignore
-- Forbid the theorem we are proving currently
if n = level.statementName then
if some n = levelInfo.statementName then
addErrorMessage info inputCtx s!"Structural recursion: you can't use '{n}' to proof itself!"
let lemmasAndDefs := level.lemmas.tiles ++ level.definitions.tiles
let lemmasAndDefs := levelInfo.lemmas ++ levelInfo.definitions
match lemmasAndDefs.find? (fun l => l.name == n) with
| none => addWarningMessage info s!"You have not unlocked the lemma/definition '{n}' yet!"
| some lem =>
@ -202,12 +202,12 @@ def compileProof (inputCtx : Parser.InputContext) (snap : Snapshot) (hasWidgets
currNamespace := scope.currNamespace,
openDecls := scope.openDecls }
let (tacticStx, cmdParserState, msgLog, endOfWhitespace) :=
MyModule.parseTactic inputCtx pmctx snap.mpState snap.msgLog couldBeEndSnap
MyModule.parseTactic inputCtx pmctx snap.mpState snap.msgLog
modify (fun s => { s with messages := msgLog })
parseResultRef.set (tacticStx, cmdParserState)
-- Check for forbidden tactics
findForbiddenTactics inputCtx gameWorkerState level tacticStx
findForbiddenTactics inputCtx gameWorkerState tacticStx
-- Insert invisible `skip` command to make sure we always display the initial goal
let skip := Syntax.node (.original default 0 default endOfWhitespace) ``Lean.Parser.Tactic.skip #[]
@ -468,16 +468,11 @@ section Initialization
return (headerSnap, srcSearchPath)
def initializeWorker (meta : DocumentMeta) (i o e : FS.Stream) (initParams : InitializeParams) (opts : Options)
(gameDir : String) (game : Game) (gameWorkerState : GameWorkerState) : IO (WorkerContext × WorkerState) := do
-- TODO: We misuse the `rootUri` field to the gameName
let rootUri? : Option String := some (toString game.name)
let initParams := {initParams with rootUri?}
(gameDir : String) (gameWorkerState : GameWorkerState) : IO (WorkerContext × WorkerState) := do
let clientHasWidgets := initParams.initializationOptions?.bind (·.hasWidgets?) |>.getD false
let some (levelId : LevelId) := GameServer.levelIdFromFileName? initParams meta.mkInputContext.fileName
| throwServerError "Could not determine level ID"
let level ← loadLevelData gameDir levelId.world levelId.level
let (headerStx, headerTask) ← compileHeader meta o opts (hasWidgets := clientHasWidgets)
gameDir level.module
gameDir gameWorkerState.levelInfo.module
let cancelTk ← CancelToken.new
let ctx :=
{ hIn := i
@ -609,13 +604,21 @@ def initAndRunWorker (i o e : FS.Stream) (opts : Options) (gameDir : String) : I
let _ ← IO.setStderr e
try
let game ← loadGameData gameDir
-- TODO: We misuse the `rootUri` field to the gameName
let rootUri? : Option String := some (toString game.name)
let initParams := {initRequest.param.toLeanInternal with rootUri?}
let some (levelId : LevelId) := GameServer.levelIdFromFileName?
initParams meta.mkInputContext.fileName
| throwServerError s!"Could not determine level ID: {meta.mkInputContext.fileName}"
let levelInfo ← loadLevelData gameDir levelId.world levelId.level
let some initializationOptions := initRequest.param.initializationOptions?
| throwServerError "no initialization options found"
let gameWorkerState : GameWorkerState:= {
inventory := initializationOptions.inventory
difficulty := initializationOptions.difficulty
levelInfo
}
let (ctx, st) ← initializeWorker meta i o e initRequest.param.toLeanInternal opts gameDir game gameWorkerState
let (ctx, st) ← initializeWorker meta i o e initParams opts gameDir gameWorkerState
let _ ← StateRefT'.run (s := st) <| ReaderT.run (r := ctx) <|
StateT.run (s := gameWorkerState) <| (mainLoop)
return (0 : UInt32)

Loading…
Cancel
Save