PageRenderTime 60ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/compiler/2.0/Aug2011.1/src/fsharp/vs/IncrementalBuild.fs

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

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