lean4-htt/Lake/LeanConfig.lean
2021-10-18 18:01:31 -04:00

72 lines
2.7 KiB
Text

/-
Copyright (c) 2021 Mac Malone. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mac Malone
-/
import Lean.Elab.Frontend
import Lake.Package
import Lake.Attributes
namespace Lake
open Lean System
/-- Main module `Name` of a Lake configuration file. -/
def configModName : Name := `lakefile
/-- The default name of the Lake configuration file (i.e., `lakefile.lean`). -/
def defaultConfigFile : FilePath := "lakefile.lean"
/-- Evaluate a `package` declaration to its respective `PackageConfig`. -/
unsafe def evalPackageDecl (env : Environment) (declName : Name)
(dir : FilePath) (args : List String := []) (leanOpts := Options.empty)
: IO PackageConfig := do
let m := env.evalConstCheck IOPackager leanOpts ``IOPackager declName
if let Except.ok ioPackager := m.run.run then
return ← ioPackager dir args
let m := env.evalConstCheck Packager leanOpts ``Packager declName
if let Except.ok packager := m.run.run then
return packager dir args
let m := env.evalConstCheck PackageConfig leanOpts ``PackageConfig declName
if let Except.ok config := m.run.run then
return config
throw <| IO.userError <|
s!"unexpected type at `{declName}`, " ++
"`Lake.IOPackager`, `Lake.Packager`, or `Lake.PackageConfig` expected"
/-- Evaluate a `script` declaration to its respective `Script`. -/
unsafe def evalScriptDecl
(env : Environment) (declName : Name) (leanOpts := Options.empty) : IO Script :=
IO.ofExcept <| Id.run <| ExceptT.run <|
env.evalConstCheck Script leanOpts ``Script declName
namespace Package
/-- Unsafe implementation of `load`. -/
unsafe def loadUnsafe (dir : FilePath) (args : List String := [])
(configFile := dir / defaultConfigFile) (leanOpts := Options.empty)
: IO Package := do
let input ← IO.FS.readFile configFile
let (env, ok) ← Elab.runFrontend input leanOpts configFile.toString configModName
if ok then
match packageAttr.ext.getState env |>.toList with
| [] =>
throw <| IO.userError
s!"configuration file is missing a `package` declaration"
| [pkgDeclName] =>
let config ← evalPackageDecl env pkgDeclName dir args leanOpts
let scripts ← scriptAttr.ext.getState env |>.foldM (init := {})
fun m d => do m.insert d <| ← evalScriptDecl env d leanOpts
return {dir, config, scripts}
| _ =>
throw <| IO.userError
s!"configuration file has multiple `package` declarations"
else
throw <| IO.userError s!"package configuration `{configFile}` has errors"
/--
Load the package located in
the given directory with the given configuration file.
-/
@[implementedBy loadUnsafe]
constant load (dir : FilePath) (args : List String := [])
(configFile := dir / defaultConfigFile) (leanOpts := Options.empty) : IO Package