summary refs log tree commit diff stats
path: root/nim/astalgo.pas
diff options
context:
space:
mode:
Diffstat (limited to 'nim/astalgo.pas')
-rwxr-xr-xnim/astalgo.pas1294
1 files changed, 0 insertions, 1294 deletions
diff --git a/nim/astalgo.pas b/nim/astalgo.pas
deleted file mode 100755
index 7c1f3ec0b..000000000
--- a/nim/astalgo.pas
+++ /dev/null
@@ -1,1294 +0,0 @@
-//
-//
-//           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
-//
-//    See the file "copying.txt", included in this
-//    distribution, for details about the copyright.
-//
-unit astalgo;
-
-// 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 the whole compiler.
-
-interface
-
-{$include 'config.inc'}
-
-uses
-  nsystem, ast, nhashes, charsets, strutils, options, msgs, ropes, idents;
-
-function hashNode(p: PObject): THash;
-
-function 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.
-
-function typeToYaml(n: PType; indent: int = 0; maxRecDepth: int = -1): PRope;
-function symToYaml(n: PSym; indent: int = 0; maxRecDepth: int = -1): PRope;
-function optionsToStr(flags: TOptions): PRope;
-function lineInfoToStr(const info: TLineInfo): PRope;
-
-// ----------------------- node sets: ---------------------------------------
-
-function ObjectSetContains(const t: TObjectSet; obj: PObject): Boolean;
-// returns true whether n is in t
-
-procedure ObjectSetIncl(var t: TObjectSet; obj: PObject);
-// include an element n in the table t
-
-function ObjectSetContainsOrIncl(var t: TObjectSet; obj: PObject): Boolean;
-
-// more are not needed ...
-
-// ----------------------- (key, val)-Hashtables ----------------------------
-
-procedure TablePut(var t: TTable; key, val: PObject);
-function TableGet(const t: TTable; key: PObject): PObject;
-
-type
-  TCmpProc = function (key, closure: PObject): Boolean;
-  // should return true if found
-function TableSearch(const 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 -----------------------------------------
-
-function StrTableContains(const t: TStrTable; n: PSym): Boolean;
-procedure StrTableAdd(var t: TStrTable; n: PSym);
-function StrTableGet(const t: TStrTable; name: PIdent): PSym;
-function StrTableIncl(var t: TStrTable; n: PSym): Boolean;
-// returns true if n is already in the string table
-
-// the iterator scheme:
-type
-  TTabIter = record // consider all fields here private
-    h: THash; // current hash
-  end;
-
-function InitTabIter(out ti: TTabIter; const tab: TStrTable): PSym;
-function NextIter(var ti: TTabIter; const 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 = record // iterator over all syms with the same identifier
-    h: THash; // current hash
-    name: PIdent;
-  end;
-
-function InitIdentIter(out ti: TIdentIter; const tab: TStrTable;
-  s: PIdent): PSym;
-function NextIdentIter(var ti: TIdentIter; const 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 = record
-    tos: Natural; // top of stack
-    stack: array of TStrTable;
-  end;
-
-procedure InitSymTab(out tab: TSymTab);
-procedure DeinitSymTab(var tab: TSymTab);
-
-function SymTabGet(const tab: TSymTab; s: PIdent): PSym;
-function SymTabLocalGet(const tab: TSymTab; s: PIdent): PSym;
-
-procedure SymTabAdd(var tab: TSymTab; e: PSym);
-procedure SymTabAddAt(var tab: TSymTab; e: PSym; at: Natural);
-
-function SymTabAddUnique(var tab: TSymTab; e: PSym): TResult;
-function SymTabAddUniqueAt(var tab: TSymTab; e: PSym; at: Natural): TResult;
-procedure OpenScope(var tab: TSymTab);
-procedure RawCloseScope(var tab: TSymTab); // the real "closeScope" adds some
-// checks in parsobj
-
-
-// these are for debugging only:
-procedure debug(n: PSym); overload;
-procedure debug(n: PType); overload;
-procedure debug(n: PNode); overload;
-
-// --------------------------- ident tables ----------------------------------
-
-function IdTableGet(const t: TIdTable; key: PIdObj): PObject; overload;
-function IdTableGet(const t: TIdTable; key: int): PObject; overload;
-procedure IdTablePut(var t: TIdTable; key: PIdObj; val: PObject);
-
-function IdTableHasObjectAsKey(const t: TIdTable; key: PIdObj): bool;
-// checks if `t` contains the `key` (compared by the pointer value, not only
-// `key`'s id)
-
-function IdNodeTableGet(const t: TIdNodeTable; key: PIdObj): PNode;
-procedure IdNodeTablePut(var t: TIdNodeTable; key: PIdObj; val: PNode);
-
-procedure writeIdNodeTable(const t: TIdNodeTable);
-
-// ---------------------------------------------------------------------------
-function getSymFromList(list: PNode; ident: PIdent; start: int = 0): PSym;
-function lookupInRecord(n: PNode; field: PIdent): PSym;
-
-function getModule(s: PSym): PSym;
-
-function mustRehash(len, counter: int): bool;
-function nextTry(h, maxHash: THash): THash;
-
-// ------------- table[int, int] ---------------------------------------------
-const
-  InvalidKey = low(int);
-
-type
-  TIIPair = record
-    key, val: int;
-  end;
-  TIIPairSeq = array of TIIPair;
-  TIITable = record // table[int, int]
-    counter: int;
-    data: TIIPairSeq;
-  end;
-
-procedure initIITable(out x: TIITable);
-function IITableGet(const t: TIITable; key: int): int;
-procedure IITablePut(var t: TIITable; key, val: int);
-
-implementation
-
-function lookupInRecord(n: PNode; field: PIdent): PSym;
-var
-  i: int;
-begin
-  result := nil;
-  case n.kind of
-    nkRecList: begin
-      for i := 0 to sonsLen(n)-1 do begin
-        result := lookupInRecord(n.sons[i], field);
-        if result <> nil then exit
-      end
-    end;
-    nkRecCase: begin
-      if (n.sons[0].kind <> nkSym) then InternalError(n.info, 'lookupInRecord');
-      result := lookupInRecord(n.sons[0], field);
-      if result <> nil then exit;
-      for i := 1 to sonsLen(n)-1 do begin
-        case n.sons[i].kind of
-          nkOfBranch, nkElse: begin
-            result := lookupInRecord(lastSon(n.sons[i]), field);
-            if result <> nil then exit;
-          end;
-          else internalError(n.info, 'lookupInRecord(record case branch)');
-        end
-      end
-    end;
-    nkSym: begin
-      if n.sym.name.id = field.id then result := n.sym;
-    end;
-    else internalError(n.info, 'lookupInRecord()');
-  end;
-end;
-
-function getModule(s: PSym): PSym;
-begin
-  result := s;
-  assert((result.kind = skModule) or (result.owner <> result));
-  while (result <> nil) and (result.kind <> skModule) do result := result.owner;
-end;
-
-function getSymFromList(list: PNode; ident: PIdent; start: int = 0): PSym;
-var
-  i: int;
-begin
-  for i := start to sonsLen(list)-1 do begin
-    if list.sons[i].kind <> nkSym then
-      InternalError(list.info, 'getSymFromList');
-    result := list.sons[i].sym;
-    if result.name.id = ident.id then exit
-  end;
-  result := nil
-end;
-
-// ---------------------- helpers --------------------------------------------
-
-function hashNode(p: PObject): THash;
-begin
-  result := hashPtr({@cast}pointer(p))
-end;
-
-function mustRehash(len, counter: int): bool;
-begin
-  assert(len > counter);
-  result := (len * 2 < counter * 3) or (len-counter < 4);
-end;
-
-// ---------------------------------------------------------------------------
-
-// convert a node to a string; this is used for YAML code generation and
-// debugging:
-
-function spaces(x: int): PRope; // returns x spaces
-begin
-  result := toRope(repeatChar(x))
-end;
-
-function toYamlChar(c: Char): string;
-begin
-  case c of
-    #0..#31, #128..#255: result := '\u' + strutils.toHex(ord(c), 4);
-    '''', '"', '\': result := '\' + c;
-    else result := c + ''
-  end;
-end;
-
-function makeYamlString(const 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
-  i: int;
-  res: string;
-begin
-  result := nil;
-  res := '"' + '';
-  for i := strStart to length(s)+strStart-1 do begin
-    if (i-strStart+1) mod MaxLineLength = 0 then begin
-      addChar(res, '"');
-      add(res, nl);
-      app(result, toRope(res));
-      res := '"'+''; // reset
-    end;
-    add(res, toYamlChar(s[i]));
-  end;
-  addChar(res, '"');
-  app(result, toRope(res));
-end;
-
-function symFlagsToStr(flags: TSymFlags): PRope;
-var
-  x: TSymFlag;
-begin
-  if flags = [] then
-    result := toRope('[]')
-  else begin
-    result := nil;
-    for x := low(TSymFlag) to high(TSymFlag) do
-      if x in flags then begin
-        if result <> nil then app(result, ', ');
-        app(result, makeYamlString(symFlagToStr[x]));
-      end;
-    result := con('['+'', con(result, ']'+''))
-  end
-end;
-
-function optionsToStr(flags: TOptions): PRope;
-var
-  x: TOption;
-begin
-  if flags = [] then
-    result := toRope('[]')
-  else begin
-    result := nil;
-    for x := low(TOption) to high(TOption) do
-      if x in flags then begin
-        if result <> nil then app(result, ', ');
-        app(result, makeYamlString(optionToStr[x]));
-      end;
-    result := con('['+'', con(result, ']'+''))
-  end
-end;
-
-function typeFlagsToStr(flags: TTypeFlags): PRope;
-var
-  x: TTypeFlag;
-begin
-  if flags = [] then
-    result := toRope('[]')
-  else begin
-    result := nil;
-    for x := low(TTypeFlag) to high(TTypeFlag) do
-      if x in flags then begin
-        if result <> nil then app(result, ', ');
-        app(result, makeYamlString(typeFlagToStr[x]));
-      end;
-    result := con('['+'', con(result, ']'+''))
-  end
-end;
-
-function lineInfoToStr(const info: TLineInfo): PRope;
-begin
-  result := ropef('[$1, $2, $3]', [makeYamlString(toFilename(info)),
-              toRope(toLinenumber(info)), toRope(toColumn(info))]);
-end;
-
-function treeToYamlAux(n: PNode; var marker: TIntSet;
-                       indent: int; maxRecDepth: int): PRope;
-forward;
-
-function symToYamlAux(n: PSym; var marker: TIntSet;
-                      indent: int; maxRecDepth: int): PRope; forward;
-function typeToYamlAux(n: PType; var marker: TIntSet;
-                      indent: int; maxRecDepth: int): PRope; forward;
-
-function strTableToYaml(const n: TStrTable; var marker: TIntSet;
-                        indent: int; maxRecDepth: int): PRope;
-var
-  istr: PRope;
-  mycount, i: int;
-begin
-  istr := spaces(indent+2);
-  result := toRope('['+'');
-  mycount := 0;
-  for i := 0 to high(n.data) do
-    if n.data[i] <> nil then begin
-      if mycount > 0 then app(result, ','+'');
-      appf(result, '$n$1$2',
-        [istr, symToYamlAux(n.data[i], marker, indent+2, maxRecDepth-1)]);
-      inc(mycount)
-    end;
-  if mycount > 0 then appf(result, '$n$1', [spaces(indent)]);
-  app(result, ']'+'');
-  assert(mycount = n.counter);
-end;
-
-function ropeConstr(indent: int; const c: array of PRope): PRope;
-// array of (name, value) pairs
-var
-  istr: PRope;
-  i: int;
-begin
-  istr := spaces(indent+2);
-  result := toRope('{'+'');
-  i := 0;
-  while i <= high(c) do begin
-    if i > 0 then app(result, ','+'');
-    appf(result, '$n$1"$2": $3', [istr, c[i], c[i+1]]);
-    inc(i, 2)
-  end;
-  appf(result, '$n$1}', [spaces(indent)]);
-end;
-
-function symToYamlAux(n: PSym; var marker: TIntSet;
-                      indent: int; maxRecDepth: int): PRope;
-var
-  ast: PRope;
-begin
-  if n = nil then
-    result := toRope('null')
-  else if IntSetContainsOrIncl(marker, n.id) then
-    result := ropef('"$1 @$2"', [
-      toRope(n.name.s),
-      toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
-  else begin
-    ast := treeToYamlAux(n.ast, marker, indent+2, maxRecDepth-1);
-    result := ropeConstr(indent, [
-      toRope('kind'), makeYamlString(symKindToStr[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'), symFlagsToStr(n.flags),
-      toRope('magic'), makeYamlString(MagicToStr[n.magic]),
-      toRope('ast'), ast,
-      toRope('options'), optionsToStr(n.options),
-      toRope('position'), toRope(n.position)
-    ]);
-  end
-  // YYY: backend info?
-end;
-
-function typeToYamlAux(n: PType; var marker: TIntSet;
-                       indent: int; maxRecDepth: int): PRope;
-var
-  i: int;
-begin
-  if n = nil then
-    result := toRope('null')
-  else if intSetContainsOrIncl(marker, n.id) then
-    result := ropef('"$1 @$2"', [
-      toRope(typeKindToStr[n.kind]),
-      toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
-  else begin
-    if sonsLen(n) > 0 then begin
-      result := toRope('['+'');
-      for i := 0 to sonsLen(n)-1 do begin
-        if i > 0 then app(result, ','+'');
-        appf(result, '$n$1$2',
-          [spaces(indent+4),
-           typeToYamlAux(n.sons[i], marker, indent + 4, maxRecDepth-1)]);
-      end;
-      appf(result, '$n$1]', [spaces(indent+2)]);
-    end
-    else
-      result := toRope('null');
-    result := ropeConstr(indent, [
-      toRope('kind'), makeYamlString(typeKindToStr[n.kind]),
-      toRope('sym'), symToYamlAux(n.sym, marker, indent+2, maxRecDepth-1),
-      toRope('n'+''), treeToYamlAux(n.n, marker, indent+2, maxRecDepth-1),
-      toRope('flags'), typeFlagsToStr(n.flags),
-      toRope('callconv'), makeYamlString(CallingConvToStr[n.callConv]),
-      toRope('size'), toRope(n.size),
-      toRope('align'), toRope(n.align),
-      toRope('sons'), result
-    ]);
-  end
-end;
-
-function treeToYamlAux(n: PNode; var marker: TIntSet; indent: int;
-                       maxRecDepth: int): PRope;
-var
-  istr: PRope;
-  i: int;
-begin
-  if n = nil then
-    result := toRope('null')
-  else begin
-    istr := spaces(indent+2);
-    result := ropef('{$n$1"kind": $2',
-                    [istr, makeYamlString(nodeKindToStr[n.kind])]);
-    if maxRecDepth <> 0 then begin
-      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)]);
-        nkFloatLit, nkFloat32Lit, nkFloat64Lit:
-          appf(result, ',$n$1"floatVal": $2', [istr, toRopeF(n.floatVal)]);
-        nkStrLit..nkTripleStrLit:
-          appf(result, ',$n$1"strVal": $2', [istr, makeYamlString(n.strVal)]);
-        nkSym:
-          appf(result, ',$n$1"sym": $2',
-            [istr, symToYamlAux(n.sym, marker, indent+2, maxRecDepth)]);
-
-        nkIdent: begin
-          if n.ident <> nil then
-            appf(result, ',$n$1"ident": $2',
-                          [istr, makeYamlString(n.ident.s)])
-          else
-            appf(result, ',$n$1"ident": null', [istr])
-        end
-        else begin
-          if sonsLen(n) > 0 then begin
-            appf(result, ',$n$1"sons": [', [istr]);
-            for i := 0 to sonsLen(n)-1 do begin
-              if i > 0 then app(result, ','+'');
-              appf(result, '$n$1$2',
-                [spaces(indent+4),
-                 treeToYamlAux(n.sons[i], marker, indent + 4, maxRecDepth-1)]);
-            end;
-            appf(result, '$n$1]', [istr]);
-          end
-        end
-      end;
-      appf(result, ',$n$1"typ": $2',
-        [istr, typeToYamlAux(n.typ, marker, indent+2, maxRecDepth)]);
-    end;
-    appf(result, '$n$1}', [spaces(indent)]);
-  end
-end;
-
-function treeToYaml(n: PNode; indent: int = 0; maxRecDepth: int = -1): PRope;
-var
-  marker: TIntSet;
-begin
-  IntSetInit(marker);
-  result := treeToYamlAux(n, marker, indent, maxRecDepth)
-end;
-
-function typeToYaml(n: PType; indent: int = 0; maxRecDepth: int = -1): PRope;
-var
-  marker: TIntSet;
-begin
-  IntSetInit(marker);
-  result := typeToYamlAux(n, marker, indent, maxRecDepth)
-end;
-
-function symToYaml(n: PSym; indent: int = 0; maxRecDepth: int = -1): PRope;
-var
-  marker: TIntSet;
-begin
-  IntSetInit(marker);
-  result := symToYamlAux(n, marker, indent, maxRecDepth)
-end;
-
-// these are for debugging only:
-function debugType(n: PType): PRope;
-var
-  i: int;
-begin
-  if n = nil then
-    result := toRope('null')
-  else begin
-    result := toRope(typeKindToStr[n.kind]);
-    if n.sym <> nil then begin
-      app(result, ' '+'');
-      app(result, n.sym.name.s);
-    end;
-    if (n.kind <> tyString) and (sonsLen(n) > 0) then begin
-      app(result, '('+'');
-      for i := 0 to sonsLen(n)-1 do begin
-        if i > 0 then app(result, ', ');
-        if n.sons[i] = nil then app(result, 'null')
-        else app(result, debugType(n.sons[i]));
-         //  app(result, typeKindToStr[n.sons[i].kind]);
-      end;
-      app(result, ')'+'');
-    end
-  end
-end;
-
-function debugTree(n: PNode; indent: int; maxRecDepth: int): PRope;
-var
-  istr: PRope;
-  i: int;
-begin
-  if n = nil then
-    result := toRope('null')
-  else begin
-    istr := spaces(indent+2);
-    result := ropef('{$n$1"kind": $2',
-                         [istr, makeYamlString(nodeKindToStr[n.kind])]);
-    if maxRecDepth <> 0 then begin
-      case n.kind of
-        nkCharLit..nkInt64Lit:
-          appf(result, ',$n$1"intVal": $2', [istr, toRope(n.intVal)]);
-        nkFloatLit, nkFloat32Lit, nkFloat64Lit:
-          appf(result, ',$n$1"floatVal": $2',
-                        [istr, toRopeF(n.floatVal)]);
-        nkStrLit..nkTripleStrLit:
-          appf(result, ',$n$1"strVal": $2',
-                        [istr, makeYamlString(n.strVal)]);
-        nkSym:
-          appf(result, ',$n$1"sym": $2_$3',
-            [istr, toRope(n.sym.name.s), toRope(n.sym.id)]);
-
-        nkIdent: begin
-          if n.ident <> nil then
-            appf(result, ',$n$1"ident": $2',
-                          [istr, makeYamlString(n.ident.s)])
-          else
-            appf(result, ',$n$1"ident": null', [istr])
-        end
-        else begin
-          if sonsLen(n) > 0 then begin
-            appf(result, ',$n$1"sons": [', [istr]);
-            for i := 0 to sonsLen(n)-1 do begin
-              if i > 0 then app(result, ','+'');
-              appf(result, '$n$1$2',
-                [spaces(indent+4),
-                 debugTree(n.sons[i], indent + 4, maxRecDepth-1)]);
-            end;
-            appf(result, '$n$1]', [istr]);
-          end
-        end
-      end;
-    end;
-    appf(result, '$n$1}', [spaces(indent)]);
-  end
-end;
-
-procedure debug(n: PSym); overload;
-begin
-  writeln(output, ropeToStr(ropef('$1_$2', [toRope(n.name.s), toRope(n.id)])));
-end;
-
-procedure debug(n: PType); overload;
-begin
-  writeln(output, ropeToStr(debugType(n)));
-end;
-
-procedure debug(n: PNode); overload;
-begin
-  writeln(output, ropeToStr(debugTree(n, 0, 100)));
-end;
-
-// -------------------- node sets --------------------------------------------
-
-{@ignore}
-const
-  EmptySeq = nil;
-{@emit
-const
-  EmptySeq = @[];
-}
-
-function nextTry(h, maxHash: THash): THash;
-begin
-  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).
-end;
-
-function objectSetContains(const t: TObjectSet; obj: PObject): Boolean;
-// returns true whether n is in t
-var
-  h: THash;
-begin
-  h := hashNode(obj) and high(t.data); // start with real hash value
-  while t.data[h] <> nil do begin
-    if (t.data[h] = obj) then begin
-      result := true; exit
-    end;
-    h := nextTry(h, high(t.data))
-  end;
-  result := false
-end;
-
-procedure objectSetRawInsert(var data: TObjectSeq; obj: PObject);
-var
-  h: THash;
-begin
-  h := HashNode(obj) and high(data);
-  while data[h] <> nil do begin
-    assert(data[h] <> obj);
-    h := nextTry(h, high(data))
-  end;
-  assert(data[h] = nil);
-  data[h] := obj;
-end;
-
-procedure objectSetEnlarge(var t: TObjectSet);
-var
-  n: TObjectSeq;
-  i: int;
-begin
-{@ignore}
-  n := emptySeq;
-  setLength(n, length(t.data) * growthFactor);
-  fillChar(n[0], length(n)*sizeof(n[0]), 0);
-{@emit
-  newSeq(n, length(t.data) * growthFactor); }
-  for i := 0 to high(t.data) do
-    if t.data[i] <> nil then objectSetRawInsert(n, t.data[i]);
-{@ignore}
-  t.data := n;
-{@emit
-  swap(t.data, n);
-}
-end;
-
-procedure objectSetIncl(var t: TObjectSet; obj: PObject);
-begin
-  if mustRehash(length(t.data), t.counter) then objectSetEnlarge(t);
-  objectSetRawInsert(t.data, obj);
-  inc(t.counter);
-end;
-
-function objectSetContainsOrIncl(var t: TObjectSet; obj: PObject): Boolean;
-// returns true if obj is already in the string table:
-var
-  h: THash;
-  it: PObject;
-begin
-  h := HashNode(obj) and high(t.data);
-  repeat
-    it := t.data[h];
-    if it = nil then break;
-    if it = obj then begin
-      result := true; exit // found it
-    end;
-    h := nextTry(h, high(t.data))
-  until false;
-  if mustRehash(length(t.data), t.counter) then begin
-    objectSetEnlarge(t);
-    objectSetRawInsert(t.data, obj);
-  end
-  else begin
-    assert(t.data[h] = nil);
-    t.data[h] := obj;
-  end;
-  inc(t.counter);
-  result := false
-end;
-
-// --------------------------- node tables -----------------------------------
-
-function TableRawGet(const t: TTable; key: PObject): int;
-var
-  h: THash;
-begin
-  h := hashNode(key) and high(t.data); // start with real hash value
-  while t.data[h].key <> nil do begin
-    if (t.data[h].key = key) then begin
-      result := h; exit
-    end;
-    h := nextTry(h, high(t.data))
-  end;
-  result := -1
-end;
-
-function TableSearch(const t: TTable; key, closure: PObject;
-                     comparator: TCmpProc): PObject;
-var
-  h: THash;
-begin
-  h := hashNode(key) and high(t.data); // start with real hash value
-  while t.data[h].key <> nil do begin
-    if (t.data[h].key = key) then
-      if comparator(t.data[h].val, closure) then begin // BUGFIX 1
-        result := t.data[h].val; exit
-      end;
-    h := nextTry(h, high(t.data))
-  end;
-  result := nil
-end;
-
-function TableGet(const t: TTable; key: PObject): PObject;
-var
-  index: int;
-begin
-  index := TableRawGet(t, key);
-  if index >= 0 then result := t.data[index].val
-  else result := nil
-end;
-
-procedure TableRawInsert(var data: TPairSeq; key, val: PObject);
-var
-  h: THash;
-begin
-  h := HashNode(key) and high(data);
-  while data[h].key <> nil do begin
-    assert(data[h].key <> key);
-    h := nextTry(h, high(data))
-  end;
-  assert(data[h].key = nil);
-  data[h].key := key;
-  data[h].val := val;
-end;
-
-procedure TableEnlarge(var t: TTable);
-var
-  n: TPairSeq;
-  i: int;
-begin
-{@ignore}
-  n := emptySeq;
-  setLength(n, length(t.data) * growthFactor);
-  fillChar(n[0], length(n)*sizeof(n[0]), 0);
-{@emit
-  newSeq(n, length(t.data) * growthFactor); }
-  for i := 0 to high(t.data) do
-    if t.data[i].key <> nil then
-      TableRawInsert(n, t.data[i].key, t.data[i].val);
-{@ignore}
-  t.data := n;
-{@emit
-  swap(t.data, n);
-}
-end;
-
-procedure TablePut(var t: TTable; key, val: PObject);
-var
-  index: int;
-begin
-  index := TableRawGet(t, key);
-  if index >= 0 then
-    t.data[index].val := val
-  else begin
-    if mustRehash(length(t.data), t.counter) then TableEnlarge(t);
-    TableRawInsert(t.data, key, val);
-    inc(t.counter)
-  end;
-end;
-
-// ----------------------- string tables ------------------------------------
-
-function StrTableContains(const t: TStrTable; n: PSym): Boolean;
-var
-  h: THash;
-begin
-  h := n.name.h and high(t.data); // start with real hash value
-  while t.data[h] <> nil do begin
-    if (t.data[h] = n) then begin
-      result := true; exit
-    end;
-    h := nextTry(h, high(t.data))
-  end;
-  result := false
-end;
-
-procedure StrTableRawInsert(var data: TSymSeq; n: PSym);
-var
-  h: THash;
-begin
-  h := n.name.h and high(data);
-  while data[h] <> nil do begin
-    if data[h] = n then
-      InternalError(n.info, 'StrTableRawInsert: ' + n.name.s);
-    h := nextTry(h, high(data))
-  end;
-  assert(data[h] = nil);
-  data[h] := n;
-end;
-
-procedure StrTableEnlarge(var t: TStrTable);
-var
-  n: TSymSeq;
-  i: int;
-begin
-{@ignore}
-  n := emptySeq;
-  setLength(n, length(t.data) * growthFactor);
-  fillChar(n[0], length(n)*sizeof(n[0]), 0);
-{@emit
-  newSeq(n, length(t.data) * growthFactor); }
-  for i := 0 to high(t.data) do
-    if t.data[i] <> nil then StrTableRawInsert(n, t.data[i]);
-{@ignore}
-  t.data := n;
-{@emit
-  swap(t.data, n);
-}
-end;
-
-procedure StrTableAdd(var t: TStrTable; n: PSym);
-begin
-  if mustRehash(length(t.data), t.counter) then StrTableEnlarge(t);
-  StrTableRawInsert(t.data, n);
-  inc(t.counter);
-end;
-
-function StrTableIncl(var t: TStrTable; n: PSym): Boolean;
-// returns true if n is already in the string table:
-var
-  h: THash;
-  it: PSym;
-begin
-  h := n.name.h and high(t.data);
-  repeat
-    it := t.data[h];
-    if it = nil then break;
-    if it.name.id = n.name.id then begin
-      result := true; exit // found it
-    end;
-    h := nextTry(h, high(t.data))
-  until false;
-  if mustRehash(length(t.data), t.counter) then begin
-    StrTableEnlarge(t);
-    StrTableRawInsert(t.data, n);
-  end
-  else begin
-    assert(t.data[h] = nil);
-    t.data[h] := n;
-  end;
-  inc(t.counter);
-  result := false
-end;
-
-function StrTableGet(const t: TStrTable; name: PIdent): PSym;
-var
-  h: THash;
-begin
-  h := name.h and high(t.data);
-  repeat
-    result := t.data[h];
-    if result = nil then break;
-    if result.name.id = name.id then
-      break;
-    h := nextTry(h, high(t.data))
-  until false;
-end;
-
-// iterators:
-
-function InitIdentIter(out ti: TIdentIter; const tab: TStrTable;
-                       s: PIdent): PSym;
-begin
-  ti.h := s.h;
-  ti.name := s;
-  if tab.Counter = 0 then result := nil
-  else result := NextIdentIter(ti, tab)
-end;
-
-function NextIdentIter(var ti: TIdentIter; const tab: TStrTable): PSym;
-var
-  h, start: THash;
-begin
-  h := ti.h and high(tab.data);
-  start := h;
-  result := tab.data[h];
-  while (result <> nil) do begin
-    if result.Name.id = ti.name.id then break;
-    h := nextTry(h, high(tab.data));
-    if h = start then begin
-      result := nil;
-      break
-    end;
-    result := tab.data[h]
-  end;
-  ti.h := nextTry(h, high(tab.data))
-end;
-
-function InitTabIter(out ti: TTabIter; const tab: TStrTable): PSym;
-begin
-  ti.h := 0; // we start by zero ...
-  if tab.counter = 0 then result := nil // FIX 1: removed endless loop
-  else result := NextIter(ti, tab)
-end;
-
-function NextIter(var ti: TTabIter; const tab: TStrTable): PSym;
-begin
-  result := nil;
-  while (ti.h <= high(tab.data)) do begin
-    result := tab.data[ti.h];
-    Inc(ti.h); // ... and increment by one always
-    if result <> nil then break
-  end;
-end;
-
-// ------------------- symbol table ------------------------------------------
-
-procedure InitSymTab(out tab: TSymTab);
-begin
-  tab.tos := 0;
-  tab.stack := EmptySeq;
-end;
-
-procedure DeinitSymTab(var tab: TSymTab);
-begin
-  tab.stack := nil;
-end;
-
-function SymTabLocalGet(const tab: TSymTab; s: PIdent): PSym;
-begin
-  result := StrTableGet(tab.stack[tab.tos-1], s)
-end;
-
-function SymTabGet(const tab: TSymTab; s: PIdent): PSym;
-var
-  i: int;
-begin
-  for i := tab.tos-1 downto 0 do begin
-    result := StrTableGet(tab.stack[i], s);
-    if result <> nil then exit
-  end;
-  result := nil
-end;
-
-procedure SymTabAddAt(var tab: TSymTab; e: PSym; at: Natural);
-begin
-  StrTableAdd(tab.stack[at], e);
-end;
-
-procedure SymTabAdd(var tab: TSymTab; e: PSym);
-begin
-  StrTableAdd(tab.stack[tab.tos-1], e)
-end;
-
-function SymTabAddUniqueAt(var tab: TSymTab; e: PSym; at: Natural): TResult;
-begin
-  if StrTableGet(tab.stack[at], e.name) <> nil then begin
-    result := Failure;
-  end
-  else begin
-    StrTableAdd(tab.stack[at], e);
-    result := Success
-  end
-end;
-
-function SymTabAddUnique(var tab: TSymTab; e: PSym): TResult;
-begin
-  result := SymTabAddUniqueAt(tab, e, tab.tos-1)
-end;
-
-procedure OpenScope(var tab: TSymTab);
-begin
-  if tab.tos >= length(tab.stack) then
-    SetLength(tab.stack, tab.tos + 1);
-  initStrTable(tab.stack[tab.tos]);
-  Inc(tab.tos)
-end;
-
-procedure RawCloseScope(var tab: TSymTab);
-begin
-  Dec(tab.tos);
-  //tab.stack[tab.tos] := nil;
-end;
-
-// --------------------------- ident tables ----------------------------------
-
-function hasEmptySlot(const data: TIdPairSeq): bool;
-var
-  h: THash;
-begin
-  for h := 0 to high(data) do
-    if data[h].key = nil then begin result := true; exit end;
-  result := false
-end;
-
-function IdTableRawGet(const t: TIdTable; key: int): int;
-var
-  h: THash;
-begin
-  h := key and high(t.data); // start with real hash value
-  while t.data[h].key <> nil do begin
-    if (t.data[h].key.id = key) then begin
-      result := h; exit
-    end;
-    h := nextTry(h, high(t.data))
-  end;
-  result := -1
-end;
-
-function IdTableHasObjectAsKey(const t: TIdTable; key: PIdObj): bool;
-var
-  index: int;
-begin
-  index := IdTableRawGet(t, key.id);
-  if index >= 0 then result := t.data[index].key = key
-  else result := false
-end;
-
-function IdTableGet(const t: TIdTable; key: PIdObj): PObject;
-var
-  index: int;
-begin
-  index := IdTableRawGet(t, key.id);
-  if index >= 0 then result := t.data[index].val
-  else result := nil
-end;
-
-function IdTableGet(const t: TIdTable; key: int): PObject;
-var
-  index: int;
-begin
-  index := IdTableRawGet(t, key);
-  if index >= 0 then result := t.data[index].val
-  else result := nil
-end;
-
-procedure IdTableRawInsert(var data: TIdPairSeq;
-                           key: PIdObj; val: PObject);
-var
-  h: THash;
-begin
-  h := key.id and high(data);
-  while data[h].key <> nil do begin
-    assert(data[h].key.id <> key.id);
-    h := nextTry(h, high(data))
-  end;
-  assert(data[h].key = nil);
-  data[h].key := key;
-  data[h].val := val;
-end;
-
-procedure IdTablePut(var t: TIdTable; key: PIdObj; val: PObject);
-var
-  index, i: int;
-  n: TIdPairSeq;
-begin
-  index := IdTableRawGet(t, key.id);
-  if index >= 0 then begin
-    assert(t.data[index].key <> nil);
-    t.data[index].val := val
-  end
-  else begin
-    if mustRehash(length(t.data), t.counter) then begin
-    {@ignore}
-      setLength(n, length(t.data) * growthFactor);
-      fillChar(n[0], length(n)*sizeof(n[0]), 0);
-    {@emit
-      newSeq(n, length(t.data) * growthFactor); }
-      for i := 0 to high(t.data) do
-        if t.data[i].key <> nil then
-          IdTableRawInsert(n, t.data[i].key, t.data[i].val);
-      assert(hasEmptySlot(n));
-    {@ignore}
-      t.data := n;
-    {@emit
-      swap(t.data, n);
-    }
-    end;
-    IdTableRawInsert(t.data, key, val);
-    inc(t.counter)
-  end;
-end;
-
-
-procedure writeIdNodeTable(const t: TIdNodeTable);
-var
-  h: THash;
-begin
-{@ignore}
-  write('{'+'');
-  for h := 0 to high(t.data) do
-    if t.data[h].key <> nil then begin
-      write(t.data[h].key.id : 5);
-    end;
-  writeln('}'+'');
-{@emit}
-end;
-
-function IdNodeTableRawGet(const t: TIdNodeTable; key: PIdObj): int;
-var
-  h: THash;
-begin
-  h := key.id and high(t.data); // start with real hash value
-  while t.data[h].key <> nil do begin
-    if (t.data[h].key.id = key.id) then begin
-      result := h; exit
-    end;
-    h := nextTry(h, high(t.data))
-  end;
-  result := -1
-end;
-
-function IdNodeTableGet(const t: TIdNodeTable; key: PIdObj): PNode;
-var
-  index: int;
-begin
-  index := IdNodeTableRawGet(t, key);
-  if index >= 0 then result := t.data[index].val
-  else result := nil
-end;
-
-procedure IdNodeTableRawInsert(var data: TIdNodePairSeq;
-                               key: PIdObj; val: PNode);
-var
-  h: THash;
-begin
-  h := key.id and high(data);
-  while data[h].key <> nil do begin
-    assert(data[h].key.id <> key.id);
-    h := nextTry(h, high(data))
-  end;
-  assert(data[h].key = nil);
-  data[h].key := key;
-  data[h].val := val;
-end;
-
-procedure IdNodeTablePut(var t: TIdNodeTable; key: PIdObj; val: PNode);
-var
-  index, i: int;
-  n: TIdNodePairSeq;
-begin
-  index := IdNodeTableRawGet(t, key);
-  if index >= 0 then begin
-    assert(t.data[index].key <> nil);
-    t.data[index].val := val
-  end
-  else begin
-    if mustRehash(length(t.data), t.counter) then begin
-    {@ignore}
-      setLength(n, length(t.data) * growthFactor);
-      fillChar(n[0], length(n)*sizeof(n[0]), 0);
-    {@emit
-      newSeq(n, length(t.data) * growthFactor); }
-      for i := 0 to high(t.data) do
-        if t.data[i].key <> nil then
-          IdNodeTableRawInsert(n, t.data[i].key, t.data[i].val);
-    {@ignore}
-      t.data := n;
-    {@emit
-      swap(t.data, n);
-    }
-    end;
-    IdNodeTableRawInsert(t.data, key, val);
-    inc(t.counter)
-  end;
-end;
-
-// ------------- int-to-int-mapping ------------------------------------------
-
-procedure initIITable(out x: TIITable);
-var
-  i: int;
-begin
-  x.counter := 0;
-{@ignore}
-  setLength(x.data, startSize);
-{@emit
-  newSeq(x.data, startSize); }
-  for i := 0 to startSize-1 do x.data[i].key := InvalidKey;
-end;
-
-function IITableRawGet(const t: TIITable; key: int): int;
-var
-  h: THash;
-begin
-  h := key and high(t.data); // start with real hash value
-  while t.data[h].key <> InvalidKey do begin
-    if (t.data[h].key = key) then begin
-      result := h; exit
-    end;
-    h := nextTry(h, high(t.data))
-  end;
-  result := -1
-end;
-
-function IITableGet(const t: TIITable; key: int): int;
-var
-  index: int;
-begin
-  index := IITableRawGet(t, key);
-  if index >= 0 then result := t.data[index].val
-  else result := InvalidKey
-end;
-
-procedure IITableRawInsert(var data: TIIPairSeq;
-                           key, val: int);
-var
-  h: THash;
-begin
-  h := key and high(data);
-  while data[h].key <> InvalidKey do begin
-    assert(data[h].key <> key);
-    h := nextTry(h, high(data))
-  end;
-  assert(data[h].key = InvalidKey);
-  data[h].key := key;
-  data[h].val := val;
-end;
-
-procedure IITablePut(var t: TIITable; key, val: int);
-var
-  index, i: int;
-  n: TIIPairSeq;
-begin
-  index := IITableRawGet(t, key);
-  if index >= 0 then begin
-    assert(t.data[index].key <> InvalidKey);
-    t.data[index].val := val
-  end
-  else begin
-    if mustRehash(length(t.data), t.counter) then begin
-    {@ignore}
-      setLength(n, length(t.data) * growthFactor);
-    {@emit
-      newSeq(n, length(t.data) * growthFactor); }
-      for i := 0 to high(n) do n[i].key := InvalidKey;
-      for i := 0 to high(t.data) do
-        if t.data[i].key <> InvalidKey then
-          IITableRawInsert(n, t.data[i].key, t.data[i].val);
-    {@ignore}
-      t.data := n;
-    {@emit
-      swap(t.data, n); }
-    end;
-    IITableRawInsert(t.data, key, val);
-    inc(t.counter)
-  end;
-end;
-
-end.