Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: frontend & server support for plugins #6893

Merged
merged 1 commit into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Lean/Elab/Frontend.lean
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,14 @@ def runFrontend
(ileanFileName? : Option String := none)
(jsonOutput : Bool := false)
(errorOnKinds : Array Name := #[])
(plugins : Array System.FilePath := #[])
: IO (Environment × Bool) := do
let startTime := (← IO.monoNanosNow).toFloat / 1000000000
let inputCtx := Parser.mkInputContext input fileName
let opts := Language.Lean.internal.cmdlineSnapshots.setIfNotSet opts true
let ctx := { inputCtx with }
let processor := Language.Lean.process
let snap ← processor (fun _ => pure <| .ok { mainModuleName, opts, trustLevel }) none ctx
let snap ← processor (fun _ => pure <| .ok { mainModuleName, opts, trustLevel, plugins }) none ctx
let snaps := Language.toSnapshotTree snap
let severityOverrides := errorOnKinds.foldl (·.insert · .error) {}
let hasErrors ← snaps.runAndReport opts jsonOutput severityOverrides
Expand Down
5 changes: 3 additions & 2 deletions src/Lean/Elab/Import.lean
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ def headerToImports (header : Syntax) : Array Import :=
{ module := id, runtimeOnly := runtime }

def processHeader (header : Syntax) (opts : Options) (messages : MessageLog)
(inputCtx : Parser.InputContext) (trustLevel : UInt32 := 0) (leakEnv := false)
(inputCtx : Parser.InputContext) (trustLevel : UInt32 := 0)
(plugins : Array System.FilePath := #[]) (leakEnv := false)
: IO (Environment × MessageLog) := do
try
let env ← importModules (leakEnv := leakEnv) (headerToImports header) opts trustLevel
let env ← importModules (leakEnv := leakEnv) (headerToImports header) opts trustLevel plugins
pure (env, messages)
catch e =>
let env ← mkEmptyEnvironment
Expand Down
5 changes: 4 additions & 1 deletion src/Lean/Environment.lean
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Lean.Util.FindExpr
import Lean.Util.Profile
import Lean.Util.InstantiateLevelParams
import Lean.PrivateName
import Lean.LoadDynlib

/-!
# Note [Environment Branches]
Expand Down Expand Up @@ -1406,11 +1407,13 @@ def finalizeImport (s : ImportState) (imports : Array Import) (opts : Options) (

@[export lean_import_modules]
def importModules (imports : Array Import) (opts : Options) (trustLevel : UInt32 := 0)
(leakEnv := false) : IO Environment := profileitIO "import" opts do
(plugins : Array System.FilePath := #[]) (leakEnv := false)
: IO Environment := profileitIO "import" opts do
for imp in imports do
if imp.module matches .anonymous then
throw <| IO.userError "import failed, trying to import module with anonymous name"
withImporting do
plugins.forM Lean.loadPlugin
let (_, s) ← importModulesCore imports |>.run
finalizeImport (leakEnv := leakEnv) s imports opts trustLevel

Expand Down
4 changes: 3 additions & 1 deletion src/Lean/Language/Lean.lean
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ structure SetupImportsResult where
opts : Options
/-- Kernel trust level. -/
trustLevel : UInt32 := 0
/-- Lean plugins to load as part of the environment setup. -/
plugins : Array System.FilePath := #[]

/-- Performance option used by cmdline driver. -/
register_builtin_option internal.cmdlineSnapshots : Bool := {
Expand Down Expand Up @@ -414,7 +416,7 @@ where
let startTime := (← IO.monoNanosNow).toFloat / 1000000000
-- allows `headerEnv` to be leaked, which would live until the end of the process anyway
let (headerEnv, msgLog) ← Elab.processHeader (leakEnv := true) stx setup.opts .empty
ctx.toInputContext setup.trustLevel
ctx.toInputContext setup.trustLevel setup.plugins
let stopTime := (← IO.monoNanosNow).toFloat / 1000000000
let diagnostics := (← Snapshot.Diagnostics.ofMessageLog msgLog)
if msgLog.hasErrors then
Expand Down
1 change: 1 addition & 0 deletions src/Lean/Server/FileWorker.lean
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ def setupImports (meta : DocumentMeta) (cmdlineOpts : Options) (chanOut : Std.Ch
return .ok {
mainModuleName
opts
plugins := fileSetupResult.plugins
}

/- Worker initialization sequence. -/
Expand Down
12 changes: 9 additions & 3 deletions src/Lean/Server/FileWorker/SetupFile.lean
Original file line number Diff line number Diff line change
Expand Up @@ -71,30 +71,35 @@ structure FileSetupResult where
srcSearchPath : SearchPath
/-- Additional options from successful setup, or else empty. -/
fileOptions : Options
/-- Lean plugins from successful setup, or else empty. -/
plugins : Array System.FilePath

def FileSetupResult.ofSuccess (pkgSearchPath : SearchPath) (fileOptions : Options)
: IO FileSetupResult := do return {
(plugins : Array System.FilePath) : IO FileSetupResult := do return {
kind := FileSetupResultKind.success
srcSearchPath := ← initSrcSearchPath pkgSearchPath,
fileOptions
fileOptions, plugins
}

def FileSetupResult.ofNoLakefile : IO FileSetupResult := do return {
kind := FileSetupResultKind.noLakefile
srcSearchPath := ← initSrcSearchPath
fileOptions := Options.empty
plugins := #[]
}

def FileSetupResult.ofImportsOutOfDate : IO FileSetupResult := do return {
kind := FileSetupResultKind.importsOutOfDate
srcSearchPath := ← initSrcSearchPath
fileOptions := Options.empty
plugins := #[]
}

def FileSetupResult.ofError (msg : String) : IO FileSetupResult := do return {
kind := FileSetupResultKind.error msg
srcSearchPath := ← initSrcSearchPath
fileOptions := Options.empty
plugins := #[]
}

/-- Uses `lake setup-file` to compile dependencies on the fly and add them to `LEAN_PATH`.
Expand Down Expand Up @@ -124,7 +129,8 @@ partial def setupFile (m : DocumentMeta) (imports : Array Import) (handleStderr
initSearchPath (← getBuildDir) info.paths.oleanPath
info.paths.loadDynlibPaths.forM loadDynlib
let pkgSearchPath ← info.paths.srcPath.mapM realPathNormalized
FileSetupResult.ofSuccess pkgSearchPath info.setupOptions.toOptions
let pluginPaths ← info.paths.pluginPaths.mapM realPathNormalized
FileSetupResult.ofSuccess pkgSearchPath info.setupOptions.toOptions pluginPaths
| 2 => -- exit code for lake reporting that there is no lakefile
FileSetupResult.ofNoLakefile
| 3 => -- exit code for `--no-build`
Expand Down
1 change: 1 addition & 0 deletions src/Lean/Util/Paths.lean
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ structure LeanPaths where
oleanPath : SearchPath
srcPath : SearchPath
loadDynlibPaths : Array FilePath := #[]
pluginPaths : Array FilePath := #[]
deriving ToJson, FromJson

def initSrcSearchPath (pkgSearchPath : SearchPath := ∅) : IO SearchPath := do
Expand Down
1 change: 1 addition & 0 deletions src/lake/Lake/CLI/Serve.lean
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def setupFile
oleanPath := ws.leanPath
srcPath := ws.leanSrcPath
loadDynlibPaths := dynlibs
pluginPaths := #[]
: LeanPaths
}
let setupOptions : LeanOptions ← do
Expand Down
2 changes: 2 additions & 0 deletions src/util/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ extern "C" object * lean_run_frontend(
object * ilean_filename,
uint8_t json_output,
object * error_kinds,
object * plugins,
object * w
);
pair_ref<elab_environment, object_ref> run_new_frontend(
Expand All @@ -360,6 +361,7 @@ pair_ref<elab_environment, object_ref> run_new_frontend(
oilean_file_name,
json_output,
error_kinds.to_obj_arg(),
mk_empty_array(),
io_mk_world()
));
}
Expand Down
Loading