123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- import std/[intsets, tables, algorithm, assertions]
- import ast, lineinfos, msgs
- type
- PackedBoolArray* = object
- s: IntSet
- len: int
- TinyLineInfo* = object
- line*: uint16
- col*: int16
- SymInfoPair* = object
- sym*: PSym
- info*: TLineInfo
- caughtExceptions*: seq[PType]
- caughtExceptionsSet*: bool
- isDecl*: bool
- SuggestFileSymbolDatabase* = object
- lineInfo*: seq[TinyLineInfo]
- sym*: seq[PSym]
- caughtExceptions*: seq[seq[PType]]
- caughtExceptionsSet*: PackedBoolArray
- isDecl*: PackedBoolArray
- fileIndex*: FileIndex
- trackCaughtExceptions*: bool
- isSorted*: bool
- SuggestSymbolDatabase* = Table[FileIndex, SuggestFileSymbolDatabase]
- func newPackedBoolArray*(): PackedBoolArray =
- PackedBoolArray(
- s: initIntSet(),
- len: 0
- )
- func low*(s: PackedBoolArray): int =
- 0
- func high*(s: PackedBoolArray): int =
- s.len - 1
- func `[]`*(s: PackedBoolArray; idx: int): bool =
- s.s.contains(idx)
- proc `[]=`*(s: var PackedBoolArray; idx: int; v: bool) =
- if v:
- s.s.incl(idx)
- else:
- s.s.excl(idx)
- proc add*(s: var PackedBoolArray; v: bool) =
- inc(s.len)
- if v:
- s.s.incl(s.len - 1)
- proc reverse*(s: var PackedBoolArray) =
- var
- reversedSet = initIntSet()
- for i in 0..s.high:
- if s.s.contains(i):
- reversedSet.incl(s.high - i)
- s.s = reversedSet
- proc getSymInfoPair*(s: SuggestFileSymbolDatabase; idx: int): SymInfoPair =
- SymInfoPair(
- sym: s.sym[idx],
- info: TLineInfo(
- line: s.lineInfo[idx].line,
- col: s.lineInfo[idx].col,
- fileIndex: s.fileIndex
- ),
- caughtExceptions:
- if s.trackCaughtExceptions:
- s.caughtExceptions[idx]
- else:
- @[],
- caughtExceptionsSet:
- if s.trackCaughtExceptions:
- s.caughtExceptionsSet[idx]
- else:
- false,
- isDecl: s.isDecl[idx]
- )
- proc reverse*(s: var SuggestFileSymbolDatabase) =
- s.lineInfo.reverse()
- s.sym.reverse()
- s.caughtExceptions.reverse()
- s.caughtExceptionsSet.reverse()
- s.isDecl.reverse()
- proc newSuggestFileSymbolDatabase*(aFileIndex: FileIndex; aTrackCaughtExceptions: bool): SuggestFileSymbolDatabase =
- SuggestFileSymbolDatabase(
- lineInfo: @[],
- sym: @[],
- caughtExceptions: @[],
- caughtExceptionsSet: newPackedBoolArray(),
- isDecl: newPackedBoolArray(),
- fileIndex: aFileIndex,
- trackCaughtExceptions: aTrackCaughtExceptions,
- isSorted: true
- )
- proc exactEquals*(a, b: TinyLineInfo): bool =
- result = a.line == b.line and a.col == b.col
- proc `==`*(a, b: SymInfoPair): bool =
- result = a.sym == b.sym and a.info.exactEquals(b.info)
- func cmp*(a: TinyLineInfo; b: TinyLineInfo): int =
- result = cmp(a.line, b.line)
- if result == 0:
- result = cmp(a.col, b.col)
- func compare*(s: var SuggestFileSymbolDatabase; i, j: int): int =
- result = cmp(s.lineInfo[i], s.lineInfo[j])
- if result == 0:
- result = cmp(s.isDecl[i], s.isDecl[j])
- proc exchange(s: var SuggestFileSymbolDatabase; i, j: int) =
- if i == j:
- return
- var tmp1 = s.lineInfo[i]
- s.lineInfo[i] = s.lineInfo[j]
- s.lineInfo[j] = tmp1
- if s.trackCaughtExceptions:
- var tmp2 = s.caughtExceptions[i]
- s.caughtExceptions[i] = s.caughtExceptions[j]
- s.caughtExceptions[j] = tmp2
- var tmp3 = s.caughtExceptionsSet[i]
- s.caughtExceptionsSet[i] = s.caughtExceptionsSet[j]
- s.caughtExceptionsSet[j] = tmp3
- var tmp4 = s.isDecl[i]
- s.isDecl[i] = s.isDecl[j]
- s.isDecl[j] = tmp4
- var tmp5 = s.sym[i]
- s.sym[i] = s.sym[j]
- s.sym[j] = tmp5
- proc quickSort(s: var SuggestFileSymbolDatabase; ll, rr: int) =
- var
- i, j, pivotIdx: int
- l = ll
- r = rr
- while true:
- i = l
- j = r
- pivotIdx = l + ((r - l) shr 1)
- while true:
- while (i < pivotIdx) and (s.compare(pivotIdx, i) > 0):
- inc i
- while (j > pivotIdx) and (s.compare(pivotIdx, j) < 0):
- dec j
- if i < j:
- s.exchange(i, j)
- if pivotIdx == i:
- pivotIdx = j
- inc i
- elif pivotIdx == j:
- pivotIdx = i
- dec j
- else:
- inc i
- dec j
- else:
- break
- if (pivotIdx - l) < (r - pivotIdx):
- if (l + 1) < pivotIdx:
- s.quickSort(l, pivotIdx - 1)
- l = pivotIdx + 1
- else:
- if (pivotIdx + 1) < r:
- s.quickSort(pivotIdx + 1, r)
- if (l + 1) < pivotIdx:
- r = pivotIdx - 1
- else:
- break
- if l >= r:
- break
- proc sort*(s: var SuggestFileSymbolDatabase) =
- s.quickSort(s.lineInfo.low, s.lineInfo.high)
- s.isSorted = true
- proc add*(s: var SuggestFileSymbolDatabase; v: SymInfoPair) =
- doAssert(v.info.fileIndex == s.fileIndex)
- s.lineInfo.add(TinyLineInfo(
- line: v.info.line,
- col: v.info.col
- ))
- s.sym.add(v.sym)
- s.isDecl.add(v.isDecl)
- if s.trackCaughtExceptions:
- s.caughtExceptions.add(v.caughtExceptions)
- s.caughtExceptionsSet.add(v.caughtExceptionsSet)
- s.isSorted = false
- proc add*(s: var SuggestSymbolDatabase; v: SymInfoPair; trackCaughtExceptions: bool) =
- s.mgetOrPut(v.info.fileIndex, newSuggestFileSymbolDatabase(v.info.fileIndex, trackCaughtExceptions)).add(v)
- proc findSymInfoIndex*(s: var SuggestFileSymbolDatabase; li: TLineInfo): int =
- doAssert(li.fileIndex == s.fileIndex)
- if not s.isSorted:
- s.sort()
- var q = TinyLineInfo(
- line: li.line,
- col: li.col
- )
- result = binarySearch(s.lineInfo, q, cmp)
|