diff options
Diffstat (limited to 'rod/astalgo.nim')
-rw-r--r-- | rod/astalgo.nim | 831 |
1 files changed, 0 insertions, 831 deletions
diff --git a/rod/astalgo.nim b/rod/astalgo.nim deleted file mode 100644 index 1b4572b2b..000000000 --- a/rod/astalgo.nim +++ /dev/null @@ -1,831 +0,0 @@ -# -# -# The Nimrod Compiler -# (c) Copyright 2009 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -# Algorithms for the abstract syntax tree: hash tables, lists -# and sets of nodes are supported. Efficiency is important as -# the data structures here are used in various places of the compiler. - -import - ast, nhashes, strutils, options, msgs, ropes, idents - -proc hashNode*(p: PObject): THash -proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope - # Convert a tree into its YAML representation; this is used by the - # YAML code generator and it is invaluable for debugging purposes. - # If maxRecDepht <> -1 then it won't print the whole graph. -proc typeToYaml*(n: PType, indent: int = 0, maxRecDepth: int = - 1): PRope -proc symToYaml*(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope -proc lineInfoToStr*(info: TLineInfo): PRope - -# ----------------------- node sets: --------------------------------------- -proc ObjectSetContains*(t: TObjectSet, obj: PObject): bool - # returns true whether n is in t -proc ObjectSetIncl*(t: var TObjectSet, obj: PObject) - # include an element n in the table t -proc ObjectSetContainsOrIncl*(t: var TObjectSet, obj: PObject): bool - # more are not needed ... - -# ----------------------- (key, val)-Hashtables ---------------------------- -proc TablePut*(t: var TTable, key, val: PObject) -proc TableGet*(t: TTable, key: PObject): PObject -type - TCmpProc* = proc (key, closure: PObject): bool # should return true if found - -proc TableSearch*(t: TTable, key, closure: PObject, comparator: TCmpProc): PObject - # return val as soon as comparator returns true; if this never happens, - # nil is returned - -# ----------------------- str table ----------------------------------------- -proc StrTableContains*(t: TStrTable, n: PSym): bool -proc StrTableAdd*(t: var TStrTable, n: PSym) -proc StrTableGet*(t: TStrTable, name: PIdent): PSym -proc StrTableIncl*(t: var TStrTable, n: PSym): bool - # returns true if n is already in the string table - # the iterator scheme: -type - TTabIter*{.final.} = object # consider all fields here private - h*: THash # current hash - - -proc InitTabIter*(ti: var TTabIter, tab: TStrTable): PSym -proc NextIter*(ti: var TTabIter, tab: TStrTable): PSym - # usage: - # var i: TTabIter; s: PSym; - # s := InitTabIter(i, table); - # while s <> nil do begin - # ... - # s := NextIter(i, table); - # end; -type - TIdentIter*{.final.} = object # iterator over all syms with the same identifier - h*: THash # current hash - name*: PIdent - - -proc InitIdentIter*(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym -proc NextIdentIter*(ti: var TIdentIter, tab: TStrTable): PSym - -# -------------- symbol table ---------------------------------------------- -# Each TParser object (which represents a module being compiled) has its own -# symbol table. A symbol table is organized as a stack of str tables. The -# stack represents the different scopes. -# Stack pointer: -# 0 imported symbols from other modules -# 1 module level -# 2 proc level -# 3 nested statements -# ... -# -type - TSymTab*{.final.} = object - tos*: Natural # top of stack - stack*: seq[TStrTable] - - -proc InitSymTab*(tab: var TSymTab) -proc DeinitSymTab*(tab: var TSymTab) -proc SymTabGet*(tab: TSymTab, s: PIdent): PSym -proc SymTabLocalGet*(tab: TSymTab, s: PIdent): PSym -proc SymTabAdd*(tab: var TSymTab, e: PSym) -proc SymTabAddAt*(tab: var TSymTab, e: PSym, at: Natural) -proc SymTabAddUnique*(tab: var TSymTab, e: PSym): TResult -proc SymTabAddUniqueAt*(tab: var TSymTab, e: PSym, at: Natural): TResult -proc OpenScope*(tab: var TSymTab) -proc RawCloseScope*(tab: var TSymTab) - # the real "closeScope" adds some - # checks in parsobj - # these are for debugging only: -proc debug*(n: PSym) -proc debug*(n: PType) -proc debug*(n: PNode) - -# --------------------------- ident tables ---------------------------------- -proc IdTableGet*(t: TIdTable, key: PIdObj): PObject -proc IdTableGet*(t: TIdTable, key: int): PObject -proc IdTablePut*(t: var TIdTable, key: PIdObj, val: PObject) -proc IdTableHasObjectAsKey*(t: TIdTable, key: PIdObj): bool - # checks if `t` contains the `key` (compared by the pointer value, not only - # `key`'s id) -proc IdNodeTableGet*(t: TIdNodeTable, key: PIdObj): PNode -proc IdNodeTablePut*(t: var TIdNodeTable, key: PIdObj, val: PNode) -proc writeIdNodeTable*(t: TIdNodeTable) - -# --------------------------------------------------------------------------- - -proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym -proc lookupInRecord*(n: PNode, field: PIdent): PSym -proc getModule*(s: PSym): PSym -proc mustRehash*(length, counter: int): bool -proc nextTry*(h, maxHash: THash): THash - -# ------------- table[int, int] --------------------------------------------- -const - InvalidKey* = low(int) - -type - TIIPair*{.final.} = object - key*, val*: int - - TIIPairSeq* = seq[TIIPair] - TIITable*{.final.} = object # table[int, int] - counter*: int - data*: TIIPairSeq - - -proc initIITable*(x: var TIITable) -proc IITableGet*(t: TIITable, key: int): int -proc IITablePut*(t: var TIITable, key, val: int) - -# implementation - -proc lookupInRecord(n: PNode, field: PIdent): PSym = - result = nil - case n.kind - of nkRecList: - for i in countup(0, sonsLen(n) - 1): - result = lookupInRecord(n.sons[i], field) - if result != nil: return - of nkRecCase: - if (n.sons[0].kind != nkSym): InternalError(n.info, "lookupInRecord") - result = lookupInRecord(n.sons[0], field) - if result != nil: return - for i in countup(1, sonsLen(n) - 1): - case n.sons[i].kind - of nkOfBranch, nkElse: - result = lookupInRecord(lastSon(n.sons[i]), field) - if result != nil: return - else: internalError(n.info, "lookupInRecord(record case branch)") - of nkSym: - if n.sym.name.id == field.id: result = n.sym - else: internalError(n.info, "lookupInRecord()") - -proc getModule(s: PSym): PSym = - result = s - assert((result.kind == skModule) or (result.owner != result)) - while (result != nil) and (result.kind != skModule): result = result.owner - -proc getSymFromList(list: PNode, ident: PIdent, start: int = 0): PSym = - for i in countup(start, sonsLen(list) - 1): - if list.sons[i].kind != nkSym: InternalError(list.info, "getSymFromList") - result = list.sons[i].sym - if result.name.id == ident.id: return - result = nil - -proc hashNode(p: PObject): THash = - result = hashPtr(cast[pointer](p)) - -proc mustRehash(length, counter: int): bool = - assert(length > counter) - result = (length * 2 < counter * 3) or (length - counter < 4) - -proc spaces(x: int): PRope = - # returns x spaces - result = toRope(repeatChar(x)) - -proc toYamlChar(c: Char): string = - case c - of '\0'..'\x1F', '\x80'..'\xFF': result = "\\u" & strutils.toHex(ord(c), 4) - of '\'', '\"', '\\': result = '\\' & c - else: result = c & "" - -proc makeYamlString(s: string): PRope = - # We have to split long strings into many ropes. Otherwise - # this could trigger InternalError(111). See the ropes module for - # further information. - const - MaxLineLength = 64 - var res: string - result = nil - res = "\"" - for i in countup(0, len(s) + 0 - 1): - if (i - 0 + 1) mod MaxLineLength == 0: - add(res, '\"') - add(res, "\n") - app(result, toRope(res)) - res = "\"" # reset - add(res, toYamlChar(s[i])) - add(res, '\"') - app(result, toRope(res)) - -proc flagsToStr[T](flags: set[T]): PRope = - if flags == {}: - result = toRope("[]") - else: - result = nil - for x in items(flags): - if result != nil: app(result, ", ") - app(result, makeYamlString($x)) - result = con("[", con(result, "]")) - -proc lineInfoToStr(info: TLineInfo): PRope = - result = ropef("[$1, $2, $3]", [makeYamlString(toFilename(info)), - toRope(toLinenumber(info)), - toRope(toColumn(info))]) - -proc treeToYamlAux(n: PNode, marker: var TIntSet, indent, maxRecDepth: int): PRope -proc symToYamlAux(n: PSym, marker: var TIntSet, indent, maxRecDepth: int): PRope -proc typeToYamlAux(n: PType, marker: var TIntSet, indent, maxRecDepth: int): PRope -proc strTableToYaml(n: TStrTable, marker: var TIntSet, indent: int, - maxRecDepth: int): PRope = - var - istr: PRope - mycount: int - istr = spaces(indent + 2) - result = toRope("[") - mycount = 0 - for i in countup(0, high(n.data)): - if n.data[i] != nil: - if mycount > 0: app(result, ",") - appf(result, "$n$1$2", - [istr, symToYamlAux(n.data[i], marker, indent + 2, maxRecDepth - 1)]) - inc(mycount) - if mycount > 0: appf(result, "$n$1", [spaces(indent)]) - app(result, "]") - assert(mycount == n.counter) - -proc ropeConstr(indent: int, c: openarray[PRope]): PRope = - # array of (name, value) pairs - var - istr: PRope - i: int - istr = spaces(indent + 2) - result = toRope("{") - i = 0 - while i <= high(c): - if i > 0: app(result, ",") - appf(result, "$n$1\"$2\": $3", [istr, c[i], c[i + 1]]) - inc(i, 2) - appf(result, "$n$1}", [spaces(indent)]) - -proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int, - maxRecDepth: int): PRope = - if n == nil: - result = toRope("null") - elif IntSetContainsOrIncl(marker, n.id): - result = ropef("\"$1 @$2\"", [toRope(n.name.s), toRope( - strutils.toHex(cast[TAddress](n), sizeof(n) * 2))]) - else: - var ast = treeToYamlAux(n.ast, marker, indent + 2, maxRecDepth - 1) - result = ropeConstr(indent, [toRope("kind"), - makeYamlString($n.kind), - toRope("name"), makeYamlString(n.name.s), - toRope("typ"), typeToYamlAux(n.typ, marker, - indent + 2, maxRecDepth - 1), - toRope("info"), lineInfoToStr(n.info), - toRope("flags"), flagsToStr(n.flags), - toRope("magic"), makeYamlString($n.magic), - toRope("ast"), ast, toRope("options"), - flagsToStr(n.options), toRope("position"), - toRope(n.position)]) - -proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int, maxRecDepth: int): PRope = - if n == nil: - result = toRope("null") - elif intSetContainsOrIncl(marker, n.id): - result = ropef("\"$1 @$2\"", [toRope($n.kind), toRope( - strutils.toHex(cast[TAddress](n), sizeof(n) * 2))]) - else: - if sonsLen(n) > 0: - result = toRope("[") - for i in countup(0, sonsLen(n) - 1): - if i > 0: app(result, ",") - appf(result, "$n$1$2", [spaces(indent + 4), typeToYamlAux(n.sons[i], - marker, indent + 4, maxRecDepth - 1)]) - appf(result, "$n$1]", [spaces(indent + 2)]) - else: - result = toRope("null") - result = ropeConstr(indent, [toRope("kind"), - makeYamlString($n.kind), - toRope("sym"), symToYamlAux(n.sym, marker, - indent + 2, maxRecDepth - 1), toRope("n"), treeToYamlAux(n.n, marker, - indent + 2, maxRecDepth - 1), toRope("flags"), FlagsToStr(n.flags), - toRope("callconv"), - makeYamlString(CallingConvToStr[n.callConv]), - toRope("size"), toRope(n.size), - toRope("align"), toRope(n.align), - toRope("sons"), result]) - -proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int, - maxRecDepth: int): PRope = - var istr: PRope - if n == nil: - result = toRope("null") - else: - istr = spaces(indent + 2) - result = ropef("{$n$1\"kind\": $2", - [istr, makeYamlString($n.kind)]) - if maxRecDepth != 0: - appf(result, ",$n$1\"info\": $2", [istr, lineInfoToStr(n.info)]) - case n.kind - of nkCharLit..nkInt64Lit: - appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)]) - of nkFloatLit, nkFloat32Lit, nkFloat64Lit: - appf(result, ",$n$1\"floatVal\": $2", [istr, toRopeF(n.floatVal)]) - of nkStrLit..nkTripleStrLit: - appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)]) - of nkSym: - appf(result, ",$n$1\"sym\": $2", - [istr, symToYamlAux(n.sym, marker, indent + 2, maxRecDepth)]) - of nkIdent: - if n.ident != nil: - appf(result, ",$n$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) - else: - appf(result, ",$n$1\"ident\": null", [istr]) - else: - if sonsLen(n) > 0: - appf(result, ",$n$1\"sons\": [", [istr]) - for i in countup(0, sonsLen(n) - 1): - if i > 0: app(result, ",") - appf(result, "$n$1$2", [spaces(indent + 4), treeToYamlAux(n.sons[i], - marker, indent + 4, maxRecDepth - 1)]) - appf(result, "$n$1]", [istr]) - appf(result, ",$n$1\"typ\": $2", - [istr, typeToYamlAux(n.typ, marker, indent + 2, maxRecDepth)]) - appf(result, "$n$1}", [spaces(indent)]) - -proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope = - var marker: TIntSet - IntSetInit(marker) - result = treeToYamlAux(n, marker, indent, maxRecDepth) - -proc typeToYaml(n: PType, indent: int = 0, maxRecDepth: int = - 1): PRope = - var marker: TIntSet - IntSetInit(marker) - result = typeToYamlAux(n, marker, indent, maxRecDepth) - -proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope = - var marker: TIntSet - IntSetInit(marker) - result = symToYamlAux(n, marker, indent, maxRecDepth) - -proc debugType(n: PType): PRope = - if n == nil: - result = toRope("null") - else: - result = toRope($n.kind) - if n.sym != nil: - app(result, " ") - app(result, n.sym.name.s) - if (n.kind != tyString) and (sonsLen(n) > 0): - app(result, "(") - for i in countup(0, sonsLen(n) - 1): - if i > 0: app(result, ", ") - if n.sons[i] == nil: - app(result, "null") - else: - app(result, debugType(n.sons[i])) - app(result, ")") - -proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = - var istr: PRope - if n == nil: - result = toRope("null") - else: - istr = spaces(indent + 2) - result = ropef("{$n$1\"kind\": $2", - [istr, makeYamlString($n.kind)]) - if maxRecDepth != 0: - case n.kind - of nkCharLit..nkInt64Lit: - appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)]) - of nkFloatLit, nkFloat32Lit, nkFloat64Lit: - appf(result, ",$n$1\"floatVal\": $2", [istr, toRopeF(n.floatVal)]) - of nkStrLit..nkTripleStrLit: - appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)]) - of nkSym: - appf(result, ",$n$1\"sym\": $2_$3", - [istr, toRope(n.sym.name.s), toRope(n.sym.id)]) - of nkIdent: - if n.ident != nil: - appf(result, ",$n$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) - else: - appf(result, ",$n$1\"ident\": null", [istr]) - else: - if sonsLen(n) > 0: - appf(result, ",$n$1\"sons\": [", [istr]) - for i in countup(0, sonsLen(n) - 1): - if i > 0: app(result, ",") - appf(result, "$n$1$2", [spaces(indent + 4), debugTree(n.sons[i], - indent + 4, maxRecDepth - 1)]) - appf(result, "$n$1]", [istr]) - appf(result, "$n$1}", [spaces(indent)]) - -proc debug(n: PSym) = - writeln(stdout, ropeToStr(ropef("$1_$2", [toRope(n.name.s), toRope(n.id)]))) - -proc debug(n: PType) = - writeln(stdout, ropeToStr(debugType(n))) - -proc debug(n: PNode) = - writeln(stdout, ropeToStr(debugTree(n, 0, 100))) - -const - EmptySeq = @ [] - -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 objectSetContains(t: TObjectSet, obj: PObject): bool = - # returns true whether n is in t - var h: THash - h = hashNode(obj) and high(t.data) # start with real hash value - while t.data[h] != nil: - if (t.data[h] == obj): - return true - h = nextTry(h, high(t.data)) - result = false - -proc objectSetRawInsert(data: var TObjectSeq, obj: PObject) = - var h: THash - h = HashNode(obj) and high(data) - while data[h] != nil: - assert(data[h] != obj) - h = nextTry(h, high(data)) - assert(data[h] == nil) - data[h] = obj - -proc objectSetEnlarge(t: var TObjectSet) = - var n: TObjectSeq - newSeq(n, len(t.data) * growthFactor) - for i in countup(0, high(t.data)): - if t.data[i] != nil: objectSetRawInsert(n, t.data[i]) - swap(t.data, n) - -proc objectSetIncl(t: var TObjectSet, obj: PObject) = - if mustRehash(len(t.data), t.counter): objectSetEnlarge(t) - objectSetRawInsert(t.data, obj) - inc(t.counter) - -proc objectSetContainsOrIncl(t: var TObjectSet, obj: PObject): bool = - # returns true if obj is already in the string table: - var - h: THash - it: PObject - h = HashNode(obj) and high(t.data) - while true: - it = t.data[h] - if it == nil: break - if it == obj: - return true # found it - h = nextTry(h, high(t.data)) - if mustRehash(len(t.data), t.counter): - objectSetEnlarge(t) - objectSetRawInsert(t.data, obj) - else: - assert(t.data[h] == nil) - t.data[h] = obj - inc(t.counter) - result = false - -proc TableRawGet(t: TTable, key: PObject): int = - var h: THash - h = hashNode(key) and high(t.data) # start with real hash value - while t.data[h].key != nil: - if (t.data[h].key == key): - return h - h = nextTry(h, high(t.data)) - result = - 1 - -proc TableSearch(t: TTable, key, closure: PObject, comparator: TCmpProc): PObject = - var h: THash - h = hashNode(key) and high(t.data) # start with real hash value - while t.data[h].key != nil: - if (t.data[h].key == key): - if comparator(t.data[h].val, closure): - # BUGFIX 1 - return t.data[h].val - h = nextTry(h, high(t.data)) - result = nil - -proc TableGet(t: TTable, key: PObject): PObject = - var index: int - index = TableRawGet(t, key) - if index >= 0: result = t.data[index].val - else: result = nil - -proc TableRawInsert(data: var TPairSeq, key, val: PObject) = - var h: THash - h = HashNode(key) and high(data) - while data[h].key != nil: - assert(data[h].key != key) - h = nextTry(h, high(data)) - assert(data[h].key == nil) - data[h].key = key - data[h].val = val - -proc TableEnlarge(t: var TTable) = - var n: TPairSeq - newSeq(n, len(t.data) * growthFactor) - for i in countup(0, high(t.data)): - if t.data[i].key != nil: TableRawInsert(n, t.data[i].key, t.data[i].val) - swap(t.data, n) - -proc TablePut(t: var TTable, key, val: PObject) = - var index: int - index = TableRawGet(t, key) - if index >= 0: - t.data[index].val = val - else: - if mustRehash(len(t.data), t.counter): TableEnlarge(t) - TableRawInsert(t.data, key, val) - inc(t.counter) - -proc StrTableContains(t: TStrTable, n: PSym): bool = - var h: THash - h = n.name.h and high(t.data) # start with real hash value - while t.data[h] != nil: - if (t.data[h] == n): - return true - h = nextTry(h, high(t.data)) - result = false - -proc StrTableRawInsert(data: var TSymSeq, n: PSym) = - var h: THash - h = n.name.h and high(data) - while data[h] != nil: - if data[h] == n: InternalError(n.info, "StrTableRawInsert: " & n.name.s) - h = nextTry(h, high(data)) - assert(data[h] == nil) - data[h] = n - -proc StrTableEnlarge(t: var TStrTable) = - var n: TSymSeq - newSeq(n, len(t.data) * growthFactor) - for i in countup(0, high(t.data)): - if t.data[i] != nil: StrTableRawInsert(n, t.data[i]) - swap(t.data, n) - -proc StrTableAdd(t: var TStrTable, n: PSym) = - if mustRehash(len(t.data), t.counter): StrTableEnlarge(t) - StrTableRawInsert(t.data, n) - inc(t.counter) - -proc StrTableIncl(t: var TStrTable, n: PSym): bool = - # returns true if n is already in the string table: - var - h: THash - it: PSym - h = n.name.h and high(t.data) - while true: - it = t.data[h] - if it == nil: break - if it.name.id == n.name.id: - return true # found it - h = nextTry(h, high(t.data)) - if mustRehash(len(t.data), t.counter): - StrTableEnlarge(t) - StrTableRawInsert(t.data, n) - else: - assert(t.data[h] == nil) - t.data[h] = n - inc(t.counter) - result = false - -proc StrTableGet(t: TStrTable, name: PIdent): PSym = - var h: THash - h = name.h and high(t.data) - while true: - result = t.data[h] - if result == nil: break - if result.name.id == name.id: break - h = nextTry(h, high(t.data)) - -proc InitIdentIter(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym = - ti.h = s.h - ti.name = s - if tab.Counter == 0: result = nil - else: result = NextIdentIter(ti, tab) - -proc NextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym = - var h, start: THash - h = ti.h and high(tab.data) - start = h - result = tab.data[h] - while (result != nil): - if result.Name.id == ti.name.id: break - h = nextTry(h, high(tab.data)) - if h == start: - result = nil - break - result = tab.data[h] - ti.h = nextTry(h, high(tab.data)) - -proc InitTabIter(ti: var TTabIter, tab: TStrTable): PSym = - ti.h = 0 # we start by zero ... - if tab.counter == 0: - result = nil # FIX 1: removed endless loop - else: - result = NextIter(ti, tab) - -proc NextIter(ti: var TTabIter, tab: TStrTable): PSym = - result = nil - while (ti.h <= high(tab.data)): - result = tab.data[ti.h] - Inc(ti.h) # ... and increment by one always - if result != nil: break - -proc InitSymTab(tab: var TSymTab) = - tab.tos = 0 - tab.stack = EmptySeq - -proc DeinitSymTab(tab: var TSymTab) = - tab.stack = nil - -proc SymTabLocalGet(tab: TSymTab, s: PIdent): PSym = - result = StrTableGet(tab.stack[tab.tos - 1], s) - -proc SymTabGet(tab: TSymTab, s: PIdent): PSym = - for i in countdown(tab.tos - 1, 0): - result = StrTableGet(tab.stack[i], s) - if result != nil: return - result = nil - -proc SymTabAddAt(tab: var TSymTab, e: PSym, at: Natural) = - StrTableAdd(tab.stack[at], e) - -proc SymTabAdd(tab: var TSymTab, e: PSym) = - StrTableAdd(tab.stack[tab.tos - 1], e) - -proc SymTabAddUniqueAt(tab: var TSymTab, e: PSym, at: Natural): TResult = - if StrTableGet(tab.stack[at], e.name) != nil: - result = Failure - else: - StrTableAdd(tab.stack[at], e) - result = Success - -proc SymTabAddUnique(tab: var TSymTab, e: PSym): TResult = - result = SymTabAddUniqueAt(tab, e, tab.tos - 1) - -proc OpenScope(tab: var TSymTab) = - if tab.tos >= len(tab.stack): setlen(tab.stack, tab.tos + 1) - initStrTable(tab.stack[tab.tos]) - Inc(tab.tos) - -proc RawCloseScope(tab: var TSymTab) = - Dec(tab.tos) #tab.stack[tab.tos] := nil; - -proc hasEmptySlot(data: TIdPairSeq): bool = - for h in countup(0, high(data)): - if data[h].key == nil: - return true - result = false - -proc IdTableRawGet(t: TIdTable, key: int): int = - var h: THash - h = key and high(t.data) # start with real hash value - while t.data[h].key != nil: - if (t.data[h].key.id == key): - return h - h = nextTry(h, high(t.data)) - result = - 1 - -proc IdTableHasObjectAsKey(t: TIdTable, key: PIdObj): bool = - var index: int - index = IdTableRawGet(t, key.id) - if index >= 0: result = t.data[index].key == key - else: result = false - -proc IdTableGet(t: TIdTable, key: PIdObj): PObject = - var index: int - index = IdTableRawGet(t, key.id) - if index >= 0: result = t.data[index].val - else: result = nil - -proc IdTableGet(t: TIdTable, key: int): PObject = - var index: int - index = IdTableRawGet(t, key) - if index >= 0: result = t.data[index].val - else: result = nil - -proc IdTableRawInsert(data: var TIdPairSeq, key: PIdObj, val: PObject) = - var h: THash - h = key.id and high(data) - while data[h].key != nil: - assert(data[h].key.id != key.id) - h = nextTry(h, high(data)) - assert(data[h].key == nil) - data[h].key = key - data[h].val = val - -proc IdTablePut(t: var TIdTable, key: PIdObj, val: PObject) = - var - index: int - n: TIdPairSeq - index = IdTableRawGet(t, key.id) - if index >= 0: - assert(t.data[index].key != nil) - t.data[index].val = val - else: - if mustRehash(len(t.data), t.counter): - newSeq(n, len(t.data) * growthFactor) - for i in countup(0, high(t.data)): - if t.data[i].key != nil: - IdTableRawInsert(n, t.data[i].key, t.data[i].val) - assert(hasEmptySlot(n)) - swap(t.data, n) - IdTableRawInsert(t.data, key, val) - inc(t.counter) - -proc writeIdNodeTable(t: TIdNodeTable) = - var h: THash - nil - -proc IdNodeTableRawGet(t: TIdNodeTable, key: PIdObj): int = - var h: THash - h = key.id and high(t.data) # start with real hash value - while t.data[h].key != nil: - if (t.data[h].key.id == key.id): - return h - h = nextTry(h, high(t.data)) - result = - 1 - -proc IdNodeTableGet(t: TIdNodeTable, key: PIdObj): PNode = - var index: int - index = IdNodeTableRawGet(t, key) - if index >= 0: result = t.data[index].val - else: result = nil - -proc IdNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) = - var h: THash - h = key.id and high(data) - while data[h].key != nil: - assert(data[h].key.id != key.id) - h = nextTry(h, high(data)) - assert(data[h].key == nil) - data[h].key = key - data[h].val = val - -proc IdNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) = - var - index: int - n: TIdNodePairSeq - index = IdNodeTableRawGet(t, key) - if index >= 0: - assert(t.data[index].key != nil) - t.data[index].val = val - else: - if mustRehash(len(t.data), t.counter): - newSeq(n, len(t.data) * growthFactor) - for i in countup(0, high(t.data)): - if t.data[i].key != nil: - IdNodeTableRawInsert(n, t.data[i].key, t.data[i].val) - swap(t.data, n) - IdNodeTableRawInsert(t.data, key, val) - inc(t.counter) - -proc initIITable(x: var TIITable) = - x.counter = 0 - newSeq(x.data, startSize) - for i in countup(0, startSize - 1): x.data[i].key = InvalidKey - -proc IITableRawGet(t: TIITable, key: int): int = - var h: THash - h = key and high(t.data) # start with real hash value - while t.data[h].key != InvalidKey: - if (t.data[h].key == key): - return h - h = nextTry(h, high(t.data)) - result = - 1 - -proc IITableGet(t: TIITable, key: int): int = - var index: int - index = IITableRawGet(t, key) - if index >= 0: result = t.data[index].val - else: result = InvalidKey - -proc IITableRawInsert(data: var TIIPairSeq, key, val: int) = - var h: THash - h = key and high(data) - while data[h].key != InvalidKey: - assert(data[h].key != key) - h = nextTry(h, high(data)) - assert(data[h].key == InvalidKey) - data[h].key = key - data[h].val = val - -proc IITablePut(t: var TIITable, key, val: int) = - var - index: int - n: TIIPairSeq - index = IITableRawGet(t, key) - if index >= 0: - assert(t.data[index].key != InvalidKey) - t.data[index].val = val - else: - if mustRehash(len(t.data), t.counter): - newSeq(n, len(t.data) * growthFactor) - for i in countup(0, high(n)): n[i].key = InvalidKey - for i in countup(0, high(t.data)): - if t.data[i].key != InvalidKey: - IITableRawInsert(n, t.data[i].key, t.data[i].val) - swap(t.data, n) - IITableRawInsert(t.data, key, val) - inc(t.counter) |