@@ -5,68 +5,33 @@ open System.Collections.Concurrent
55open System.Collections .Generic
66open System.Threading
77open System.Threading .Tasks
8- open FSharp.Compiler .Service .Tests2
9- open FSharp.Compiler .Service .Tests2 .DepResolving
8+ open FSharp.Compiler .Service .Tests .Graph
109open NUnit.Framework
1110
12- type FileIdx =
13- FileIdx of int
14- with
15- member this.Idx = match this with FileIdx idx -> idx
16- override this.ToString () = this.Idx.ToString ()
17- static member make ( idx : int ) = FileIdx idx
18-
11+ [<Test>]
12+ let runCompiler () =
13+ let args =
14+ System.IO.File.ReadAllLines ( @" C:\projekty\fsharp\heuristic\tests\FSharp.Compiler.Service.Tests2\args.txt " ) |> Array.skip 1
15+ FSharp.Compiler.CommandLineMain.main args |> ignore
16+
17+ [<CustomEquality ; NoComparison>]
1918type Node =
2019 {
2120 Idx : FileIdx
2221 Deps : FileIdx []
2322 TransitiveDeps : FileIdx []
2423 Dependants : FileIdx []
2524 mutable PartialResult : string option
26- mutable ThisResult : int
25+ mutable ThisResult : int option
2726 mutable UnprocessedDepsCount : int
2827 _lock : Object
2928 }
30- with member this.GetHashCode () = this.Idx.Idx
31-
32- [<Test>]
33- let runCompiler () =
34- let args =
35- System.IO.File.ReadAllLines( @" C:\projekty\fsharp\heuristic\tests\FSharp.Compiler.Service.Tests2\args.txt" ) |> Array.skip 1
36- FSharp.Compiler.CommandLineMain.main args |> ignore
37-
38-
39-
40- /// <summary> DAG of files </summary>
41- type FileGraph = IReadOnlyDictionary< FileIdx, FileIdx[]>
42-
43- let memoize < 'a , 'b when 'a : equality > f : ( 'a -> 'b ) =
44- let y = HashIdentity.Structural< 'a>
45- let d = new ConcurrentDictionary< 'a, 'b>( y)
46- fun x -> d.GetOrAdd( x, fun r -> f r)
29+ override this.Equals ( y ) =
30+ match y with
31+ | :? Node as other -> ( this.Idx = other.Idx)
32+ | _ -> false
33+ override this.GetHashCode () = this.Idx.Idx
4734
48- module FileGraph =
49-
50- let calcTransitiveGraph ( graph : FileGraph ) : FileGraph =
51- let transitiveGraph = Dictionary< FileIdx, FileIdx[]>()
52-
53- let rec calcTransitiveEdges =
54- fun ( idx : FileIdx ) ->
55- let edgeTargets = graph[ idx]
56- edgeTargets
57- |> Array.collect calcTransitiveEdges
58- |> Array.append edgeTargets
59- |> Array.distinct
60- |> memoize
61-
62- graph.Keys
63- |> Seq.iter ( fun idx -> calcTransitiveEdges idx |> ignore)
64-
65- transitiveGraph :> IReadOnlyDictionary<_,_>
66-
67- let collectEdges ( graph : FileGraph ) =
68- graph
69-
7035type State = string // TcState
7136type SingleResult = int // partial result for a single file
7237
@@ -75,7 +40,7 @@ type SingleResult = int // partial result for a single file
7540/// </summary>
7641/// <param name="graph"></param>
7742/// <param name="deps">Transitive deps</param>
78- let combineResults ( graph : IReadOnlyDictionary < FileIdx , Node >) ( node : Node ) ( folder : State -> SingleResult -> State ) : State =
43+ let combineResults ( graph : IDictionary < FileIdx , Node >) ( node : Node ) ( folder : State -> SingleResult -> State ) : State =
7944
8045 // Find the child with most transitive deps
8146 let biggestChild =
@@ -93,9 +58,10 @@ let combineResults (graph : IReadOnlyDictionary<FileIdx, Node>) (node : Node) (f
9358 node.TransitiveDeps
9459 |> Array.filter alreadyIncluded.Add
9560
61+ // Add those results to the initial one
9662 let state =
9763 toBeAdded
98- |> Array.map ( fun d -> graph[ d]. ThisResult)
64+ |> Array.map ( fun d -> graph[ d]. ThisResult |> Option.defaultWith ( fun () -> failwith " Unexpected lack of result " ) )
9965 |> Array.fold folder state
10066
10167 state
@@ -125,23 +91,26 @@ let processGraph (graph : IDictionary<FileIdx, Node>) =
12591 let fold ( state : string ) ( singleResult : int ) =
12692 state + singleResult.ToString()
12793
94+ let actualActualWork ( idx : FileIdx ) ( state : State ) : SingleResult * State =
95+ let thisResult = idx.Idx
96+ let state = fold state thisResult
97+ thisResult, state
98+
12899 let actualWork ( idx : FileIdx ) =
129100 let node = graph[ idx]
130- let depsResult =
131- node.Deps
132- |> Array.map ( fun dep -> match graph[ dep]. PartialResult with Some result -> result | None -> failwith $" Unexpected lack of result for a dependency {idx} -> {dep}" )
133- |> Array.fold fold " "
134- let thisResult = idx.Idx
101+ let state = combineResults graph node fold
102+ let thisResult = actualActualWork idx state
135103 thisResult
136104
137105 // Processing of a single node/file - gives a result
138106 let go ( idx : FileIdx ) =
139107 let node = graph[ idx]
140108 printfn $" Start {idx} -> %+A {node.Deps}"
141109 Thread.Sleep( 500 )
142- let res = actualWork idx
143- node.PartialResult <- Some res
144- printfn $" Stop {idx} work - result {res}"
110+ let singleResult , state = actualWork idx
111+ node.ThisResult <- Some singleResult
112+ node.PartialResult <- Some state
113+ printfn $" Stop {idx} work - SingleResult={singleResult} State={state}"
145114
146115 // Increment processed deps count for all dependants and schedule those who are now unblocked
147116 node.Dependants
@@ -197,7 +166,7 @@ let runGrapher () =
197166 // System.IO.File.ReadAllLines(@"C:\projekty\fsharp\heuristic\tests\FSharp.Compiler.Service.Tests2\args.txt") |> Array.skip 1
198167 // FSharp.Compiler.CommandLineMain.main args |> ignore
199168
200- let graph =
169+ let deps : FileGraph =
201170 [|
202171 0 , [||] // A
203172 1 , [| 0 |] // B1 -> A
@@ -206,34 +175,17 @@ let runGrapher () =
206175 4 , [| 3 |] // C2 -> C1
207176 5 , [| 2 ; 4 |] // D -> B2, C2
208177 |]
209- |> dict
178+ |> Array.map ( fun ( a , deps ) -> FileIdx.make a, deps |> Array.map FileIdx.make)
179+ |> readOnlyDict
210180
211- let fileDeps =
212- graph
213- |> DepResolving.calcTransitiveGraph
214-
215- let fileDependants =
216- fileDeps
217- // Collect all edges
218- |> Seq.collect ( fun ( idx , deps ) -> deps |> Array.map ( fun dep -> FileIdx.make idx, FileIdx.make dep))
219- // Group dependants of the same dependencies together
220- |> Array.groupBy ( fun ( idx , dep ) -> dep)
221- // Construct reversed graph
222- |> Array.map ( fun ( dep , edges ) -> dep, edges |> Array.map fst)
223- |> dict
224- // Add nodes that are missing due to having no dependants
225- |> fun graph ->
226- fileDeps
227- |> Array.map ( fun ( idx , deps ) ->
228- match graph.TryGetValue idx with
229- | true , dependants -> idx, dependants
230- | false , _ -> idx, [||]
231- )
232- |> dict
181+ let dependants = deps |> FileGraph.reverse
182+
183+ let transitiveDeps = deps |> FileGraph.calcTransitiveGraph
184+ let transitiveDependants = transitiveDeps |> FileGraph.reverse
233185
234186 let graph =
235- fileDeps
236- |> Seq.map ( fun ( idx , deps ) -> idx, { Idx = idx; Deps = deps; Dependants = fileDependants [ idx]; PartialResult = None; UnprocessedDepsCount = deps.Length; _ lock = Object()})
187+ transitiveDeps
188+ |> Seq.map ( fun ( KeyValue ( idx , deps )) -> idx, { Idx = idx; Deps = deps; Dependants = dependants [ idx]; TransitiveDeps = transitiveDependants [ idx ]; ThisResult = None ; PartialResult = None; UnprocessedDepsCount = deps.Length; _ lock = Object()})
237189 |> dict
238190
239191 processGraph graph
0 commit comments