got rid of nstrtabs and nhashes modules

This commit is contained in:
Araq 2011-06-10 22:49:06 +02:00
commit 922e216b86
20 changed files with 57 additions and 362 deletions

View file

@ -10,7 +10,7 @@
# abstract syntax tree + symbol table # abstract syntax tree + symbol table
import import
msgs, nhashes, nversion, options, strutils, crc, ropes, idents, lists msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists
const const
ImportTablePos* = 0 ImportTablePos* = 0

View file

@ -12,7 +12,7 @@
# the data structures here are used in various places of the compiler. # the data structures here are used in various places of the compiler.
import import
ast, nhashes, strutils, options, msgs, ropes, idents, rodutils ast, hashes, strutils, options, msgs, ropes, idents, rodutils
proc hashNode*(p: PObject): THash proc hashNode*(p: PObject): THash
proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope
@ -179,7 +179,7 @@ proc getSymFromList(list: PNode, ident: PIdent, start: int = 0): PSym =
result = nil result = nil
proc hashNode(p: PObject): THash = proc hashNode(p: PObject): THash =
result = hashPtr(cast[pointer](p)) result = hash(cast[pointer](p))
proc mustRehash(length, counter: int): bool = proc mustRehash(length, counter: int): bool =
assert(length > counter) assert(length > counter)

View file

@ -10,7 +10,7 @@
# This module declares some helpers for the C code generator. # This module declares some helpers for the C code generator.
import import
ast, astalgo, ropes, lists, nhashes, strutils, types, msgs, wordrecg, ast, astalgo, ropes, lists, hashes, strutils, types, msgs, wordrecg,
platform platform
proc whichPragma*(n: PNode): TSpecialWord = proc whichPragma*(n: PNode): TSpecialWord =

View file

@ -11,7 +11,7 @@
# than the old one. It also generates better code. # than the old one. It also generates better code.
import import
ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp, ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
options, options,
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,

View file

@ -10,7 +10,7 @@
# This module handles the conditional symbols. # This module handles the conditional symbols.
import import
ast, astalgo, msgs, nhashes, platform, strutils, idents ast, astalgo, msgs, hashes, platform, strutils, idents
var gSymbols*: TStrTable var gSymbols*: TStrTable

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -12,7 +12,7 @@
# by knowing how the anchors are going to be named. # by knowing how the anchors are going to be named.
import import
ast, astalgo, strutils, nhashes, options, nversion, msgs, os, ropes, idents, ast, astalgo, strutils, hashes, options, nversion, msgs, os, ropes, idents,
wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite
proc CommandDoc*(filename: string) proc CommandDoc*(filename: string)

View file

@ -12,7 +12,7 @@
# code!** # code!**
import import
ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp, ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os, options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils

View file

@ -12,7 +12,7 @@
# The interface supports one language nested in another. # The interface supports one language nested in another.
import import
nhashes, options, msgs, strutils, platform, idents, lexbase, wordrecg, lexer hashes, options, msgs, strutils, platform, idents, lexbase, wordrecg, lexer
type type
TTokenClass* = enum TTokenClass* = enum

View file

@ -12,7 +12,7 @@
# id. This module is essential for the compiler's performance. # id. This module is essential for the compiler's performance.
import import
nhashes, strutils hashes, strutils
type type
TIdObj* = object of TObject TIdObj* = object of TObject
@ -80,7 +80,7 @@ proc cmpExact(a, b: cstring, blen: int): int =
proc getIdent(identifier: string): PIdent = proc getIdent(identifier: string): PIdent =
result = getIdent(cstring(identifier), len(identifier), result = getIdent(cstring(identifier), len(identifier),
getNormalizedHash(identifier)) hashIgnoreStyle(identifier))
proc getIdent(identifier: string, h: THash): PIdent = proc getIdent(identifier: string, h: THash): PIdent =
result = getIdent(cstring(identifier), len(identifier), h) result = getIdent(cstring(identifier), len(identifier), h)

View file

@ -16,7 +16,7 @@
# DOS or Macintosh text files, even when it is not the native format. # DOS or Macintosh text files, even when it is not the native format.
import import
nhashes, options, msgs, strutils, platform, idents, lexbase, llstream, hashes, options, msgs, strutils, platform, idents, lexbase, llstream,
wordrecg wordrecg
const const
@ -546,17 +546,17 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
var c = buf[pos] var c = buf[pos]
case c case c
of 'a'..'z', '0'..'9', '\x80'..'\xFF': of 'a'..'z', '0'..'9', '\x80'..'\xFF':
h = concHash(h, ord(c)) h = h !& ord(c)
of 'A'..'Z': of 'A'..'Z':
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower() c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = concHash(h, ord(c)) h = h !& ord(c)
of '_': of '_':
if buf[pos+1] notin SymChars: if buf[pos+1] notin SymChars:
lexMessage(L, errInvalidToken, "_") lexMessage(L, errInvalidToken, "_")
break break
else: break else: break
Inc(pos) Inc(pos)
h = finishHash(h) h = !$h
tok.ident = getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h) tok.ident = getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
L.bufpos = pos L.bufpos = pos
if (tok.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or if (tok.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or
@ -567,7 +567,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
proc endOperator(L: var TLexer, tok: var TToken, pos: int, proc endOperator(L: var TLexer, tok: var TToken, pos: int,
hash: THash) {.inline.} = hash: THash) {.inline.} =
var h = finishHash(hash) var h = !$hash
tok.ident = getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h) tok.ident = getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
if (tok.ident.id < oprLow) or (tok.ident.id > oprHigh): tok.tokType = tkOpr if (tok.ident.id < oprLow) or (tok.ident.id > oprHigh): tok.tokType = tkOpr
else: tok.tokType = TTokType(tok.ident.id - oprLow + ord(tkColon)) else: tok.tokType = TTokType(tok.ident.id - oprLow + ord(tkColon))
@ -580,7 +580,7 @@ proc getOperator(L: var TLexer, tok: var TToken) =
while true: while true:
var c = buf[pos] var c = buf[pos]
if c notin OpChars: break if c notin OpChars: break
h = concHash(h, Ord(c)) h = h !& Ord(c)
Inc(pos) Inc(pos)
endOperator(L, tok, pos, h) endOperator(L, tok, pos, h)
@ -678,7 +678,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
# '*:' is unfortunately a special case, because it is two tokens in # '*:' is unfortunately a special case, because it is two tokens in
# 'var v*: int'. # 'var v*: int'.
if L.buf[L.bufpos+1] == ':' and L.buf[L.bufpos+2] notin OpChars: if L.buf[L.bufpos+1] == ':' and L.buf[L.bufpos+2] notin OpChars:
var h = concHash(0, ord('*')) var h = 0 !& ord('*')
endOperator(L, tok, L.bufpos+1, h) endOperator(L, tok, L.bufpos+1, h)
else: else:
getOperator(L, tok) getOperator(L, tok)

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -10,7 +10,7 @@
# Built-in types and compilerprocs are registered here. # Built-in types and compilerprocs are registered here.
import import
ast, astalgo, nhashes, msgs, platform, nversion, times, idents, rodread ast, astalgo, hashes, msgs, platform, nversion, times, idents, rodread
var SystemModule*: PSym var SystemModule*: PSym
@ -69,7 +69,7 @@ proc getSysType(kind: TTypeKind): PType =
if result == nil: InternalError("type not found: " & $kind) if result == nil: InternalError("type not found: " & $kind)
proc getCompilerProc(name: string): PSym = proc getCompilerProc(name: string): PSym =
var ident = getIdent(name, getNormalizedHash(name)) var ident = getIdent(name, hashIgnoreStyle(name))
result = StrTableGet(compilerprocs, ident) result = StrTableGet(compilerprocs, ident)
if result == nil: if result == nil:
result = StrTableGet(rodCompilerProcs, ident) result = StrTableGet(rodCompilerProcs, ident)

View file

@ -1,138 +0,0 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
strutils
const
SmallestSize* = (1 shl 3) - 1
DefaultSize* = (1 shl 11) - 1
BiggestSize* = (1 shl 28) - 1
type
THash* = int
PHash* = ref THash
THashFunc* = proc (str: cstring): THash
proc concHash*(h: THash, val: int): THash {.inline.} =
result = h +% val
result = result +% result shl 10
result = result xor (result shr 6)
proc finishHash*(h: THash): THash {.inline.} =
result = h +% h shl 3
result = result xor (result shr 11)
result = result +% result shl 15
proc GetDataHash*(Data: Pointer, Size: int): THash =
var
h: THash
p: cstring
i, s: int
h = 0
p = cast[cstring](Data)
i = 0
s = size
while s > 0:
h = h +% ord(p[i])
h = h +% h shl 10
h = h xor (h shr 6)
Inc(i)
Dec(s)
h = h +% h shl 3
h = h xor (h shr 11)
h = h +% h shl 15
result = THash(h)
proc hashPtr*(p: Pointer): THash =
result = (cast[THash](p)) shr 3 # skip the alignment
proc GetHash*(str: cstring): THash =
var
h: THash
i: int
h = 0
i = 0
while str[i] != '\0':
h = h +% ord(str[i])
h = h +% h shl 10
h = h xor (h shr 6)
Inc(i)
h = h +% h shl 3
h = h xor (h shr 11)
h = h +% h shl 15
result = THash(h)
proc GetHashStr*(s: string): THash =
var h: THash
h = 0
for i in countup(1, len(s)):
h = h +% ord(s[i])
h = h +% h shl 10
h = h xor (h shr 6)
h = h +% h shl 3
h = h xor (h shr 11)
h = h +% h shl 15
result = THash(h)
proc getNormalizedHash*(s: string): THash =
var
h: THash
c: Char
h = 0
for i in countup(0, len(s) + 0 - 1):
c = s[i]
if c == '_':
continue # skip _
if c in {'A'..'Z'}:
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = h +% ord(c)
h = h +% h shl 10
h = h xor (h shr 6)
h = h +% h shl 3
h = h xor (h shr 11)
h = h +% h shl 15
result = THash(h)
proc GetHashStrCI*(s: string): THash =
var
h: THash
c: Char
h = 0
for i in countup(0, len(s) + 0 - 1):
c = s[i]
if c in {'A'..'Z'}:
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = h +% ord(c)
h = h +% h shl 10
h = h xor (h shr 6)
h = h +% h shl 3
h = h xor (h shr 11)
h = h +% h shl 15
result = THash(h)
proc GetHashCI*(str: cstring): THash =
var
h: THash
c: Char
i: int
h = 0
i = 0
while str[i] != '\0':
c = str[i]
if c in {'A'..'Z'}:
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = h +% ord(c)
h = h +% h shl 10
h = h xor (h shr 6)
Inc(i)
h = h +% h shl 3
h = h xor (h shr 11)
h = h +% h shl 15
result = THash(h)

View file

@ -1,171 +0,0 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2009 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# String tables.
import
os, nhashes, strutils
type
TStringTableMode* = enum
modeCaseSensitive, # the table is case sensitive
modeCaseInsensitive, # the table is case insensitive
modeStyleInsensitive # the table is style insensitive
TKeyValuePair* = tuple[key, val: string]
TKeyValuePairSeq* = seq[TKeyValuePair]
TStringTable* = object of TObject
counter*: int
data*: TKeyValuePairSeq
mode*: TStringTableMode
PStringTable* = ref TStringTable
proc newStringTable*(keyValuePairs: openarray[string],
mode: TStringTableMode = modeCaseSensitive): PStringTable
proc put*(t: PStringTable, key, val: string)
proc get*(t: PStringTable, key: string): string
proc hasKey*(t: PStringTable, key: string): bool
proc length*(t: PStringTable): int
type
TFormatFlag* = enum
useEnvironment, # use environment variable if the ``$key``
# is not found in the table
useEmpty, # use the empty string as a default, thus it
# won't throw an exception if ``$key`` is not
# in the table
useKey # do not replace ``$key`` if it is not found
# in the table (or in the environment)
TFormatFlags* = set[TFormatFlag]
proc `%`*(f: string, t: PStringTable, flags: TFormatFlags = {}): string
# implementation
const
growthFactor = 2
startSize = 64
proc newStringTable(keyValuePairs: openarray[string],
mode: TStringTableMode = modeCaseSensitive): PStringTable =
new(result)
result.mode = mode
result.counter = 0
newSeq(result.data, startSize)
var i = 0
while i < high(keyValuePairs):
put(result, keyValuePairs[i], keyValuePairs[i + 1])
inc(i, 2)
proc myhash(t: PStringTable, key: string): THash =
case t.mode
of modeCaseSensitive: result = nhashes.GetHashStr(key)
of modeCaseInsensitive: result = nhashes.GetHashStrCI(key)
of modeStyleInsensitive: result = nhashes.getNormalizedHash(key)
proc myCmp(t: PStringTable, a, b: string): bool =
case t.mode
of modeCaseSensitive: result = cmp(a, b) == 0
of modeCaseInsensitive: result = cmpIgnoreCase(a, b) == 0
of modeStyleInsensitive: result = cmpIgnoreStyle(a, b) == 0
proc mustRehash(length, counter: int): bool =
assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4)
proc length(t: PStringTable): int =
result = t.counter
proc nextTry(h, maxHash: THash): THash =
result = ((5 * h) + 1) and maxHash
# For any initial h in range(maxHash), repeating that maxHash times
# generates each int in range(maxHash) exactly once (see any text on
# random-number generation for proof).
proc RawGet(t: PStringTable, key: string): int =
var h = myhash(t, key) and high(t.data) # start with real hash value
while not isNil(t.data[h].key):
if mycmp(t, t.data[h].key, key):
return h
h = nextTry(h, high(t.data))
result = - 1
proc get(t: PStringTable, key: string): string =
var index = RawGet(t, key)
if index >= 0: result = t.data[index].val
else: result = ""
proc hasKey(t: PStringTable, key: string): bool =
result = rawGet(t, key) >= 0
proc RawInsert(t: PStringTable, data: var TKeyValuePairSeq, key, val: string) =
var h = myhash(t, key) and high(data)
while not isNil(data[h].key):
h = nextTry(h, high(data))
data[h].key = key
data[h].val = val
proc Enlarge(t: PStringTable) =
var n: TKeyValuePairSeq
newSeq(n, len(t.data) * growthFactor)
for i in countup(0, high(t.data)):
if not isNil(t.data[i].key): RawInsert(t, n, t.data[i].key, t.data[i].val)
swap(t.data, n)
proc Put(t: PStringTable, key, val: string) =
var index = RawGet(t, key)
if index >= 0:
t.data[index].val = val
else:
if mustRehash(len(t.data), t.counter): Enlarge(t)
RawInsert(t, t.data, key, val)
inc(t.counter)
proc RaiseFormatException(s: string) =
var e: ref EInvalidValue
new(e)
e.msg = "format string: key not found: " & s
raise e
proc getValue(t: PStringTable, flags: TFormatFlags, key: string): string =
if hasKey(t, key): return get(t, key)
if useEnvironment in flags: result = os.getEnv(key)
else: result = ""
if result.len == 0:
if useKey in flags: result = '$' & key
elif not (useEmpty in flags): raiseFormatException(key)
proc `%`(f: string, t: PStringTable, flags: TFormatFlags = {}): string =
const
PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'}
result = ""
var i = 0
while i <= len(f) + 0 - 1:
if f[i] == '$':
case f[i + 1]
of '$':
add(result, '$')
inc(i, 2)
of '{':
var j = i + 1
while (j <= len(f) + 0 - 1) and (f[j] != '}'): inc(j)
var key = substr(f, i + 2 + 0 - 1, j - 1 + 0 - 1)
add(result, getValue(t, flags, key))
i = j + 1
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_':
var j = i + 1
while (j <= len(f) + 0 - 1) and (f[j] in PatternChars): inc(j)
var key = substr(f, i + 1 + 0 - 1, j - 1 + 0 - 1)
add(result, getValue(t, flags, key))
i = j
else:
add(result, f[i])
inc(i)
else:
add(result, f[i])
inc(i)

View file

@ -8,7 +8,7 @@
# #
import import
os, lists, strutils, nstrtabs os, lists, strutils, strtabs
const const
hasTinyCBackend* = defined(tinyc) hasTinyCBackend* = defined(tinyc)
@ -117,10 +117,10 @@ proc existsConfigVar(key: string): bool =
result = hasKey(gConfigVars, key) result = hasKey(gConfigVars, key)
proc getConfigVar(key: string): string = proc getConfigVar(key: string): string =
result = nstrtabs.get(gConfigVars, key) result = gConfigVars[key]
proc setConfigVar(key, val: string) = proc setConfigVar(key, val: string) =
nstrtabs.put(gConfigVars, key, val) gConfigVars[key] = val
proc getOutFile*(filename, ext: string): string = proc getOutFile*(filename, ext: string): string =
if options.outFile != "": result = options.outFile if options.outFile != "": result = options.outFile
@ -204,4 +204,4 @@ proc binaryStrSearch(x: openarray[string], y: string): int =
return mid return mid
result = - 1 result = - 1
gConfigVars = newStringTable([], modeStyleInsensitive) gConfigVars = newStringTable(modeStyleInsensitive)

View file

@ -59,7 +59,7 @@
# #
import import
msgs, strutils, platform, nhashes, crc msgs, strutils, platform, hashes, crc
const const
CacheLeafs* = true CacheLeafs* = true

View file

@ -11,7 +11,7 @@
# subset is provided. # subset is provided.
import import
os, msgs, strutils, platform, nhashes, ropes, options os, msgs, strutils, platform, hashes, ropes, options
type type
TRstNodeKind* = enum TRstNodeKind* = enum

View file

@ -10,7 +10,7 @@
# This module implements the semantic checking pass. # This module implements the semantic checking pass.
import import
strutils, nhashes, lists, options, lexer, ast, astalgo, trees, treetab, strutils, hashes, lists, options, lexer, ast, astalgo, trees, treetab,
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math, wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
magicsys, parser, nversion, nimsets, semdata, evals, semfold, importer, magicsys, parser, nversion, nimsets, semdata, evals, semfold, importer,
procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest

View file

@ -10,7 +10,7 @@
# Implements a table from trees to trees. Does structural equavilent checking. # Implements a table from trees to trees. Does structural equavilent checking.
import import
nhashes, ast, astalgo, types hashes, ast, astalgo, types
proc hashTree(n: PNode): THash = proc hashTree(n: PNode): THash =
if n == nil: return if n == nil: return
@ -19,20 +19,20 @@ proc hashTree(n: PNode): THash =
of nkEmpty, nkNilLit, nkType: of nkEmpty, nkNilLit, nkType:
nil nil
of nkIdent: of nkIdent:
result = concHash(result, n.ident.h) result = result !& n.ident.h
of nkSym: of nkSym:
result = concHash(result, n.sym.name.h) result = result !& n.sym.name.h
of nkCharLit..nkInt64Lit: of nkCharLit..nkInt64Lit:
if (n.intVal >= low(int)) and (n.intVal <= high(int)): if (n.intVal >= low(int)) and (n.intVal <= high(int)):
result = concHash(result, int(n.intVal)) result = result !& int(n.intVal)
of nkFloatLit..nkFloat64Lit: of nkFloatLit..nkFloat64Lit:
if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0): if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0):
result = concHash(result, toInt(n.floatVal)) result = result !& toInt(n.floatVal)
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
result = concHash(result, GetHashStr(n.strVal)) result = result !& hash(n.strVal)
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
result = concHash(result, hashTree(n.sons[i])) result = result !& hashTree(n.sons[i])
proc TreesEquivalent(a, b: PNode): bool = proc TreesEquivalent(a, b: PNode): bool =
if a == b: if a == b:

View file

@ -14,7 +14,7 @@
# be slow and unreadable. # be slow and unreadable.
import import
nhashes, strutils, idents hashes, strutils, idents
# Keywords must be kept sorted and within a range # Keywords must be kept sorted and within a range
@ -124,6 +124,6 @@ proc whichKeyword*(id: String): TSpecialWord =
proc initSpecials() = proc initSpecials() =
# initialize the keywords: # initialize the keywords:
for s in countup(succ(low(specialWords)), high(specialWords)): for s in countup(succ(low(specialWords)), high(specialWords)):
getIdent(specialWords[s], getNormalizedHash(specialWords[s])).id = ord(s) getIdent(specialWords[s], hashIgnoreStyle(specialWords[s])).id = ord(s)
initSpecials() initSpecials()

View file

@ -18,12 +18,16 @@ type
## always have a size of a power of two and can use the ``and`` ## always have a size of a power of two and can use the ``and``
## operator instead of ``mod`` for truncation of the hash value. ## operator instead of ``mod`` for truncation of the hash value.
proc concHash(h: THash, val: int): THash {.inline.} = proc `!&`*(h: THash, val: int): THash {.inline.} =
## mixes a hash value `h` with `val` to produce a new hash value. This is
## only needed if you need to implement a hash proc for a new datatype.
result = h +% val result = h +% val
result = result +% result shl 10 result = result +% result shl 10
result = result xor (result shr 6) result = result xor (result shr 6)
proc finishHash(h: THash): THash {.inline.} = proc `!$`*(h: THash): THash {.inline.} =
## finishes the computation of the hash value. This is
## only needed if you need to implement a hash proc for a new datatype.
result = h +% h shl 3 result = h +% h shl 3
result = result xor (result shr 11) result = result xor (result shr 11)
result = result +% result shl 15 result = result +% result shl 15
@ -35,10 +39,10 @@ proc hashData*(Data: Pointer, Size: int): THash =
var i = 0 var i = 0
var s = size var s = size
while s > 0: while s > 0:
h = concHash(h, ord(p[i])) h = h !& ord(p[i])
Inc(i) Inc(i)
Dec(s) Dec(s)
result = finishHash(h) result = !$h
proc hash*(x: Pointer): THash {.inline.} = proc hash*(x: Pointer): THash {.inline.} =
## efficient hashing of pointers ## efficient hashing of pointers
@ -60,8 +64,8 @@ proc hash*(x: string): THash =
## efficient hashing of strings ## efficient hashing of strings
var h: THash = 0 var h: THash = 0
for i in 0..x.len-1: for i in 0..x.len-1:
h = concHash(h, ord(x[i])) h = h !& ord(x[i])
result = finishHash(h) result = !$h
proc hashIgnoreStyle*(x: string): THash = proc hashIgnoreStyle*(x: string): THash =
## efficient hashing of strings; style is ignored ## efficient hashing of strings; style is ignored
@ -72,8 +76,8 @@ proc hashIgnoreStyle*(x: string): THash =
continue # skip _ continue # skip _
if c in {'A'..'Z'}: if c in {'A'..'Z'}:
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower() c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = concHash(h, ord(c)) h = h !& ord(c)
result = finishHash(h) result = !$h
proc hashIgnoreCase*(x: string): THash = proc hashIgnoreCase*(x: string): THash =
## efficient hashing of strings; case is ignored ## efficient hashing of strings; case is ignored
@ -82,12 +86,12 @@ proc hashIgnoreCase*(x: string): THash =
var c = x[i] var c = x[i]
if c in {'A'..'Z'}: if c in {'A'..'Z'}:
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower() c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = concHash(h, ord(c)) h = h !& ord(c)
result = finishHash(h) result = !$h
proc hash*[T: tuple](x: T): THash = proc hash*[T: tuple](x: T): THash =
## efficient hashing of tuples. ## efficient hashing of tuples.
for f in fields(x): for f in fields(x):
result = concHash(result, hash(f)) result = result !& hash(f)
result = finishHash(result) result = !$result