PageRenderTime 61ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/3.1/Nov2013/src/fsharp/vs/IncrementalBuild.fs

#
F# | 1769 lines | 1309 code | 220 blank | 240 comment | 201 complexity | fd86a291fcc725996110a0d919bcd7cc MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. namespace Microsoft.FSharp.Compiler
  2. #nowarn "57"
  3. open Internal.Utilities.Debug
  4. open Internal.Utilities.FileSystem
  5. open System
  6. open System.IO
  7. open System.Reflection
  8. open System.Diagnostics
  9. open System.Collections.Generic
  10. open System
  11. open Microsoft.FSharp.Compiler
  12. open Microsoft.FSharp.Compiler.Range
  13. open Microsoft.FSharp.Compiler.Build
  14. open Microsoft.FSharp.Compiler.Tastops
  15. open Microsoft.FSharp.Compiler.ErrorLogger
  16. open Microsoft.FSharp.Compiler.Lib
  17. open Microsoft.FSharp.Compiler.AbstractIL
  18. open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
  19. module internal IncrementalBuild =
  20. /// A particular node in the Expr language. Use an int for keys instead of the entire Expr to avoid extra hashing.
  21. type Id =
  22. | Id of int
  23. static member toInt (Id id) = id
  24. override id.ToString() = match id with Id(n) ->sprintf "Id(%d)" n
  25. [<NoEquality; NoComparison>]
  26. /// A build rule representing a single output
  27. type ScalarBuildRule =
  28. /// ScalarInput (uniqueRuleId, outputName)
  29. ///
  30. /// A build rule representing a single input, producing the input as its single scalar result
  31. | ScalarInput of Id * string
  32. /// ScalarDemultiplex (uniqueRuleId, outputName, input, taskFunction)
  33. ///
  34. /// A build rule representing the merge of a set of inputs to a single output
  35. | ScalarDemultiplex of Id * string * VectorBuildRule * (obj[] -> obj)
  36. /// ScalarMap (uniqueRuleId, outputName, input, taskFunction)
  37. ///
  38. /// A build rule representing the transformation of a single input to a single output
  39. | ScalarMap of Id * string * ScalarBuildRule * (obj->obj)
  40. /// Get the Id for the given ScalarBuildRule.
  41. static member GetId = function
  42. | ScalarInput(id,_) ->id
  43. | ScalarDemultiplex(id,_,_,_) ->id
  44. | ScalarMap(id,_,_,_) ->id
  45. /// Get the Name for the givenScalarExpr.
  46. static member GetName = function
  47. | ScalarInput(_,n) ->n
  48. | ScalarDemultiplex(_,n,_,_) ->n
  49. | ScalarMap(_,n,_,_) ->n
  50. override ve.ToString() =
  51. match ve with
  52. | ScalarInput(Id id,name) ->sprintf "InputScalar(%d,%s)" id name
  53. | ScalarDemultiplex(Id id,name,_,_) ->sprintf "ScalarDemultiplex(%d,%s)" id name
  54. | ScalarMap(Id id,name,_,_) ->sprintf "ScalarMap(%d,%s)" id name
  55. /// A build rule with a vector of outputs
  56. and VectorBuildRule =
  57. /// VectorInput (uniqueRuleId, outputName)
  58. ///
  59. /// A build rule representing the transformation of a single input to a single output
  60. | VectorInput of Id * string
  61. /// VectorInput (uniqueRuleId, outputName, initialAccumulator, inputs, taskFunction)
  62. ///
  63. /// A build rule representing the scan-left combinining a single scalar accumulator input with a vector of inputs
  64. | VectorScanLeft of Id * string * ScalarBuildRule * VectorBuildRule * (obj->obj->Eventually<obj>)
  65. /// VectorMap (uniqueRuleId, outputName, inputs, taskFunction)
  66. ///
  67. /// A build rule representing the parallel map of the inputs to outputs
  68. | VectorMap of Id * string * VectorBuildRule * (obj->obj)
  69. /// VectorStamp (uniqueRuleId, outputName, inputs, stampFunction)
  70. ///
  71. /// A build rule representing pairing the inputs with a timestamp specified by the given function.
  72. | VectorStamp of Id * string * VectorBuildRule * (obj->DateTime)
  73. /// VectorMultiplex (uniqueRuleId, outputName, input, taskFunction)
  74. ///
  75. /// A build rule representing taking a single input and transforming it to a vector of outputs
  76. | VectorMultiplex of Id * string * ScalarBuildRule * (obj->obj[])
  77. /// Get the Id for the given VectorBuildRule.
  78. static member GetId = function
  79. | VectorInput(id,_) ->id
  80. | VectorScanLeft(id,_,_,_,_) ->id
  81. | VectorMap(id,_,_,_) ->id
  82. | VectorStamp(id,_,_,_) ->id
  83. | VectorMultiplex(id,_,_,_) ->id
  84. /// Get the Name for the given VectorBuildRule.
  85. static member GetName = function
  86. | VectorInput(_,n) ->n
  87. | VectorScanLeft(_,n,_,_,_) ->n
  88. | VectorMap(_,n,_,_) ->n
  89. | VectorStamp(_,n,_,_) ->n
  90. | VectorMultiplex(_,n,_,_) ->n
  91. override ve.ToString() =
  92. match ve with
  93. | VectorInput(Id id,name) ->sprintf "VectorInput(%d,%s)" id name
  94. | VectorScanLeft(Id id,name,_,_,_) ->sprintf "VectorScanLeft(%d,%s)" id name
  95. | VectorMap(Id id,name,_,_) ->sprintf "VectorMap(%d,%s)" id name
  96. | VectorStamp(Id id,name,_,_) ->sprintf "VectorStamp(%d,%s)" id name
  97. | VectorMultiplex(Id id,name,_,_) ->sprintf "VectorMultiplex(%d,%s)" id name
  98. [<NoEquality; NoComparison>]
  99. type BuildRuleExpr =
  100. | ScalarBuildRule of ScalarBuildRule
  101. | VectorBuildRule of VectorBuildRule
  102. /// Get the Id for the given Expr.
  103. static member GetId = function
  104. | ScalarBuildRule se ->ScalarBuildRule.GetId se
  105. | VectorBuildRule ve ->VectorBuildRule.GetId ve
  106. /// Get the Name for the given Expr.
  107. static member GetName= function
  108. | ScalarBuildRule se ->ScalarBuildRule.GetName se
  109. | VectorBuildRule ve ->VectorBuildRule.GetName ve
  110. override e.ToString() =
  111. match e with
  112. | ScalarBuildRule _ -> sprintf "ScalarBuildRule se"
  113. | VectorBuildRule _ -> sprintf "VectorBuildRule ve"
  114. // Ids of exprs
  115. let nextid = ref 999 // Number ids starting with 1000 to discern them
  116. let NextId() =
  117. nextid:=!nextid+1
  118. Id(!nextid)
  119. type IScalar =
  120. abstract GetScalarExpr : unit -> ScalarBuildRule
  121. type IVector =
  122. abstract GetVectorExpr : unit-> VectorBuildRule
  123. type Scalar<'T> = interface end
  124. type Vector<'T> = interface end
  125. /// The outputs of a build
  126. [<NoEquality; NoComparison>]
  127. type NamedOutput =
  128. | NamedVectorOutput of string * IVector
  129. | NamedScalarOutput of string * IScalar
  130. type BuildRules = { RuleList : (string * BuildRuleExpr) list }
  131. /// Visit each task and call op with the given accumulator.
  132. let FoldOverBuildRules(rules:BuildRules, op, acc)=
  133. let rec VisitVector (ve:VectorBuildRule) acc =
  134. match ve with
  135. | VectorInput _ ->op (VectorBuildRule ve) acc
  136. | VectorScanLeft(_,_,a,i,_) ->op (VectorBuildRule ve) (VisitVector i (VisitScalar a acc))
  137. | VectorMap(_,_,i,_)
  138. | VectorStamp(_,_,i,_) ->op (VectorBuildRule ve) (VisitVector i acc)
  139. | VectorMultiplex(_,_,i,_) ->op (VectorBuildRule ve) (VisitScalar i acc)
  140. and VisitScalar (se:ScalarBuildRule) acc =
  141. match se with
  142. | ScalarInput _ ->op (ScalarBuildRule se) acc
  143. | ScalarDemultiplex(_,_,i,_) ->op (ScalarBuildRule se) (VisitVector i acc)
  144. | ScalarMap(_,_,i,_) ->op (ScalarBuildRule se) (VisitScalar i acc)
  145. let rec VisitRule (expr:BuildRuleExpr) acc =
  146. match expr with
  147. | ScalarBuildRule se ->VisitScalar se acc
  148. | VectorBuildRule ve ->VisitVector ve acc
  149. List.foldBack VisitRule (rules.RuleList |> List.map snd) acc
  150. /// Convert from interfaces into discriminated union.
  151. let ToBuild (names:NamedOutput list) : BuildRules =
  152. // Create the rules.
  153. let CreateRules() =
  154. { RuleList = names |> List.map(function NamedVectorOutput(n,v) -> n,VectorBuildRule(v.GetVectorExpr())
  155. | NamedScalarOutput(n,s) -> n,ScalarBuildRule(s.GetScalarExpr())) }
  156. // Ensure that all names are unique.
  157. let EnsureUniqueNames (expr:BuildRuleExpr) (acc:Map<string,Id>) =
  158. let AddUniqueIdToNameMapping(id,name)=
  159. match acc.TryFind name with
  160. | Some(priorId) ->
  161. if id<>priorId then failwith (sprintf "Two build expressions had the same name: %s" name)
  162. else acc
  163. | None-> Map.add name id acc
  164. let id = BuildRuleExpr.GetId(expr)
  165. let name = BuildRuleExpr.GetName(expr)
  166. AddUniqueIdToNameMapping(id,name)
  167. // Validate the rule tree
  168. let ValidateRules (rules:BuildRules) =
  169. FoldOverBuildRules(rules,EnsureUniqueNames,Map.empty) |> ignore
  170. // Convert and validate
  171. let rules = CreateRules()
  172. ValidateRules rules
  173. rules
  174. /// These describe the input conditions for a result. If conditions change then the result is invalid.
  175. type InputSignature =
  176. | SingleMappedVectorInput of InputSignature[]
  177. | EmptyTimeStampedInput of DateTime
  178. | BoundInputScalar // An external input into the build
  179. | BoundInputVector // An external input into the build
  180. | IndexedValueElement of DateTime
  181. | UnevaluatedInput
  182. /// Return true if the result is fully evaluated
  183. member is.IsEvaluated() =
  184. let rec IsEvaluated(is) =
  185. match is with
  186. | UnevaluatedInput -> false
  187. | SingleMappedVectorInput iss -> iss |> Array.forall IsEvaluated
  188. | _ -> true
  189. IsEvaluated(is)
  190. override is.ToString() = sprintf "%A" is
  191. /// A slot for holding a single result.
  192. type Result =
  193. | NotAvailable
  194. | InProgress of (unit -> Eventually<obj>) * DateTime
  195. | Available of obj * DateTime * InputSignature
  196. /// Get the available result. Throw an exception if not available.
  197. static member GetAvailable = function Available(o,_,_) ->o | _->failwith "No available result"
  198. /// Get the time stamp if available. Otheriwse MaxValue.
  199. static member Timestamp = function Available(_,ts,_) ->ts | InProgress(_,ts) -> ts | _-> DateTime.MaxValue
  200. /// Get the time stamp if available. Otheriwse MaxValue.
  201. static member InputSignature = function Available(_,_,signature) ->signature | _-> UnevaluatedInput
  202. member x.ResultIsInProgress = match x with | InProgress _ -> true | _ -> false
  203. member x.GetInProgressContinuation() = match x with | InProgress (f,_) -> f() | _ -> failwith "not in progress"
  204. member x.TryGetAvailable() = match x with | InProgress _ | NotAvailable -> None | Available(obj,dt,i) -> Some(obj,dt,i)
  205. override r.ToString() =
  206. match r with
  207. | NotAvailable -> "NotAvailable"
  208. | InProgress _ -> "InProgress"
  209. | Available(o, ts, _) -> sprintf "Available('%s' as of %A)" (o.ToString()) ts
  210. /// An immutable sparse vector of results.
  211. type ResultVector(size,zeroElementTimestamp,map) =
  212. let get slot =
  213. match Map.tryFind slot map with
  214. | Some(result) ->result
  215. | None->NotAvailable
  216. let asList = lazy List.map (fun i->i,get i) [0..size-1]
  217. static member OfSize(size) = ResultVector(size,DateTime.MinValue,Map.empty)
  218. member rv.Size = size
  219. member rv.Get slot = get slot
  220. member rv.Resize(newsize) =
  221. if size<>newsize then
  222. ResultVector(newsize, zeroElementTimestamp, map |> Map.filter(fun s _ -> s < newsize))
  223. else rv
  224. member rv.Set(slot,value) =
  225. #if DEBUG
  226. if slot<0 then failwith "ResultVector slot less than zero"
  227. if slot>=size then failwith "ResultVector slot too big"
  228. #endif
  229. ResultVector(size, zeroElementTimestamp, Map.add slot value map)
  230. member rv.MaxTimestamp() =
  231. // use t = Trace.Call("IncrementalBuildVerbose", "MaxTimestamp", fun _->sprintf "vector of size=%d" size)
  232. let Maximize (lasttimestamp:DateTime) (_,result) =
  233. let thistimestamp = Result.Timestamp result
  234. let m = max lasttimestamp thistimestamp
  235. // use t = Trace.Call("IncrementalBuildVerbose", "Maximize", fun _->sprintf "last=%s this=%s max=%s" (lasttimestamp.ToString()) (thistimestamp.ToString()) (m.ToString()))
  236. m
  237. List.fold Maximize zeroElementTimestamp (asList.Force())
  238. member rv.Signature() =
  239. let l = asList.Force()
  240. let l = l |> List.map(fun (_,result) ->Result.InputSignature result)
  241. SingleMappedVectorInput (l|>List.toArray)
  242. member rv.FoldLeft f s : 'a = List.fold f s (asList.Force())
  243. override rv.ToString() = asList.ToString() // NOTE: Force()ing this inside ToString() leads to StackOverflowException and very undesirable debugging behavior for all of F#
  244. /// A result of performing build actions
  245. [<NoEquality; NoComparison>]
  246. type ResultSet =
  247. | ScalarResult of Result
  248. | VectorResult of ResultVector
  249. override rs.ToString() =
  250. match rs with
  251. | ScalarResult(sr) ->sprintf "ScalarResult(%s)" (sr.ToString())
  252. | VectorResult(rs) ->sprintf "VectorResult(%s)" (rs.ToString())
  253. /// Action timing
  254. module Time =
  255. #if SILVERLIGHT
  256. let Action<'T> taskname slot func : 'T = func()
  257. #else
  258. let sw = new Stopwatch()
  259. let Action<'T> taskname slot func : 'T=
  260. if Trace.ShouldLog("IncrementalBuildWorkUnits") then
  261. let slotMessage =
  262. if slot= -1 then sprintf "%s" taskname
  263. else sprintf "%s over slot %d" taskname slot
  264. // Timings and memory
  265. let maxGen = System.GC.MaxGeneration
  266. let ptime = System.Diagnostics.Process.GetCurrentProcess()
  267. let timePrev = ptime.UserProcessorTime.TotalSeconds
  268. let gcPrev = [| for i in 0 .. maxGen -> System.GC.CollectionCount i |]
  269. let pbPrev = ptime.PrivateMemorySize64 in
  270. // Call the function
  271. let result = func()
  272. // Report.
  273. let timeNow = ptime.UserProcessorTime.TotalSeconds
  274. let pbNow = ptime.PrivateMemorySize64
  275. let spanGC = [| for i in 0 .. maxGen -> System.GC.CollectionCount i - gcPrev.[i] |]
  276. Trace.PrintLine("IncrementalBuildWorkUnits", fun _ ->
  277. sprintf "%s TIME: %4.3f MEM: %3d (delta) G0: %3d G1: %2d G2: %2d"
  278. slotMessage
  279. (timeNow - timePrev)
  280. (pbNow - pbPrev)
  281. spanGC.[min 0 maxGen]
  282. spanGC.[min 1 maxGen]
  283. spanGC.[min 2 maxGen])
  284. result
  285. else func()
  286. #endif
  287. /// Result of a particular action over the bound build tree
  288. [<NoEquality; NoComparison>]
  289. type ActionResult =
  290. | IndexedResult of Id * int * (*slotcount*) int * Eventually<obj> * DateTime
  291. | ScalarValuedResult of Id * obj * DateTime * InputSignature
  292. | VectorValuedResult of Id * obj[] * DateTime * InputSignature
  293. | ResizeResult of Id * (*slotcount*) int
  294. override ar.ToString() =
  295. match ar with
  296. | IndexedResult(id,slot,slotcount,_,dt) ->sprintf "IndexedResult(%d,%d,%d,obj,%A)" (Id.toInt id) slot slotcount dt
  297. | ScalarValuedResult(id,_,dt,inputsig) ->sprintf "ScalarValuedResult(%d,obj,%A,%A)" (Id.toInt id) dt inputsig
  298. | VectorValuedResult(id,_,dt,inputsig) ->sprintf "VectorValuedResult(%d,obj[],%A,%A)" (Id.toInt id) dt inputsig
  299. | ResizeResult(id,slotcount) ->sprintf "ResizeResult(%d,%d)" (Id.toInt id) slotcount
  300. /// A pending action over the bound build tree
  301. [<NoEquality; NoComparison>]
  302. type Action =
  303. | IndexedAction of Id * (*taskname*)string * int * (*slotcount*) int * DateTime * (unit->Eventually<obj>)
  304. | ScalarAction of Id * (*taskname*)string * DateTime * InputSignature * (unit->obj)
  305. | VectorAction of Id * (*taskname*)string * DateTime * InputSignature * (unit->obj[])
  306. | ResizeResultAction of Id * (*slotcount*) int
  307. /// Execute one action and return a corresponding result.
  308. static member Execute action =
  309. match action with
  310. | IndexedAction(id,taskname,slot,slotcount,timestamp,func) -> IndexedResult(id,slot,slotcount,Time.Action taskname slot func,timestamp)
  311. | ScalarAction(id,taskname,timestamp,inputsig,func) -> ScalarValuedResult(id,Time.Action taskname (-1) func,timestamp,inputsig)
  312. | VectorAction(id,taskname,timestamp,inputsig,func) -> VectorValuedResult(id,Time.Action taskname (-1) func,timestamp,inputsig)
  313. | ResizeResultAction(id,slotcount) -> ResizeResult(id,slotcount)
  314. /// String helper functions for when there's no %A
  315. type String =
  316. static member OfList2 l =
  317. " ["^String.Join(",\n ", List.toArray (l|>List.map (fun (v1,v2) ->((box v1).ToString()) + ";" + ((box v2).ToString())))) + " ]"
  318. /// A set of build rules and the corresponding, possibly partial, results from building.
  319. [<Sealed>]
  320. type PartialBuild(rules:BuildRules, results:Map<Id,ResultSet>) =
  321. member bt.Rules = rules
  322. member bt.Results = results
  323. override bt.ToString() =
  324. let sb = new System.Text.StringBuilder()
  325. results |> Map.iter(fun id result->
  326. let id = Id.toInt id
  327. let s = sprintf "\n {Id=%d,ResultSet=%s}" id (result.ToString())
  328. let _ = sb.Append(s)
  329. ())
  330. sprintf "{Rules={%s}\n Results={%s}}" (String.OfList2 rules.RuleList) (sb.ToString())
  331. /// Given an expression, find the expected width.
  332. let rec GetVectorWidthByExpr(bt:PartialBuild,ve:VectorBuildRule) =
  333. let KnownValue ve =
  334. match bt.Results.TryFind(VectorBuildRule.GetId ve) with
  335. | Some(resultSet) ->
  336. match resultSet with
  337. | VectorResult rv ->Some(rv.Size)
  338. | _ -> failwith "Expected vector to have vector result."
  339. | None-> None
  340. match ve with
  341. | VectorScanLeft(_,_,_,i,_)
  342. | VectorMap(_,_,i,_)
  343. | VectorStamp(_,_,i,_) ->
  344. match GetVectorWidthByExpr(bt,i) with
  345. | Some _ as r -> r
  346. | None->KnownValue ve
  347. | VectorInput _
  348. | VectorMultiplex _ -> KnownValue ve
  349. /// Given an expression name, get the corresponding expression.
  350. let GetTopLevelExprByName(bt:PartialBuild, seek:string) =
  351. bt.Rules.RuleList |> List.filter(fun(name,_) ->name=seek) |> List.map(fun(_,root) ->root) |> List.head
  352. /// Get an expression matching the given name.
  353. let GetExprByName(bt:PartialBuild, seek:string) : BuildRuleExpr =
  354. let MatchName (expr:BuildRuleExpr) (acc:BuildRuleExpr option) : BuildRuleExpr option =
  355. let name = BuildRuleExpr.GetName(expr)
  356. if name = seek then Some(expr) else acc
  357. let matchOption = FoldOverBuildRules(bt.Rules,MatchName,None)
  358. Option.get matchOption
  359. // Given an Id, find the corresponding expression.
  360. let GetExprById(bt:PartialBuild, seek:Id) : BuildRuleExpr=
  361. let rec VectorExprOfId ve =
  362. match ve with
  363. | VectorInput(id,_) ->if seek=id then Some(VectorBuildRule ve) else None
  364. | VectorScanLeft(id,_,a,i,_) ->
  365. if seek=id then Some(VectorBuildRule ve) else
  366. let result = ScalarExprOfId(a)
  367. match result with Some _ -> result | None->VectorExprOfId i
  368. | VectorMap(id,_,i,_) ->if seek=id then Some(VectorBuildRule ve) else VectorExprOfId i
  369. | VectorStamp(id,_,i,_) ->if seek=id then Some(VectorBuildRule ve) else VectorExprOfId i
  370. | VectorMultiplex(id,_,i,_) ->if seek=id then Some(VectorBuildRule ve) else ScalarExprOfId i
  371. and ScalarExprOfId se =
  372. match se with
  373. | ScalarInput(id,_) ->if seek=id then Some(ScalarBuildRule se) else None
  374. | ScalarDemultiplex(id,_,i,_) ->if seek=id then Some(ScalarBuildRule se) else VectorExprOfId i
  375. | ScalarMap(id,_,i,_) ->if seek=id then Some(ScalarBuildRule se) else ScalarExprOfId i
  376. let ExprOfId(expr:BuildRuleExpr) =
  377. match expr with
  378. | ScalarBuildRule se ->ScalarExprOfId se
  379. | VectorBuildRule ve ->VectorExprOfId ve
  380. let exprs = bt.Rules.RuleList |> List.map(fun(_,root) ->ExprOfId(root)) |> List.filter Option.isSome
  381. match exprs with
  382. | Some(expr)::_ -> expr
  383. | _ -> failwith (sprintf "GetExprById did not find an expression for Id %d" (Id.toInt seek))
  384. let GetVectorWidthById (bt:PartialBuild) seek =
  385. match GetExprById(bt,seek) with
  386. | ScalarBuildRule _ ->failwith "Attempt to get width of scalar."
  387. | VectorBuildRule ve ->Option.get (GetVectorWidthByExpr(bt,ve))
  388. let GetScalarExprResult(bt:PartialBuild, se:ScalarBuildRule) =
  389. match bt.Results.TryFind(ScalarBuildRule.GetId se) with
  390. | Some(resultSet) ->
  391. match se,resultSet with
  392. | ScalarInput _,ScalarResult(r)
  393. | ScalarMap _,ScalarResult(r)
  394. | ScalarDemultiplex _,ScalarResult(r) ->r
  395. | se,result->failwith (sprintf "GetScalarExprResult had no match for %A,%A" se result)
  396. | None->NotAvailable
  397. let GetVectorExprResultVector(bt:PartialBuild, ve:VectorBuildRule) =
  398. match bt.Results.TryFind(VectorBuildRule.GetId ve) with
  399. | Some(resultSet) ->
  400. match ve,resultSet with
  401. | VectorScanLeft _,VectorResult rv
  402. | VectorMap _,VectorResult rv
  403. | VectorInput _,VectorResult rv
  404. | VectorStamp _,VectorResult rv
  405. | VectorMultiplex _,VectorResult rv -> Some rv
  406. | ve,result->failwith (sprintf "GetVectorExprResultVector had no match for %A,%A" ve result)
  407. | None->None
  408. let GetVectorExprResult(bt:PartialBuild, ve:VectorBuildRule, slot) =
  409. match bt.Results.TryFind(VectorBuildRule.GetId ve) with
  410. | Some(resultSet) ->
  411. match ve,resultSet with
  412. | VectorScanLeft _,VectorResult rv
  413. | VectorMap _,VectorResult rv
  414. | VectorInput _,VectorResult rv
  415. | VectorStamp _,VectorResult rv -> rv.Get slot
  416. | VectorMultiplex _,VectorResult rv -> rv.Get slot
  417. | ve,result->failwith (sprintf "GetVectorExprResult had no match for %A,%A" ve result)
  418. | None->NotAvailable
  419. /// Get the maximum build stamp for an output.
  420. let MaxTimestamp(bt:PartialBuild,id,_inputstamp) =
  421. match bt.Results.TryFind(id) with
  422. | Some(resultset) ->
  423. match resultset with
  424. | ScalarResult(rs) -> Result.Timestamp rs
  425. | VectorResult rv -> rv.MaxTimestamp()
  426. | None -> DateTime.MaxValue
  427. let Signature(bt:PartialBuild,id) =
  428. match bt.Results.TryFind(id) with
  429. | Some(resultset) ->
  430. match resultset with
  431. | ScalarResult(rs) -> Result.InputSignature rs
  432. | VectorResult rv -> rv.Signature()
  433. | None -> UnevaluatedInput
  434. /// Get all the results for the given expr.
  435. let AllResultsOfExpr extractor (bt:PartialBuild) expr =
  436. let GetAvailable (rv:ResultVector) =
  437. let Extract acc (_, result) = (extractor result)::acc
  438. List.rev (rv.FoldLeft Extract [])
  439. let GetVectorResultById id =
  440. match bt.Results.TryFind(id) with
  441. | Some(found) ->
  442. match found with
  443. | VectorResult rv ->GetAvailable rv
  444. | _ -> failwith "wrong result type"
  445. | None -> []
  446. GetVectorResultById(VectorBuildRule.GetId(expr))
  447. let AvailableAllResultsOfExpr bt expr =
  448. let msg = "Expected all results to be available"
  449. AllResultsOfExpr (function Available(o,_,_) -> o | _ -> failwith msg) bt expr
  450. /// Bind a set of build rules to a set of input values.
  451. let ToBound(buildRules:BuildRules, vectorinputs, scalarinputs) =
  452. let now = DateTime.Now
  453. let rec ApplyScalarExpr(se,results) =
  454. match se with
  455. | ScalarInput(id,n) ->
  456. let matches = scalarinputs
  457. |> List.filter (fun (inputname,_) ->inputname=n)
  458. |> List.map (fun (_,inputvalue:obj) -> ScalarResult(Available(inputvalue,now,BoundInputScalar)))
  459. List.foldBack (Map.add id) matches results
  460. | ScalarMap(_,_,se,_) ->ApplyScalarExpr(se,results)
  461. | ScalarDemultiplex(_,_,ve,_) ->ApplyVectorExpr(ve,results)
  462. and ApplyVectorExpr(ve,results) =
  463. match ve with
  464. | VectorInput(id,n) ->
  465. let matches = vectorinputs
  466. |> List.filter (fun (inputname,_,_) ->inputname=n)
  467. |> List.map (fun (_,size,inputvalues:obj list) ->
  468. let results = inputvalues|>List.mapi(fun i value->i,Available(value,now,BoundInputVector))
  469. VectorResult(ResultVector(size,DateTime.MinValue,results|>Map.ofList))
  470. )
  471. List.foldBack (Map.add id) matches results
  472. | VectorScanLeft(_,_,a,i,_) ->ApplyVectorExpr(i,ApplyScalarExpr(a,results))
  473. | VectorMap(_,_,i,_)
  474. | VectorStamp(_,_,i,_) ->ApplyVectorExpr(i,results)
  475. | VectorMultiplex(_,_,i,_) ->ApplyScalarExpr(i,results)
  476. let ApplyExpr expr results =
  477. match expr with
  478. | ScalarBuildRule se ->ApplyScalarExpr(se,results)
  479. | VectorBuildRule ve ->ApplyVectorExpr(ve,results)
  480. // Place vector inputs into results map.
  481. let results = List.foldBack ApplyExpr (buildRules.RuleList |> List.map snd) Map.empty
  482. PartialBuild(buildRules,results)
  483. /// Visit each executable action and call actionFunc with the given accumulator.
  484. let ForeachAction output bt (actionFunc:Action->'acc->'acc) (acc:'acc) =
  485. use t = Trace.Call("IncrementalBuildVerbose", "ForeachAction", fun _->sprintf "name=%s" output)
  486. let seen = Dictionary<_,_>()
  487. let Seen(id) =
  488. if seen.ContainsKey(id) then true
  489. else seen.[id]<-true
  490. false
  491. let HasChanged(inputtimestamp,outputtimestamp) =
  492. if inputtimestamp<>outputtimestamp then
  493. Trace.PrintLine("IncrementalBuildVerbose", fun _ -> sprintf "Input timestamp is %A. Output timestamp is %A." inputtimestamp outputtimestamp)
  494. true
  495. else false
  496. let ShouldEvaluate(bt,currentsig:InputSignature,id) =
  497. let isAvailable = currentsig.IsEvaluated()
  498. if isAvailable then
  499. let priorsig = Signature(bt,id)
  500. currentsig<>priorsig
  501. else false
  502. /// Make sure the result vector saved matches the size of expr
  503. let ResizeVectorExpr(ve:VectorBuildRule,acc) =
  504. let id = VectorBuildRule.GetId ve
  505. match GetVectorWidthByExpr(bt,ve) with
  506. | Some(expectedWidth) ->
  507. match bt.Results.TryFind(id) with
  508. | Some(found) ->
  509. match found with
  510. | VectorResult rv ->
  511. if rv.Size<> expectedWidth then
  512. actionFunc (ResizeResultAction(id,expectedWidth)) acc
  513. else acc
  514. | _ -> acc
  515. | None -> acc
  516. | None -> acc
  517. let rec VisitVector ve acc =
  518. if Seen(VectorBuildRule.GetId ve) then acc
  519. else
  520. Trace.PrintLine("IncrementalBuildVerbose", fun _ -> sprintf "In ForeachAction at vector expression %s" (ve.ToString()))
  521. let acc = ResizeVectorExpr(ve,acc)
  522. match ve with
  523. | VectorInput _ ->acc
  524. | VectorScanLeft(id,taskname,accumulatorExpr,inputExpr,func) ->
  525. let acc =
  526. match GetVectorWidthByExpr(bt,ve) with
  527. | Some(cardinality) ->
  528. let GetInputAccumulator slot =
  529. if slot=0 then GetScalarExprResult(bt,accumulatorExpr)
  530. else GetVectorExprResult(bt,ve,slot-1)
  531. let Scan slot =
  532. let accumulatorResult = GetInputAccumulator slot
  533. let inputResult = GetVectorExprResult(bt,inputExpr,slot)
  534. match accumulatorResult,inputResult with
  535. | Available(accumulator,accumulatortimesamp,_accumulatorInputSig),Available(input,inputtimestamp,_inputSig) ->
  536. let inputtimestamp = max inputtimestamp accumulatortimesamp
  537. let prevoutput = GetVectorExprResult(bt,ve,slot)
  538. let outputtimestamp = Result.Timestamp prevoutput
  539. let scanOp =
  540. if HasChanged(inputtimestamp,outputtimestamp) then
  541. Some (fun () -> func accumulator input)
  542. elif prevoutput.ResultIsInProgress then
  543. Some prevoutput.GetInProgressContinuation
  544. else
  545. // up-to-date and complete, no work required
  546. None
  547. match scanOp with
  548. | Some scanOp -> Some(actionFunc (IndexedAction(id,taskname,slot,cardinality,inputtimestamp,scanOp)) acc)
  549. | None -> None
  550. | _ -> None
  551. match ([0..cardinality-1]|>List.tryPick Scan) with Some(acc) ->acc | None->acc
  552. | None -> acc
  553. // Check each slot for an action that may be performed.
  554. VisitVector inputExpr (VisitScalar accumulatorExpr acc)
  555. | VectorMap(id, taskname, inputExpr, func) ->
  556. let acc =
  557. match GetVectorWidthByExpr(bt,ve) with
  558. | Some(cardinality) ->
  559. if cardinality=0 then
  560. // For vector length zero, just propagate the prior timestamp.
  561. let inputtimestamp = MaxTimestamp(bt,VectorBuildRule.GetId(inputExpr),DateTime.MinValue)
  562. let outputtimestamp = MaxTimestamp(bt,id,DateTime.MinValue)
  563. if HasChanged(inputtimestamp,outputtimestamp) then
  564. Trace.PrintLine("IncrementalBuildVerbose", fun _ -> sprintf "Vector Map with cardinality zero setting output timestamp to %A." inputtimestamp)
  565. actionFunc (VectorAction(id,taskname,inputtimestamp,EmptyTimeStampedInput inputtimestamp, fun _ ->[||])) acc
  566. else acc
  567. else
  568. let MapResults acc slot =
  569. let inputtimestamp = Result.Timestamp (GetVectorExprResult(bt,inputExpr,slot))
  570. let outputtimestamp = Result.Timestamp (GetVectorExprResult(bt,ve,slot))
  571. if HasChanged(inputtimestamp,outputtimestamp) then
  572. let OneToOneOp() =
  573. Eventually.Done (func (Result.GetAvailable (GetVectorExprResult(bt,inputExpr,slot))))
  574. actionFunc (IndexedAction(id,taskname,slot,cardinality,inputtimestamp,OneToOneOp)) acc
  575. else acc
  576. [0..cardinality-1] |> List.fold MapResults acc
  577. | None -> acc
  578. VisitVector inputExpr acc
  579. | VectorStamp(id, taskname, inputExpr, func) ->
  580. // For every result that is available, check time stamps.
  581. let acc =
  582. match GetVectorWidthByExpr(bt,ve) with
  583. | Some(cardinality) ->
  584. if cardinality=0 then
  585. // For vector length zero, just propagate the prior timestamp.
  586. let inputtimestamp = MaxTimestamp(bt,VectorBuildRule.GetId(inputExpr),DateTime.MinValue)
  587. let outputtimestamp = MaxTimestamp(bt,id,DateTime.MinValue)
  588. if HasChanged(inputtimestamp,outputtimestamp) then
  589. Trace.PrintLine("IncrementalBuildVerbose", fun _ -> sprintf "Vector Stamp with cardinality zero setting output timestamp to %A." inputtimestamp)
  590. actionFunc (VectorAction(id,taskname,inputtimestamp,EmptyTimeStampedInput inputtimestamp,fun _ ->[||])) acc
  591. else acc
  592. else
  593. let CheckStamp acc slot =
  594. let inputresult = GetVectorExprResult(bt,inputExpr,slot)
  595. match inputresult with
  596. | Available(ires,_,_) ->
  597. let oldtimestamp = Result.Timestamp (GetVectorExprResult(bt,ve,slot))
  598. let newtimestamp = func ires
  599. if newtimestamp<>oldtimestamp then
  600. Trace.PrintLine("IncrementalBuildVerbose", fun _ -> sprintf "Old timestamp was %A. New timestamp is %A." oldtimestamp newtimestamp)
  601. actionFunc (IndexedAction(id,taskname,slot,cardinality,newtimestamp, fun _ -> Eventually.Done ires)) acc
  602. else acc
  603. | _ -> acc
  604. [0..cardinality-1] |> List.fold CheckStamp acc
  605. | None -> acc
  606. VisitVector inputExpr acc
  607. | VectorMultiplex(id, taskname, inputExpr, func) ->
  608. VisitScalar inputExpr
  609. (match GetScalarExprResult(bt,inputExpr) with
  610. | Available(inp,inputtimestamp,inputsig) ->
  611. let outputtimestamp = MaxTimestamp(bt,id,inputtimestamp)
  612. if HasChanged(inputtimestamp,outputtimestamp) then
  613. let MultiplexOp() = func inp
  614. actionFunc (VectorAction(id,taskname,inputtimestamp,inputsig,MultiplexOp)) acc
  615. else acc
  616. | _->acc)
  617. and VisitScalar se acc =
  618. if Seen(ScalarBuildRule.GetId se) then acc
  619. else
  620. Trace.PrintLine("IncrementalBuildVerbose", fun _ -> sprintf "In ForeachAction at scalar expression %s" (se.ToString()))
  621. match se with
  622. | ScalarInput _ ->acc
  623. | ScalarDemultiplex(id,taskname,inputExpr,func) ->
  624. VisitVector inputExpr
  625. (
  626. match GetVectorExprResultVector(bt,inputExpr) with
  627. | Some(inputresult) ->
  628. let currentsig = inputresult.Signature()
  629. if ShouldEvaluate(bt,currentsig,id) then
  630. let inputtimestamp = MaxTimestamp(bt, VectorBuildRule.GetId(inputExpr), DateTime.MaxValue)
  631. let DemultiplexOp() =
  632. let input = AvailableAllResultsOfExpr bt inputExpr |> List.toArray
  633. func input
  634. actionFunc (ScalarAction(id,taskname,inputtimestamp,currentsig,DemultiplexOp)) acc
  635. else acc
  636. | None -> acc
  637. )
  638. | ScalarMap(id,taskname,inputExpr,func) ->
  639. VisitScalar inputExpr
  640. (match GetScalarExprResult(bt,inputExpr) with
  641. | Available(inp,inputtimestamp,inputsig) ->
  642. let outputtimestamp = MaxTimestamp(bt, id, inputtimestamp)
  643. if HasChanged(inputtimestamp,outputtimestamp) then
  644. let MapOp() = func inp
  645. actionFunc (ScalarAction(id,taskname,inputtimestamp,inputsig,MapOp)) acc
  646. else acc
  647. | _->acc)
  648. let Visit expr acc =
  649. match expr with
  650. | ScalarBuildRule se ->VisitScalar se acc
  651. | VectorBuildRule ve ->VisitVector ve acc
  652. let filtered = bt.Rules.RuleList |> List.filter (fun (s,_) -> s = output) |> List.map snd
  653. List.foldBack Visit filtered acc
  654. /// Given the result of a single action, apply that action to the Build
  655. let ApplyResult(actionResult:ActionResult,bt:PartialBuild) =
  656. use t = Trace.Call("IncrementalBuildVerbose", "ApplyResult", fun _ -> "")
  657. let result =
  658. match actionResult with
  659. | ResizeResult(id,slotcount) ->
  660. match bt.Results.TryFind(id) with
  661. | Some(resultSet) ->
  662. match resultSet with
  663. | VectorResult rv ->
  664. let rv = rv.Resize(slotcount)
  665. let results = Map.add id (VectorResult rv) bt.Results
  666. PartialBuild(bt.Rules,results)
  667. | _ -> failwith "Unexpected"
  668. | None -> failwith "Unexpected"
  669. | ScalarValuedResult(id,value,timestamp,inputsig) ->
  670. PartialBuild(bt.Rules, Map.add id (ScalarResult(Available(value,timestamp,inputsig))) bt.Results)
  671. | VectorValuedResult(id,values,timestamp,inputsig) ->
  672. let Append acc slot =
  673. Map.add slot (Available(values.[slot],timestamp,inputsig)) acc
  674. let results = [0..values.Length-1]|>List.fold Append (Map.empty)
  675. let results = VectorResult(ResultVector(values.Length,timestamp,results))
  676. let bt = PartialBuild(bt.Rules, Map.add id results bt.Results)
  677. bt
  678. | IndexedResult(id,index,slotcount,value,timestamp) ->
  679. let width = (GetVectorWidthById bt id)
  680. let priorResults = bt.Results.TryFind(id)
  681. let prior =
  682. match priorResults with
  683. | Some(prior) ->prior
  684. | None->VectorResult(ResultVector.OfSize width)
  685. match prior with
  686. | VectorResult rv ->
  687. let result =
  688. match value with
  689. | Eventually.Done res ->
  690. Trace.PrintLine("FSharpBackgroundBuildVerbose", fun _ -> "Eventually.Done...")
  691. Available(res,timestamp, IndexedValueElement timestamp)
  692. | Eventually.NotYetDone f ->
  693. Trace.PrintLine("FSharpBackgroundBuildVerbose", fun _ -> "Eventually.NotYetDone...")
  694. InProgress (f,timestamp)
  695. let results = rv.Resize(slotcount).Set(index,result)
  696. PartialBuild(bt.Rules, Map.add id (VectorResult(results)) bt.Results)
  697. | _->failwith "Unexpected"
  698. result
  699. /// Evaluate the result of a single output
  700. let EvalLeafsFirst output bt =
  701. use t = Trace.Call("IncrementalBuildVerbose", "EvalLeafsFirst", fun _->sprintf "name=%s" output)
  702. let ExecuteApply action bt =
  703. let actionResult = Action.Execute(action)
  704. ApplyResult(actionResult,bt)
  705. let rec Eval(bt,gen) =
  706. Trace.PrintLine("FSharpBackgroundBuildVerbose", fun _ -> sprintf "---- Build generation %d ----" gen)
  707. #if DEBUG
  708. // This can happen, for example, if there is a task whose timestamp never stops increasing.
  709. // Possibly could detect this case directly.
  710. if gen>5000 then failwith "Infinite loop in incremental builder?"
  711. #endif
  712. let newBt = ForeachAction output bt ExecuteApply bt
  713. if newBt=bt then bt else Eval(newBt,gen+1)
  714. Eval(bt,0)
  715. let Step output (bt:PartialBuild) =
  716. use t = Trace.Call("IncrementalBuildVerbose", "Step", fun _->sprintf "name=%s" output)
  717. let BuildActionList() =
  718. use t = Trace.Call("IncrementalBuildVerbose", "BuildActionList", fun _->sprintf "name=%s" output)
  719. let Cons action list = action :: list
  720. // Hey look, we're building up the whole list, executing one thing and then throwing
  721. // the list away. What about saving the list inside the Build instance?
  722. ForeachAction output bt Cons []
  723. let ExecuteOneAction(worklist) =
  724. use t = Trace.Call("IncrementalBuildVerbose", "ExecuteOneAction", fun _->sprintf "name=%s" output)
  725. match worklist with
  726. | action::_ ->
  727. let actionResult = Action.Execute(action)
  728. Some(ApplyResult(actionResult,bt))
  729. | _->None
  730. ExecuteOneAction(BuildActionList())
  731. /// Eval by calling step over and over until done.
  732. let rec EvalStepwise output bt =
  733. use t = Trace.Call("IncrementalBuildVerbose", "EvalStepwise", fun _->sprintf "name=%s" output)
  734. let rec Evaluate(output,bt)=
  735. let newBt = Step output bt
  736. match newBt with
  737. | Some(newBt) -> Evaluate(output,newBt)
  738. | None->bt
  739. Evaluate(output,bt)
  740. /// Evaluate a build.
  741. let Eval output bt = EvalLeafsFirst output bt
  742. /// Get a scalar vector. Result must be available
  743. let GetScalarResult<'T>(name,bt) : ('T*DateTime) option =
  744. use t = Trace.Call("IncrementalBuildVerbose", "GetScalarResult", fun _->sprintf "name=%s" name)
  745. match GetTopLevelExprByName(bt,name) with
  746. | ScalarBuildRule se ->
  747. let id = ScalarBuildRule.GetId se
  748. match bt.Results.TryFind(id) with
  749. | Some(result) ->
  750. match result with
  751. | ScalarResult(sr) ->
  752. match sr.TryGetAvailable() with
  753. | Some(r,timestamp,_) -> Some(downcast r, timestamp)
  754. | None -> None
  755. | _ ->failwith "Expected a scalar result."
  756. | None->None
  757. | VectorBuildRule _ -> failwith "Expected scalar."
  758. /// Get a result vector. All results must be available or thrown an exception.
  759. let GetVectorResult<'T>(name,bt) : 'T[] =
  760. match GetTopLevelExprByName(bt,name) with
  761. | ScalarBuildRule _ -> failwith "Expected vector."
  762. | VectorBuildRule ve -> AvailableAllResultsOfExpr bt ve |> List.map(unbox) |> Array.ofList
  763. /// Get an element of vector result or None if there were no results.
  764. let GetVectorResultBySlot<'T>(name,slot,bt) : ('T*DateTime) option =
  765. match GetTopLevelExprByName(bt,name) with
  766. | ScalarBuildRule _ -> failwith "Expected vector expression"
  767. | VectorBuildRule ve ->
  768. match GetVectorExprResult(bt,ve,slot).TryGetAvailable() with
  769. | Some(o,timestamp,_) -> Some(downcast o,timestamp)
  770. | None->None
  771. /// Given an input value, find the corresponding slot.
  772. let GetSlotByInput<'T>(name:string,input:'T,build:PartialBuild,equals:'T->'T->bool) : int =
  773. let expr = GetExprByName(build,name)
  774. let id = BuildRuleExpr.GetId(expr)
  775. let resultSet = Option.get ( build.Results.TryFind(id))
  776. match resultSet with
  777. | VectorResult rv ->
  778. let MatchNames acc (slot,result) =
  779. match result with
  780. | Available(o,_,_) ->
  781. let o = o :?> 'T
  782. if equals o input then Some slot else acc
  783. | _ -> acc
  784. let slotOption = rv.FoldLeft MatchNames None
  785. match slotOption with
  786. | Some slot -> slot
  787. | _ -> failwith (sprintf "Could not find requested input '%A' named '%s' in set %+A" input name rv)
  788. | _ -> failwith (sprintf "Could not find requested input: %A" input)
  789. // Redeclare functions in the incremental build scope-----------------------------------------------------------------------
  790. // Methods for declaring inputs and outputs
  791. /// Declares a vector build input.
  792. let InputVector<'T> name =
  793. let expr = VectorInput(NextId(),name)
  794. { new Vector<'T>
  795. interface IVector with
  796. override pe.GetVectorExpr() = expr }
  797. /// Declares a scalar build input.
  798. let InputScalar<'T> name =
  799. let expr = ScalarInput(NextId(),name)
  800. { new Scalar<'T>
  801. interface IScalar with
  802. override pe.GetScalarExpr() = expr }
  803. module Scalar =
  804. let Map (taskname:string) (task:'I->'O) (input:Scalar<'I>) : Scalar<'O> =
  805. let BoxingMap i = box(task(unbox(i)))
  806. let input = (input:?>IScalar).GetScalarExpr()
  807. let expr = ScalarMap(NextId(),taskname,input,BoxingMap)
  808. { new Scalar<'O>
  809. interface IScalar with
  810. override pe.GetScalarExpr() = expr}
  811. let Multiplex (taskname:string) (task:'I -> 'O array) (input:Scalar<'I>) : Vector<'O> =
  812. let BoxingMultiplex i = Array.map box (task(unbox(i)))
  813. let input = (input:?>IScalar).GetScalarExpr()
  814. let expr = VectorMultiplex(NextId(),taskname,input,BoxingMultiplex)
  815. { new Vector<'O>
  816. interface IVector with
  817. override pe.GetVectorExpr() = expr}
  818. module Vector =
  819. /// Maps one vector to another using the given function.
  820. let Map (taskname:string) (task:'I ->'O) (input:Vector<'I>) : Vector<'O> =
  821. let BoxingMapVector i =
  822. box(task(unbox i))
  823. let input = (input:?>IVector).GetVectorExpr()
  824. let expr = VectorMap(NextId(),taskname,input,BoxingMapVector)
  825. { new Vector<'O>
  826. interface IVector with
  827. override pe.GetVectorExpr() = expr }
  828. /// Apply a function to each element of the vector, threading an accumulator argument
  829. /// through the computation. Returns intermediate results in a vector.
  830. let ScanLeft (taskname:string) (task:'A -> 'I -> Eventually<'A>) (acc:Scalar<'A>) (input:Vector<'I>) : Vector<'A> =
  831. let BoxingScanLeft a i =
  832. Eventually.box(task (unbox a) (unbox i))
  833. let acc = (acc:?>IScalar).GetScalarExpr()
  834. le

Large files files are truncated, but you can click here to view the full file