Skip to content
This repository was archived by the owner on Oct 25, 2023. It is now read-only.

Commit e6a6715

Browse files
committed
refactor: simplify FacetConifg and build monads ala #107
closes #107
1 parent 0ca66ed commit e6a6715

17 files changed

+227
-300
lines changed

Diff for: Lake/Build.lean

+2
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ Authors: Mac Malone
66
import Lake.Build.Monad
77
import Lake.Build.Actions
88
import Lake.Build.IndexTargets
9+
import Lake.Build.Module
10+
import Lake.Build.Package
911
import Lake.Build.Imports

Diff for: Lake/Build/Context.lean

+12-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import Lake.Util.Error
99
import Lake.Util.OptionIO
1010
import Lake.Config.Context
1111
import Lake.Build.Trace
12+
import Lake.Build.Store
13+
import Lake.Build.Topological
1214

1315
open System
1416
namespace Lake
@@ -29,9 +31,18 @@ abbrev BuildT := ReaderT BuildContext
2931
/-- The monad for the Lake build manager. -/
3032
abbrev SchedulerM := BuildT <| LogT BaseIO
3133

32-
/-- The monad for Lake builds. -/
34+
/-- The core monad for Lake builds. -/
3335
abbrev BuildM := BuildT <| MonadLogT BaseIO OptionIO
3436

37+
/-- A transformer to equip a monad with a Lake build store. -/
38+
abbrev BuildStoreT := StateT BuildStore
39+
40+
/-- A transformer for monads that may encounter a build cycle. -/
41+
abbrev BuildCycleT := CycleT BuildKey
42+
43+
/-- A recursive build of a Lake build store that may encounter a cycle. -/
44+
abbrev RecBuildM := BuildCycleT <| BuildStoreT BuildM
45+
3546
instance : MonadError BuildM := ⟨MonadLog.error⟩
3647
instance : MonadLift IO BuildM := ⟨MonadError.runIO⟩
3748

Diff for: Lake/Build/Facets.lean

+14-17
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Lake.Build.TargetTypes
1111
1212
This module declares most of the builtin facets an targets and
1313
their build data builtin facets and targets. Some of these definitions
14-
are needed for configurations, so we define them here before we need to
14+
are needed for configurations, so we define them here before we need to
1515
import said configurations for `BuildInfo`.
1616
-/
1717

@@ -33,62 +33,59 @@ instance (facet : ModuleFacet α) : FamilyDef ModuleData facet.name α :=
3333
instance [FamilyDef ModuleData facet α] : CoeDep Name facet (ModuleFacet α) :=
3434
⟨facet, family_key_eq_type⟩
3535

36-
namespace Module
37-
abbrev leanBinFacet := `lean.bin
38-
abbrev oleanFacet := `olean
39-
abbrev ileanFacet := `ilean
40-
abbrev cFacet := `lean.c
41-
abbrev oFacet := `lean.o
42-
abbrev dynlibFacet := `dynlib
43-
end Module
44-
4536
/--
4637
The core compilation / elaboration of the Lean file via `lean`,
4738
which produce the Lean binaries of the module (i.e., `olean` and `ilean`).
4839
It is thus the facet used by default for building imports of a module.
4940
Also, if the module is not lean-only, it produces `c` files as well.
5041
-/
42+
abbrev Module.leanBinFacet := `lean.bin
5143
module_data lean.bin : ActiveOpaqueTarget
5244

5345
/-- The `olean` file produced by `lean` -/
46+
abbrev Module.oleanFacet := `olean
5447
module_data olean : ActiveFileTarget
5548

5649
/-- The `ilean` file produced by `lean` -/
50+
abbrev Module.ileanFacet := `ilean
5751
module_data ilean : ActiveFileTarget
5852

5953
/-- The C file built from the Lean file via `lean` -/
54+
abbrev Module.cFacet := `lean.c
6055
module_data lean.c : ActiveFileTarget
6156

6257
/-- The object file built from `lean.c` -/
58+
abbrev Module.oFacet := `lean.o
6359
module_data lean.o : ActiveFileTarget
6460

6561
/-- Shared library for `--load-dynlib` -/
62+
abbrev Module.dynlibFacet := `dynlib
6663
module_data dynlib : ActiveFileTarget
6764

6865
/-! ## Package Facets -/
6966

70-
/-- The package's `extraDepTarget`. -/
67+
/-- The package's `extraDepTarget` mixed with its transitive dependencies `extraDepTarget`. -/
68+
abbrev Package.extraDepFacet := `extraDep
7169
package_data extraDep : ActiveOpaqueTarget
7270

7371
/-! ## Target Facets -/
7472

75-
abbrev LeanLib.staticFacet := `leanLib.static
76-
abbrev LeanLib.sharedFacet := `leanLib.shared
77-
abbrev LeanExe.exeFacet := `leanExe
78-
abbrev ExternLib.staticFacet := `externLib.static
79-
abbrev ExternLib.sharedFacet := `externLib.shared
80-
8173
/-- A Lean library's static binary. -/
74+
abbrev LeanLib.staticFacet := `leanLib.static
8275
target_data leanLib.static : ActiveFileTarget
8376

8477
/-- A Lean library's shared binary. -/
78+
abbrev LeanLib.sharedFacet := `leanLib.shared
8579
target_data leanLib.shared : ActiveFileTarget
8680

8781
/-- A Lean binary executable. -/
82+
abbrev LeanExe.exeFacet := `leanExe
8883
target_data leanExe : ActiveFileTarget
8984

9085
/-- A external library's static binary. -/
86+
abbrev ExternLib.staticFacet := `externLib.static
9187
target_data externLib.static : ActiveFileTarget
9288

9389
/-- A external library's shared binary. -/
90+
abbrev ExternLib.sharedFacet := `externLib.shared
9491
target_data externLib.shared : ActiveFileTarget

Diff for: Lake/Build/Imports.lean

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Mac Malone
55
-/
66
import Lake.Build.Index
7-
import Lake.Config.Workspace
87

98
/-!
109
Definitions to support `lake print-paths` builds.

Diff for: Lake/Build/Index.lean

+31-133
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Mac Malone
55
-/
66
import Lake.Build.Roots
7-
import Lake.Build.Module
87
import Lake.Build.Topological
98
import Lake.Util.EStateT
109

@@ -14,146 +13,35 @@ import Lake.Util.EStateT
1413
The Lake build index is the complete map of Lake build keys to
1514
Lake build functions, which is used by Lake to build any Lake build info.
1615
17-
This module contains the definitions used to formalize this concept,
18-
and it leverages the index to perform topologically-based recursive builds.
16+
This module leverages the index to perform topologically-based recursive builds.
1917
-/
2018

2119
open Std Lean
2220
namespace Lake
2321

24-
/-!
25-
## Facet Build Maps
26-
-/
27-
28-
/-- A map from module facet names to build functions. -/
29-
abbrev ModuleBuildMap (m : TypeType v) :=
30-
DRBMap Name (cmp := Name.quickCmp) fun k =>
31-
Module → IndexBuildFn m → m (ModuleData k)
32-
33-
@[inline] def ModuleBuildMap.empty : ModuleBuildMap m := DRBMap.empty
34-
35-
/-- A map from package facet names to build functions. -/
36-
abbrev PackageBuildMap (m : TypeType v) :=
37-
DRBMap Name (cmp := Name.quickCmp) fun k =>
38-
Package → IndexBuildFn m → m (PackageData k)
39-
40-
@[inline] def PackageBuildMap.empty : PackageBuildMap m := DRBMap.empty
41-
42-
/-- A map from target facet names to build functions. -/
43-
abbrev TargetBuildMap (m : TypeType v) :=
44-
DRBMap Name (cmp := Name.quickCmp) fun k =>
45-
Package → IndexBuildFn m → m (PackageData k)
46-
47-
@[inline] def TargetBuildMap.empty : PackageBuildMap m := DRBMap.empty
48-
49-
/-!
50-
## Build Function Constructor Helpers
51-
-/
52-
53-
/--
54-
Converts a conveniently typed module facet build function into its
55-
dynamically typed equivalent.
56-
-/
57-
@[inline] def mkModuleFacetBuild {facet : Name} (build : Module → IndexT m α)
58-
[h : FamilyDef ModuleData facet α] : Module → IndexT m (ModuleData facet) :=
59-
cast (by rw [← h.family_key_eq_type]) build
60-
61-
/--
62-
Converts a conveniently typed package facet build function into its
63-
dynamically typed equivalent.
64-
-/
65-
@[inline] def mkPackageFacetBuild {facet : Name} (build : Package → IndexT m α)
66-
[h : FamilyDef PackageData facet α] : Package → IndexT m (PackageData facet) :=
67-
cast (by rw [← h.family_key_eq_type]) build
68-
6922
/--
7023
Converts a conveniently typed target facet build function into its
7124
dynamically typed equivalent.
7225
-/
73-
@[inline] def mkTargetFacetBuild (facet : Name) (build : IndexT m α)
74-
[h : FamilyDef TargetData facet α] : IndexT m (TargetData facet) :=
26+
@[macroInline] def mkTargetFacetBuild (facet : Name) (build : IndexBuildM α)
27+
[h : FamilyDef TargetData facet α] : IndexBuildM (TargetData facet) :=
7528
cast (by rw [← h.family_key_eq_type]) build
7629

77-
section
78-
variable [Monad m] [MonadLiftT BuildM m] [MonadBuildStore m]
79-
80-
/-!
81-
## Initial Facet Maps
82-
-/
83-
84-
open Module in
85-
/--
86-
A module facet name to build function map that contains builders for
87-
the initial set of Lake module facets (e.g., `lean.{imports, c, o, dynlib]`).
88-
-/
89-
@[specialize] def moduleBuildMap : ModuleBuildMap m :=
90-
have : MonadLift BuildM m := ⟨liftM⟩
91-
ModuleBuildMap.empty (m := m)
92-
-- Compute unique imports (direct × transitive)
93-
|>.insert importFacet (mkModuleFacetBuild (·.recParseImports))
94-
-- Build module (`.olean`, `.ilean`, and possibly `.c`)
95-
|>.insert leanBinFacet (mkModuleFacetBuild (·.recBuildLean .leanBin))
96-
|>.insert oleanFacet (mkModuleFacetBuild (·.recBuildLean .olean))
97-
|>.insert ileanFacet (mkModuleFacetBuild (·.recBuildLean .ilean))
98-
|>.insert cFacet (mkModuleFacetBuild (·.recBuildLean .c))
99-
-- Build module `.o`
100-
|>.insert oFacet (mkModuleFacetBuild <| fun mod => do
101-
mod.mkOTarget (Target.active (← mod.c.recBuild)) |>.activate
102-
)
103-
-- Build shared library for `--load-dynlb`
104-
|>.insert dynlibFacet (mkModuleFacetBuild (·.recBuildDynlib))
105-
106-
/--
107-
A package facet name to build function map that contains builders for
108-
the initial set of Lake package facets (e.g., `extraDep`).
109-
-/
110-
@[specialize] def packageBuildMap : PackageBuildMap m :=
111-
have : MonadLift BuildM m := ⟨liftM⟩
112-
PackageBuildMap.empty (m := m)
113-
-- Compute the package's transitive dependencies
114-
|>.insert `deps (mkPackageFacetBuild <| fun pkg => do
115-
let mut deps := #[]
116-
let mut depSet := PackageSet.empty
117-
for dep in pkg.deps do
118-
for depDep in (← recBuild <| dep.facet `deps) do
119-
unless depSet.contains depDep do
120-
deps := deps.push depDep
121-
depSet := depSet.insert depDep
122-
unless depSet.contains dep do
123-
deps := deps.push dep
124-
depSet := depSet.insert dep
125-
return deps
126-
)
127-
-- Build the `extraDepTarget` for the package and its transitive dependencies
128-
|>.insert `extraDep (mkPackageFacetBuild <| fun pkg => do
129-
let mut target := ActiveTarget.nil
130-
for dep in pkg.deps do
131-
target ← target.mixOpaqueAsync (← dep.extraDep.recBuild)
132-
target.mixOpaqueAsync <| ← pkg.extraDepTarget.activate
133-
)
134-
13530
/-!
13631
## Topologically-based Recursive Build Using the Index
13732
-/
13833

13934
/-- Recursive build function for anything in the Lake build index. -/
140-
@[specialize] def recBuildIndex (info : BuildInfo) : IndexT m (BuildData info.key) := do
141-
have : MonadLift BuildM m := ⟨liftM⟩
35+
def recBuildWithIndex (info : BuildInfo) : IndexBuildM (BuildData info.key) := do
14236
match info with
14337
| .moduleFacet mod facet =>
144-
if let some build := moduleBuildMap.find? facet then
145-
build mod
146-
else if let some config := (← getWorkspace).findModuleFacetConfig? facet then
147-
have := config.familyDef
148-
mkModuleFacetBuild config.build mod
38+
if let some config := (← getWorkspace).findModuleFacetConfig? facet then
39+
config.build mod
14940
else
15041
error s!"do not know how to build module facet `{facet}`"
15142
| .packageFacet pkg facet =>
152-
if let some build := packageBuildMap.find? facet then
153-
build pkg
154-
else if let some config := (← getWorkspace).findPackageFacetConfig? facet then
155-
have := config.familyDef
156-
mkPackageFacetBuild config.build pkg
43+
if let some config := (← getWorkspace).findPackageFacetConfig? facet then
44+
config.build pkg
15745
else
15846
error s!"do not know how to build package facet `{facet}`"
15947
| .customTarget pkg target =>
@@ -170,7 +58,7 @@ the initial set of Lake package facets (e.g., `extraDep`).
17058
| .sharedLeanLib lib =>
17159
mkTargetFacetBuild LeanLib.sharedFacet lib.recBuildShared
17260
| .leanExe exe =>
173-
mkTargetFacetBuild LeanExe.exeFacet exe.recBuild
61+
mkTargetFacetBuild LeanExe.exeFacet exe.recBuildExe
17462
| .staticExternLib lib =>
17563
mkTargetFacetBuild ExternLib.staticFacet lib.target.activate
17664
| .sharedExternLib lib =>
@@ -182,31 +70,41 @@ the initial set of Lake package facets (e.g., `extraDep`).
18270
Recursively build the given info using the Lake build index
18371
and a topological / suspending scheduler.
18472
-/
185-
@[specialize] def buildIndexTop' (info : BuildInfo) : CycleT BuildKey m (BuildData info.key) :=
186-
buildDTop BuildData BuildInfo.key recBuildIndex info
73+
def buildIndexTop' (info : BuildInfo) : RecBuildM (BuildData info.key) :=
74+
buildDTop BuildData BuildInfo.key recBuildWithIndex info
18775

18876
/--
18977
Recursively build the given info using the Lake build index
19078
and a topological / suspending scheduler and return the dynamic result.
19179
-/
192-
@[inline] def buildIndexTop (info : BuildInfo)
193-
[FamilyDef BuildData info.key α] : CycleT BuildKey m α := do
194-
cast (by simp) <| buildIndexTop' (m := m) info
195-
196-
end
80+
@[macroInline] def buildIndexTop (info : BuildInfo)
81+
[FamilyDef BuildData info.key α] : RecBuildM α := do
82+
cast (by simp) <| buildIndexTop' info
19783

19884
/-- Build the given Lake target using the given Lake build store. -/
199-
@[inline] def BuildInfo.buildIn (store : BuildStore) (self : BuildInfo)
200-
[FamilyDef BuildData self.key α] : BuildM α := do
201-
failOnBuildCycle <| ← EStateT.run' (m := BuildM) store <| buildIndexTop self
85+
@[inline] def BuildInfo.buildIn
86+
(store : BuildStore) (self : BuildInfo) [FamilyDef BuildData self.key α] : BuildM α := do
87+
failOnBuildCycle <| ← EStateT.run' store <| buildIndexTop self
20288

20389
/-- Build the given Lake target in a fresh build store. -/
204-
@[inline] def BuildInfo.build (self : BuildInfo) [FamilyDef BuildData self.key α] : BuildM α :=
90+
@[macroInline] def BuildInfo.build
91+
(self : BuildInfo) [FamilyDef BuildData self.key α] : BuildM α :=
20592
buildIn BuildStore.empty self
20693

20794
export BuildInfo (build buildIn)
20895

209-
/-- An opaque target that builds the Lake target in a fresh build store. -/
96+
/-! ## Targets Using the Build Index -/
97+
98+
/-- An opaque target that builds the info in a fresh build store. -/
21099
@[inline] def BuildInfo.target (self : BuildInfo)
211100
[FamilyDef BuildData self.key (ActiveBuildTarget α)] : OpaqueTarget :=
212101
BuildTarget.mk' () <| self.build <&> (·.task)
102+
103+
/-- A smart constructor for facet configurations that generate targets. -/
104+
@[inline] def mkFacetTargetConfig (build : ι → IndexBuildM (ActiveBuildTarget α))
105+
[h : FamilyDef Fam facet (ActiveBuildTarget α)] : FacetConfig Fam ι facet where
106+
build := cast (by rw [← h.family_key_eq_type]) build
107+
toTarget? := fun info key_eq_type =>
108+
have : FamilyDef BuildData info.key (ActiveBuildTarget α) :=
109+
⟨h.family_key_eq_type ▸ key_eq_type⟩
110+
info.target

0 commit comments

Comments
 (0)