lean4-htt/Lake/BuildTarget.lean

152 lines
4.4 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2021 Mac Malone. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mac Malone
-/
namespace Lake
-- # Build Task
def BuildTask := Task (Except IO.Error PUnit)
namespace BuildTask
def nop : BuildTask :=
Task.pure (Except.ok ())
def spawn (action : IO PUnit) (prio := Task.Priority.dedicated) : IO BuildTask :=
IO.asTask action prio
def await (self : BuildTask) : IO PUnit := do
IO.ofExcept (← IO.wait self)
def all (tasks : List BuildTask) : IO BuildTask :=
IO.asTask (tasks.forM (·.await))
end BuildTask
instance : Inhabited BuildTask := ⟨BuildTask.nop⟩
def afterTask (task : BuildTask) (action : IO PUnit) : IO BuildTask :=
IO.mapTask (fun x => IO.ofExcept x *> action) task
def afterTaskList (tasks : List BuildTask) (action : IO PUnit) : IO BuildTask :=
IO.mapTasks (fun xs => xs.forM IO.ofExcept *> action) <| tasks
instance : HAndThen BuildTask (IO PUnit) (IO BuildTask) :=
⟨afterTask⟩
instance : HAndThen (List BuildTask) (IO PUnit) (IO BuildTask) :=
⟨afterTaskList⟩
-- # Build Target
structure BuildTarget (t : Type) (a : Type) where
artifact : a
trace : t
buildTask : BuildTask
-- manually derive `Inhabited` instance because automatic deriving fails
instance [Inhabited t] [Inhabited a] : Inhabited (BuildTarget t a) :=
⟨Inhabited.default, Inhabited.default, BuildTask.nop⟩
namespace BuildTarget
def pure (artifact : a) (trace : t) : BuildTarget t a :=
{artifact, trace, buildTask := BuildTask.nop}
def withTrace (trace : t) (self : BuildTarget r a) : BuildTarget t a :=
{self with trace := trace}
def discardTrace (self : BuildTarget t a) : BuildTarget PUnit a :=
self.withTrace ()
def withArtifact (artifact : a) (self : BuildTarget t b) : BuildTarget t a :=
{self with artifact := artifact}
def discardArtifact (self : BuildTarget t α) : BuildTarget t PUnit :=
self.withArtifact ()
def materialize (self : BuildTarget t α) : IO PUnit :=
self.buildTask.await
end BuildTarget
def afterTarget (target : BuildTarget t a) (action : IO PUnit) : IO BuildTask :=
afterTask target.buildTask action
def afterTargetList (targets : List (BuildTarget t a)) (action : IO PUnit) : IO BuildTask :=
afterTaskList (targets.map (·.buildTask)) action
instance : HAndThen (BuildTarget t a) (IO PUnit) (IO BuildTask) :=
⟨afterTarget⟩
instance : HAndThen (List (BuildTarget t a)) (IO PUnit) (IO BuildTask) :=
⟨afterTargetList⟩
-- # Hash Traces
section
def Hash := UInt64
instance : OfNat Hash n := inferInstanceAs (OfNat UInt64 n)
instance : Inhabited Hash := inferInstanceAs (Inhabited UInt64)
instance : BEq Hash := inferInstanceAs (BEq UInt64)
end
def Hash.ofNat (n : Nat) := UInt64.ofNat n
def Hash.foldList (init : Hash) (hashes : List Hash) :=
List.foldl mixHash init hashes
-- # MTime Traces
section
open IO.FS (SystemTime)
def MTime := SystemTime
instance : Inhabited MTime := ⟨⟨0,0⟩⟩
instance : OfNat MTime (nat_lit 0) := ⟨⟨0,0⟩⟩
instance : BEq MTime := inferInstanceAs (BEq SystemTime)
instance : Repr MTime := inferInstanceAs (Repr SystemTime)
instance : Ord MTime := inferInstanceAs (Ord SystemTime)
instance : LT MTime := ltOfOrd
instance : LE MTime := leOfOrd
end
def MTime.listMax (mtimes : List MTime) := mtimes.maximum?.getD 0
class GetMTime (α) where
getMTime : α → IO MTime
export GetMTime (getMTime)
instance : GetMTime System.FilePath where
getMTime file := do (← file.metadata).modified
abbrev MTimeBuildTarget := BuildTarget MTime
namespace MTimeBuildTarget
def mtime (self : MTimeBuildTarget a) :=
self.trace
def mk (artifact : a) (mtime : MTime := 0) (buildTask : BuildTask) : MTimeBuildTarget a :=
{artifact, trace := mtime, buildTask}
def pure (artifact : a) (mtime : MTime := 0) : MTimeBuildTarget a :=
{artifact, trace := mtime, buildTask := BuildTask.nop}
def all (targets : List (MTimeBuildTarget a)) : IO (MTimeBuildTarget PUnit) := do
let depsMTime := MTime.listMax <| targets.map (·.mtime)
let task ← BuildTask.all <| targets.map (·.buildTask)
return MTimeBuildTarget.mk () depsMTime task
def collectAll (targets : List (MTimeBuildTarget a)) : IO (MTimeBuildTarget (List a)) := do
let artifacts := targets.map (·.artifact)
let depsMTime := MTime.listMax <| targets.map (·.mtime)
let task ← BuildTask.all <| targets.map (·.buildTask)
return MTimeBuildTarget.mk artifacts depsMTime task
end MTimeBuildTarget