diff options
Diffstat (limited to 'compiler/idents.nim')
-rw-r--r-- | compiler/idents.nim | 101 |
1 files changed, 59 insertions, 42 deletions
diff --git a/compiler/idents.nim b/compiler/idents.nim index a50c5269c..34177e76d 100644 --- a/compiler/idents.nim +++ b/compiler/idents.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -11,23 +11,29 @@ # An identifier is a shared immutable string that can be compared by its # id. This module is essential for the compiler's performance. -import - hashes, strutils +import wordrecg +import std/hashes -type - TIdObj* = object of TObject - id*: int # unique id; use this for comparisons and not the pointers - - PIdObj* = ref TIdObj +when defined(nimPreviewSlimSystem): + import std/assertions + +type PIdent* = ref TIdent - TIdent*{.acyclic.} = object of TIdObj + TIdent*{.acyclic.} = object + id*: int # unique id; use this for comparisons and not the pointers s*: string next*: PIdent # for hash-table chaining - h*: THash # hash value of s - -var buckets*: array[0..4096 * 2 - 1, PIdent] + h*: Hash # hash value of s + + IdentCache* = ref object + buckets: array[0..4096 * 2 - 1, PIdent] + wordCounter: int + idAnon*, idDelegator*, emptyIdent*: PIdent -proc cmpIgnoreStyle(a, b: cstring, blen: int): int = +proc resetIdentCache*() = discard + +proc cmpIgnoreStyle*(a, b: cstring, blen: int): int = + if a[0] != b[0]: return 1 var i = 0 var j = 0 result = 1 @@ -40,12 +46,12 @@ proc cmpIgnoreStyle(a, b: cstring, blen: int): int = if aa >= 'A' and aa <= 'Z': aa = chr(ord(aa) + (ord('a') - ord('A'))) if bb >= 'A' and bb <= 'Z': bb = chr(ord(bb) + (ord('a') - ord('A'))) result = ord(aa) - ord(bb) - if (result != 0) or (aa == '\0'): break + if (result != 0) or (aa == '\0'): break inc(i) inc(j) if result == 0: if a[i] != '\0': result = 1 - + proc cmpExact(a, b: cstring, blen: int): int = var i = 0 var j = 0 @@ -54,27 +60,25 @@ proc cmpExact(a, b: cstring, blen: int): int = var aa = a[i] var bb = b[j] result = ord(aa) - ord(bb) - if (result != 0) or (aa == '\0'): break + if (result != 0) or (aa == '\0'): break inc(i) inc(j) - if result == 0: + if result == 0: if a[i] != '\0': result = 1 -var wordCounter = 1 - -proc getIdent*(identifier: cstring, length: int, h: THash): PIdent = - var idx = h and high(buckets) - result = buckets[idx] +proc getIdent*(ic: IdentCache; identifier: cstring, length: int, h: Hash): PIdent = + var idx = h and high(ic.buckets) + result = ic.buckets[idx] var last: PIdent = nil var id = 0 - while result != nil: - if cmpExact(cstring(result.s), identifier, length) == 0: - if last != nil: + while result != nil: + if cmpExact(cstring(result.s), identifier, length) == 0: + if last != nil: # make access to last looked up identifier faster: last.next = result.next - result.next = buckets[idx] - buckets[idx] = result - return + result.next = ic.buckets[idx] + ic.buckets[idx] = result + return elif cmpIgnoreStyle(cstring(result.s), identifier, length) == 0: assert((id == 0) or (id == result.id)) id = result.id @@ -83,24 +87,37 @@ proc getIdent*(identifier: cstring, length: int, h: THash): PIdent = new(result) result.h = h result.s = newString(length) - for i in countup(0, length - 1): result.s[i] = identifier[i] - result.next = buckets[idx] - buckets[idx] = result - if id == 0: - inc(wordCounter) - result.id = -wordCounter - else: + for i in 0..<length: result.s[i] = identifier[i] + result.next = ic.buckets[idx] + ic.buckets[idx] = result + if id == 0: + inc(ic.wordCounter) + result.id = -ic.wordCounter + else: result.id = id -proc getIdent*(identifier: string): PIdent = - result = getIdent(cstring(identifier), len(identifier), +proc getIdent*(ic: IdentCache; identifier: string): PIdent = + result = getIdent(ic, cstring(identifier), identifier.len, hashIgnoreStyle(identifier)) -proc getIdent*(identifier: string, h: THash): PIdent = - result = getIdent(cstring(identifier), len(identifier), h) +proc getIdent*(ic: IdentCache; identifier: string, h: Hash): PIdent = + result = getIdent(ic, cstring(identifier), identifier.len, h) -proc IdentEq*(id: PIdent, name: string): bool = - result = id.id == getIdent(name).id +proc newIdentCache*(): IdentCache = + result = IdentCache() + result.idAnon = result.getIdent":anonymous" + result.wordCounter = 1 + result.idDelegator = result.getIdent":delegator" + result.emptyIdent = result.getIdent("") + # initialize the keywords: + for s in succ(low(TSpecialWord))..high(TSpecialWord): + result.getIdent($s, hashIgnoreStyle($s)).id = ord(s) -var idAnon* = getIdent":anonymous" +proc whichKeyword*(id: PIdent): TSpecialWord = + if id.id < 0: result = wInvalid + else: result = TSpecialWord(id.id) +proc hash*(x: PIdent): Hash {.inline.} = x.h +proc `==`*(a, b: PIdent): bool {.inline.} = + if a.isNil or b.isNil: result = system.`==`(a, b) + else: result = a.id == b.id |