diff options
Diffstat (limited to 'compiler/suggestsymdb.nim')
-rw-r--r-- | compiler/suggestsymdb.nim | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/compiler/suggestsymdb.nim b/compiler/suggestsymdb.nim new file mode 100644 index 000000000..e1e67afbe --- /dev/null +++ b/compiler/suggestsymdb.nim @@ -0,0 +1,212 @@ +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) |