Skip to content

Commit cc7f18b

Browse files
committed
conn: Speed up finding relevant scoped defs
stack-info: PR: #343, branch: artempyanykh/stack/3
1 parent f5999e6 commit cc7f18b

File tree

1 file changed

+48
-18
lines changed

1 file changed

+48
-18
lines changed

Marksman/Conn.fs

+48-18
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,46 @@ type ConnDifference =
7979

8080
concatLines lines
8181

82+
type Defs =
83+
{ byScope: MMap<Scope, Def>
84+
bySlug: MMap<ScopeSlug, Scope * Def> }
85+
86+
static member Empty = { byScope = MMap.empty; bySlug = MMap.empty }
87+
88+
member this.IsEmpty = MMap.isEmpty this.byScope
89+
90+
member this.AllSeq = MMap.toSeq this.byScope
91+
92+
member this.AllSetSeq = MMap.toSetSeq this.byScope
93+
94+
member this.Add(scope: Scope, def: Def) : Defs =
95+
let byScope = this.byScope |> MMap.add scope def
96+
97+
let scopeSlug = ScopeSlug.ofScopedDef (scope, def)
98+
99+
let bySlug =
100+
scopeSlug
101+
|> Option.map (fun x -> this.bySlug |> MMap.add x (scope, def))
102+
|> Option.defaultValue this.bySlug
103+
104+
{ byScope = byScope; bySlug = bySlug }
105+
106+
member this.Remove(scope: Scope, def: Def) : Defs =
107+
let byScope = this.byScope |> MMap.removeValue scope def
108+
109+
let scopeSlug = ScopeSlug.ofScopedDef (scope, def)
110+
111+
let bySlug =
112+
scopeSlug
113+
|> Option.map (fun x -> this.bySlug |> MMap.removeValue x (scope, def))
114+
|> Option.defaultValue this.bySlug
115+
116+
{ byScope = byScope; bySlug = bySlug }
117+
118+
82119
type Conn =
83120
{ refs: MMap<Scope, Ref>
84-
defs: MMap<Scope, Def>
121+
defs: Defs
85122
tags: MMap<Scope, Tag>
86123
resolved: Graph<ScopedSym>
87124
unresolved: Graph<Unresolved>
@@ -141,10 +178,10 @@ type Conn =
141178
for ref in refs do
142179
yield Indented(4, ref).ToString()
143180

144-
if this.defs |> MMap.isEmpty |> not then
181+
if not this.defs.IsEmpty then
145182
yield "Defs:"
146183

147-
for scope, defs in MMap.toSetSeq this.defs do
184+
for scope, defs in this.defs.AllSetSeq do
148185
yield $" {scope}:"
149186

150187
for def in defs do
@@ -182,7 +219,7 @@ module Conn =
182219

183220
let empty =
184221
{ refs = MMap.empty
185-
defs = MMap.empty
222+
defs = Defs.Empty
186223
tags = MMap.empty
187224
resolved = Graph.empty
188225
unresolved = Graph.empty
@@ -191,7 +228,7 @@ module Conn =
191228

192229
let isSameStructure c1 c2 =
193230
c1.refs = c2.refs
194-
&& c1.defs = c2.defs
231+
&& c1.defs.byScope = c2.defs.byScope
195232
&& c1.tags = c2.tags
196233
&& c1.resolved = c2.resolved
197234
&& c1.unresolved = c2.unresolved
@@ -296,7 +333,7 @@ module Conn =
296333
| _, Sym.Def _
297334
| _, Sym.Tag _ -> ()
298335

299-
defs <- MMap.removeValue scope def defs
336+
defs <- defs.Remove(scope, def)
300337
resolved <- Graph.removeVertexWithCallback cb scopedSym resolved
301338

302339
// When the doc is removed we need to remove all unresolved links within this doc's scope
@@ -326,15 +363,15 @@ module Conn =
326363
| CrossRef(CrossDoc _)
327364
| IntraRef _ -> ()
328365
| Sym.Def def ->
329-
defs <- MMap.add scope def defs
366+
defs <- defs.Add(scope, def)
330367

331368
match def with
332369
| Doc
333370
| Header(1, _) ->
334371
// Whenever a new title is added, links that were previously pointing at the Doc
335372
// or the other titles need to be invalidated
336373
let affectedDefs =
337-
defs
374+
defs.byScope
338375
|> MMap.tryFind scope
339376
|> Option.defaultValue Set.empty
340377
|> Seq.filter Def.isTitle
@@ -344,18 +381,11 @@ module Conn =
344381
// Similarly, other doc/titles could resolve to the same scope group
345382
let scopeSlug = ScopeSlug.ofScopedDef (scope, def)
346383

347-
// TODO: we could do this faster if the groups were maintained in a set
348384
let affectedDefsInOtherScopes =
349385
match scopeSlug with
350-
| None -> Seq.empty
386+
| None -> Set.empty
351387
| Some scopeSlug ->
352-
defs
353-
|> MMap.toSeq
354-
|> Seq.choose (fun scopedDef ->
355-
ScopeSlug.ofScopedDef scopedDef
356-
|> Option.map (fun slug -> scopedDef, slug))
357-
|> Seq.filter (fun (_, slug) -> slug = scopeSlug)
358-
|> Seq.map fst
388+
MMap.tryFind scopeSlug defs.bySlug |> Option.defaultValue Set.empty
359389

360390
let affectedDefs =
361391
affectedDefs |> Seq.append affectedDefsInOtherScopes |> Set.ofSeq
@@ -470,7 +500,7 @@ module Conn =
470500

471501
let difference c1 c2 : ConnDifference =
472502
{ refsDifference = MMap.difference c1.refs c2.refs
473-
defsDifference = MMap.difference c1.defs c2.defs
503+
defsDifference = MMap.difference c1.defs.byScope c2.defs.byScope
474504
tagsDifference = MMap.difference c1.tags c2.tags
475505
resolvedDifference = Graph.difference c1.resolved c2.resolved
476506
unresolvedDifference = Graph.difference c1.unresolved c2.unresolved

0 commit comments

Comments
 (0)