@@ -41,12 +41,47 @@ unsafe def evalScriptDecl
41
41
42
42
namespace Package
43
43
44
+ deriving instance BEq, Hashable for Import
45
+
46
+ /- Cache for the imported header environment of Lake configuration files. -/
47
+ initialize importEnvCache : IO.Ref (Std.HashMap (List Import) Environment) ← IO.mkRef {}
48
+
49
+ /-- Like `Lean.Elab.processHeader`, but using `importEnvCache`. -/
50
+ def processHeader (header : Syntax) (messages : MessageLog) (inputCtx : Parser.InputContext) (trustLevel : UInt32)
51
+ : IO (Environment × MessageLog) := do
52
+ try
53
+ let imports := Elab.headerToImports header
54
+ if let some env := (← importEnvCache.get).find? imports then return (env, messages)
55
+ let env ← importModules imports {} trustLevel
56
+ importEnvCache.modify (·.insert imports env)
57
+ return (env, messages)
58
+ catch e =>
59
+ let env ← mkEmptyEnvironment
60
+ let spos := header.getPos?.getD 0
61
+ let pos := inputCtx.fileMap.toPosition spos
62
+ return (env, messages.add { fileName := inputCtx.fileName, data := toString e, pos })
63
+
64
+ /-- Like `Lean.Elab.runFrontend`, but using `importEnvCache`. -/
65
+ def runFrontend (input : String) (opts : Options) (fileName : String) (mainModuleName : Name) (trustLevel : UInt32 := 1024 )
66
+ : IO (Environment × Bool) := do
67
+ let inputCtx := Parser.mkInputContext input fileName
68
+ let (header, parserState, messages) ← Parser.parseHeader inputCtx
69
+ let (env, messages) ← processHeader header messages inputCtx trustLevel
70
+ let env := env.setMainModule mainModuleName
71
+
72
+ let mut commandState := Elab.Command.mkState env {} opts
73
+ let s ← Elab.IO.processCommands inputCtx parserState commandState
74
+ for msg in s.commandState.messages.toList do
75
+ IO.eprint (← msg.toString)
76
+
77
+ pure (s.commandState.env, !s.commandState.messages.hasErrors)
78
+
44
79
/-- Unsafe implementation of `load`. -/
45
80
unsafe def loadUnsafe (dir : FilePath) (args : List String := [])
46
81
(configFile := dir / defaultConfigFile) (leanOpts := Options.empty)
47
82
: IO Package := do
48
83
let input ← IO.FS.readFile configFile
49
- let (env, ok) ← Elab. runFrontend input leanOpts configFile.toString configModName
84
+ let (env, ok) ← runFrontend input leanOpts configFile.toString configModName
50
85
if ok then
51
86
match packageAttr.ext.getState env |>.toList with
52
87
| [] => error s! "configuration file is missing a `package` declaration"
0 commit comments