summary refs log tree commit diff stats
path: root/nim/ast.pas
diff options
context:
space:
mode:
Diffstat (limited to 'nim/ast.pas')
-rw-r--r--nim/ast.pas2548
1 files changed, 1426 insertions, 1122 deletions
diff --git a/nim/ast.pas b/nim/ast.pas
index 587284d56..c84262db4 100644
--- a/nim/ast.pas
+++ b/nim/ast.pas
@@ -1,1122 +1,1426 @@
-//
-//
-//           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
-//
-//    See the file "copying.txt", included in this
-//    distribution, for details about the copyright.
-//
-unit ast;
-
-// abstract syntax tree + symbol table
-
-interface
-
-{$include 'config.inc'}
-
-uses
-  nsystem, charsets, msgs, hashes,
-  nversion, options, strutils, crc, ropes, idents, lists;
-
-const
-  ImportTablePos = 0;
-  ModuleTablePos = 1;
-
-type
-  TCallingConvention = (
-    ccDefault,   // proc has no explicit calling convention
-    ccStdCall,   // procedure is stdcall
-    ccCDecl,     // cdecl
-    ccSafeCall,  // safecall
-    ccSysCall,   // system call
-    ccInline,    // proc should be inlined
-    ccFastCall,  // fastcall (pass parameters in registers)
-    ccClosure,   // proc has a closure
-    ccNoConvention // needed for generating proper C procs sometimes
-  );
-
-const
-  CallingConvToStr: array [TCallingConvention] of string = (
-    '', 'stdcall', 'cdecl', 'safecall', 'syscall', 'inline', 'fastcall',
-    'closure', 'noconv');
-
-(*[[[cog
-def toEnum(name, elems, prefixlen=0):
-  body = ""
-  strs = ""
-  prefix = ""
-  counter = 0
-  for e in elems:
-    if counter % 4 == 0: prefix = "\n    "
-    else: prefix = ""
-    body += prefix + e + ', '
-    strs += prefix + "'%s', " % e[prefixlen:]
-    counter += 1
-
-  return ("type\n  T%s = (%s);\n  T%ss = set of T%s;\n"
-            % (name, body.rstrip(", "), name, name),
-          "const\n  %sToStr: array [T%s] of string = (%s);\n"
-            % (name, name, strs.rstrip(", ")))
-
-enums = eval(file("data/ast.yml").read())
-for key, val in enums.iteritems():
-  (a, b) = toEnum(key, val)
-  cog.out(a)
-  cog.out(b)
-]]]*)
-type
-  TNodeKind = (
-    nkNone, nkEmpty, nkIdent, nkSym, 
-    nkType, nkCharLit, nkIntLit, nkInt8Lit, 
-    nkInt16Lit, nkInt32Lit, nkInt64Lit, nkFloatLit, 
-    nkFloat32Lit, nkFloat64Lit, nkStrLit, nkRStrLit, 
-    nkTripleStrLit, nkMetaNode, nkNilLit, nkDotCall, 
-    nkCommand, nkCall, nkGenericCall, nkExplicitTypeListCall, 
-    nkExprEqExpr, nkExprColonExpr, nkIdentDefs, nkInfix, 
-    nkPrefix, nkPostfix, nkPar, nkCurly, 
-    nkBracket, nkBracketExpr, nkPragmaExpr, nkRange, 
-    nkDotExpr, nkCheckedFieldExpr, nkDerefExpr, nkIfExpr, 
-    nkElifExpr, nkElseExpr, nkLambda, nkAccQuoted, 
-    nkHeaderQuoted, nkTableConstr, nkQualified, nkHiddenStdConv, 
-    nkHiddenSubConv, nkHiddenCallConv, nkConv, nkCast, 
-    nkAddr, nkHiddenAddr, nkHiddenDeref, nkObjDownConv, 
-    nkObjUpConv, nkChckRangeF, nkChckRange64, nkChckRange, 
-    nkStringToCString, nkCStringToString, nkPassAsOpenArray, nkAsgn, 
-    nkDefaultTypeParam, nkGenericParams, nkFormalParams, nkOfInherit, 
-    nkModule, nkProcDef, nkConverterDef, nkMacroDef, 
-    nkTemplateDef, nkIteratorDef, nkOfBranch, nkElifBranch, 
-    nkExceptBranch, nkElse, nkMacroStmt, nkAsmStmt, 
-    nkPragma, nkIfStmt, nkWhenStmt, nkForStmt, 
-    nkWhileStmt, nkCaseStmt, nkVarSection, nkConstSection, 
-    nkConstDef, nkTypeSection, nkTypeDef, nkYieldStmt, 
-    nkTryStmt, nkFinally, nkRaiseStmt, nkReturnStmt, 
-    nkBreakStmt, nkContinueStmt, nkBlockStmt, nkDiscardStmt, 
-    nkStmtList, nkImportStmt, nkFromStmt, nkImportAs, 
-    nkIncludeStmt, nkAccessStmt, nkCommentStmt, nkStmtListExpr, 
-    nkBlockExpr, nkVm, nkTypeOfExpr, nkObjectTy, 
-    nkTupleTy, nkRecList, nkRecCase, nkRecWhen, 
-    nkRefTy, nkPtrTy, nkVarTy, nkProcTy, 
-    nkEnumTy, nkEnumFieldDef, nkReturnToken);
-  TNodeKinds = set of TNodeKind;
-const
-  NodeKindToStr: array [TNodeKind] of string = (
-    'nkNone', 'nkEmpty', 'nkIdent', 'nkSym', 
-    'nkType', 'nkCharLit', 'nkIntLit', 'nkInt8Lit', 
-    'nkInt16Lit', 'nkInt32Lit', 'nkInt64Lit', 'nkFloatLit', 
-    'nkFloat32Lit', 'nkFloat64Lit', 'nkStrLit', 'nkRStrLit', 
-    'nkTripleStrLit', 'nkMetaNode', 'nkNilLit', 'nkDotCall', 
-    'nkCommand', 'nkCall', 'nkGenericCall', 'nkExplicitTypeListCall', 
-    'nkExprEqExpr', 'nkExprColonExpr', 'nkIdentDefs', 'nkInfix', 
-    'nkPrefix', 'nkPostfix', 'nkPar', 'nkCurly', 
-    'nkBracket', 'nkBracketExpr', 'nkPragmaExpr', 'nkRange', 
-    'nkDotExpr', 'nkCheckedFieldExpr', 'nkDerefExpr', 'nkIfExpr', 
-    'nkElifExpr', 'nkElseExpr', 'nkLambda', 'nkAccQuoted', 
-    'nkHeaderQuoted', 'nkTableConstr', 'nkQualified', 'nkHiddenStdConv', 
-    'nkHiddenSubConv', 'nkHiddenCallConv', 'nkConv', 'nkCast', 
-    'nkAddr', 'nkHiddenAddr', 'nkHiddenDeref', 'nkObjDownConv', 
-    'nkObjUpConv', 'nkChckRangeF', 'nkChckRange64', 'nkChckRange', 
-    'nkStringToCString', 'nkCStringToString', 'nkPassAsOpenArray', 'nkAsgn', 
-    'nkDefaultTypeParam', 'nkGenericParams', 'nkFormalParams', 'nkOfInherit', 
-    'nkModule', 'nkProcDef', 'nkConverterDef', 'nkMacroDef', 
-    'nkTemplateDef', 'nkIteratorDef', 'nkOfBranch', 'nkElifBranch', 
-    'nkExceptBranch', 'nkElse', 'nkMacroStmt', 'nkAsmStmt', 
-    'nkPragma', 'nkIfStmt', 'nkWhenStmt', 'nkForStmt', 
-    'nkWhileStmt', 'nkCaseStmt', 'nkVarSection', 'nkConstSection', 
-    'nkConstDef', 'nkTypeSection', 'nkTypeDef', 'nkYieldStmt', 
-    'nkTryStmt', 'nkFinally', 'nkRaiseStmt', 'nkReturnStmt', 
-    'nkBreakStmt', 'nkContinueStmt', 'nkBlockStmt', 'nkDiscardStmt', 
-    'nkStmtList', 'nkImportStmt', 'nkFromStmt', 'nkImportAs', 
-    'nkIncludeStmt', 'nkAccessStmt', 'nkCommentStmt', 'nkStmtListExpr', 
-    'nkBlockExpr', 'nkVm', 'nkTypeOfExpr', 'nkObjectTy', 
-    'nkTupleTy', 'nkRecList', 'nkRecCase', 'nkRecWhen', 
-    'nkRefTy', 'nkPtrTy', 'nkVarTy', 'nkProcTy', 
-    'nkEnumTy', 'nkEnumFieldDef', 'nkReturnToken');
-type
-  TSymFlag = (
-    sfTypeCheck, sfForward, sfImportc, sfExportc, 
-    sfVolatile, sfUsed, sfWrite, sfRegister, 
-    sfPure, sfCodeGenerated, sfPrivate, sfGlobal, 
-    sfResult, sfNoSideEffect, sfMainModule, sfSystemModule, 
-    sfNoReturn, sfAddrTaken, sfInInterface, sfNoStatic, 
-    sfCompilerProc, sfCppMethod, sfDiscriminant, sfDeprecated, 
-    sfInClosure, sfIsCopy, sfStar, sfMinus);
-  TSymFlags = set of TSymFlag;
-const
-  SymFlagToStr: array [TSymFlag] of string = (
-    'sfTypeCheck', 'sfForward', 'sfImportc', 'sfExportc', 
-    'sfVolatile', 'sfUsed', 'sfWrite', 'sfRegister', 
-    'sfPure', 'sfCodeGenerated', 'sfPrivate', 'sfGlobal', 
-    'sfResult', 'sfNoSideEffect', 'sfMainModule', 'sfSystemModule', 
-    'sfNoReturn', 'sfAddrTaken', 'sfInInterface', 'sfNoStatic', 
-    'sfCompilerProc', 'sfCppMethod', 'sfDiscriminant', 'sfDeprecated', 
-    'sfInClosure', 'sfIsCopy', 'sfStar', 'sfMinus');
-type
-  TTypeKind = (
-    tyNone, tyBool, tyChar, tyEmptySet, 
-    tyArrayConstr, tyNil, tyGeneric, tyGenericInst, 
-    tyGenericParam, tyEnum, tyAnyEnum, tyArray, 
-    tyObject, tyTuple, tySet, tyRange, 
-    tyPtr, tyRef, tyVar, tySequence, 
-    tyProc, tyPointer, tyOpenArray, tyString, 
-    tyCString, tyForward, tyInt, tyInt8, 
-    tyInt16, tyInt32, tyInt64, tyFloat, 
-    tyFloat32, tyFloat64, tyFloat128);
-  TTypeKinds = set of TTypeKind;
-const
-  TypeKindToStr: array [TTypeKind] of string = (
-    'tyNone', 'tyBool', 'tyChar', 'tyEmptySet', 
-    'tyArrayConstr', 'tyNil', 'tyGeneric', 'tyGenericInst', 
-    'tyGenericParam', 'tyEnum', 'tyAnyEnum', 'tyArray', 
-    'tyObject', 'tyTuple', 'tySet', 'tyRange', 
-    'tyPtr', 'tyRef', 'tyVar', 'tySequence', 
-    'tyProc', 'tyPointer', 'tyOpenArray', 'tyString', 
-    'tyCString', 'tyForward', 'tyInt', 'tyInt8', 
-    'tyInt16', 'tyInt32', 'tyInt64', 'tyFloat', 
-    'tyFloat32', 'tyFloat64', 'tyFloat128');
-type
-  TNodeFlag = (
-    nfNone, nfBase2, nfBase8, nfBase16, 
-    nfAllConst);
-  TNodeFlags = set of TNodeFlag;
-const
-  NodeFlagToStr: array [TNodeFlag] of string = (
-    'nfNone', 'nfBase2', 'nfBase8', 'nfBase16', 
-    'nfAllConst');
-type
-  TTypeFlag = (
-    tfIsDistinct, tfGeneric, tfExternal, tfImported, 
-    tfInfoGenerated, tfSemChecked, tfHasOutParams, tfEnumHasWholes, 
-    tfVarargs, tfFinal);
-  TTypeFlags = set of TTypeFlag;
-const
-  TypeFlagToStr: array [TTypeFlag] of string = (
-    'tfIsDistinct', 'tfGeneric', 'tfExternal', 'tfImported', 
-    'tfInfoGenerated', 'tfSemChecked', 'tfHasOutParams', 'tfEnumHasWholes', 
-    'tfVarargs', 'tfFinal');
-type
-  TSymKind = (
-    skUnknownSym, skConditional, skDynLib, skParam, 
-    skTypeParam, skTemp, skType, skConst, 
-    skVar, skProc, skIterator, skConverter, 
-    skMacro, skTemplate, skField, skEnumField, 
-    skForVar, skModule, skLabel);
-  TSymKinds = set of TSymKind;
-const
-  SymKindToStr: array [TSymKind] of string = (
-    'skUnknownSym', 'skConditional', 'skDynLib', 'skParam', 
-    'skTypeParam', 'skTemp', 'skType', 'skConst', 
-    'skVar', 'skProc', 'skIterator', 'skConverter', 
-    'skMacro', 'skTemplate', 'skField', 'skEnumField', 
-    'skForVar', 'skModule', 'skLabel');
-{[[[end]]]}
-
-type
-  // symbols that require compiler magic:
-  TMagic = (
-    //[[[cog
-    //magics = eval(file("data/magic.yml").read())
-    //for i in range(0, len(magics)-1):
-    //  cog.out("m" + magics[i] + ", ")
-    //  if (i+1) % 6 == 0: cog.outl("")
-    //cog.outl("m" + magics[-1])
-    //]]]
-    mNone, mDefined, mNew, mNewFinalize, mLow, mHigh, 
-    mSizeOf, mRegisterFinalizer, mSucc, mPred, mInc, mDec, 
-    mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, 
-    mCard, mOrd, mChr, mAddI, mSubI, mMulI, 
-    mDivI, mModI, mAddI64, mSubI64, mMulI64, mDivI64, 
-    mModI64, mShrI, mShlI, mBitandI, mBitorI, mBitxorI, 
-    mMinI, mMaxI, mShrI64, mShlI64, mBitandI64, mBitorI64, 
-    mBitxorI64, mMinI64, mMaxI64, mAddF64, mSubF64, mMulF64, 
-    mDivF64, mMinF64, mMaxF64, mAddU, mSubU, mMulU, 
-    mDivU, mModU, mAddU64, mSubU64, mMulU64, mDivU64, 
-    mModU64, mEqI, mLeI, mLtI, mEqI64, mLeI64, 
-    mLtI64, mEqF64, mLeF64, mLtF64, mLeU, mLtU, 
-    mLeU64, mLtU64, mEqEnum, mLeEnum, mLtEnum, mEqCh, 
-    mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef, 
-    mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, 
-    mUnaryMinusI, mUnaryMinusI64, mAbsI, mAbsI64, mNot, mUnaryPlusI, 
-    mBitnotI, mUnaryPlusI64, mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, 
-    mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, 
-    mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt, 
-    mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, 
-    mCStrToStr, mStrToStr, mAnd, mOr, mEqStr, mLeStr, 
-    mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, 
-    mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, mConTArr, 
-    mConTT, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq, 
-    mInRange, mInSet, mIs, mAsgn, mRepr, mExit, 
-    mSetLengthStr, mSetLengthSeq, mAssert, mSwap, mIsNil, mArray, 
-    mOpenArray, mRange, mSet, mSeq, mCompileDate, mCompileTime, 
-    mNimrodVersion, mNimrodMajor, mNimrodMinor, mNimrodPatch, mCpuEndian, mNaN, 
-    mInf, mNegInf, mNLen, mNChild, mNSetChild, mNAdd, 
-    mNAddMultiple, mNDel, mNKind, mNIntVal, mNFloatVal, mNSymbol, 
-    mNIdent, mNGetType, mNStrVal, mNSetIntVal, mNSetFloatVal, mNSetSymbol, 
-    mNSetIdent, mNSetType, mNSetStrVal, mNNewNimNode, mNCopyNimNode, mNCopyNimTree, 
-    mStrToIdent, mIdentToStr, mEqIdent, mNHint, mNWarning, mNError
-    //[[[end]]]
-  );
-
-type
-  PNode = ^TNode;
-  PNodePtr = ^{@ptr}PNode;
-  TNodeSeq = array of PNode;
-
-  PType = ^TType;
-  PSym = ^TSym;
-
-  TNode = {@ignore} record // keep this below 32 bytes;
-                           // otherwise the AST grows too much
-    typ: PType;
-    strVal: string;
-    comment: string;
-    sons: TNodeSeq; // else!
-    info: TLineInfo;
-    flags: TNodeFlags;
-    case Kind: TNodeKind of
-      nkCharLit, nkIntLit, nkInt8Lit, nkInt16Lit, nkInt32Lit, nkInt64Lit:
-        (intVal: biggestInt);
-      nkFloatLit, nkFloat32Lit, nkFloat64Lit:
-        (floatVal: biggestFloat);
-      nkSym: (sym: PSym);
-      nkIdent: (ident: PIdent);
-      nkMetaNode: (nodePtr: PNodePtr);
-  end;
-  {@emit
-  record // keep this below 32 bytes; otherwise the AST grows too much
-    typ: PType;
-    comment: string;
-    info: TLineInfo;
-    flags: TNodeFlags;
-    case Kind: TNodeKind of
-      nkCharLit..nkInt64Lit:
-        (intVal: biggestInt);
-      nkFloatLit..nkFloat64Lit:
-        (floatVal: biggestFloat);
-      nkStrLit..nkTripleStrLit:
-        (strVal: string);
-      nkSym: (sym: PSym);
-      nkIdent: (ident: PIdent);
-      nkMetaNode: (nodePtr: PNodePtr);
-      else (sons: TNodeSeq);
-  end; }
-
-  TSymSeq = array of PSym;
-  TStrTable = object           // a table[PIdent] of PSym
-    counter: int;
-    data: TSymSeq;
-  end;
-
-// -------------- backend information -------------------------------
-
-  TLocKind = (
-    locNone,       // no location
-    locTemp,       // temporary location
-    locLocalVar,   // location is a local variable
-    locGlobalVar,  // location is a global variable
-    locParam,      // location is a parameter
-    locField,      // location is a record field
-    locArrayElem,  // location is an array element
-    locExpr,       // "location" is really an expression
-    locImmediate,  // location is an immediate value
-    locProc,       // location is a proc (an address of a procedure)
-    locData,       // location is a constant
-    locCall,       // location is a call expression
-    locOther       // location is something other
-  );
-  
-  TLocFlag = (
-    lfIndirect,    // backend introduced a pointer
-    lfNoDeepCopy,  // no need for a deep copy
-    lfNoDecl,      // do not declare it in C
-    lfDynamicLib,  // link symbol to dynamic library
-    lfHeader       // include header file for symbol
-  );
-
-  TStorageLoc = (
-    OnUnknown,     // location is unknown (stack, heap or static)
-    OnStack,       // location is on hardware stack
-    OnHeap         // location is on heap or global (reference counting needed)
-  );
-
-  TLocFlags = set of TLocFlag;
-  TLoc = record
-    k: TLocKind;    // kind of location
-    s: TStorageLoc;
-    flags: TLocFlags;  // location's flags
-    t: PType;       // type of location
-    r: PRope;       // rope value of location (code generators)
-    a: int;         // location's "address", i.e. slot for temporaries
-  end;
-
-// ---------------- end of backend information ------------------------------
-
-  TSym = object(TIdObj)      // symbols are identical iff they have the same
-                             // id!
-    kind: TSymKind;
-    typ: PType;
-    name: PIdent;
-    info: TLineInfo;
-    owner: PSym;
-    flags: TSymFlags;
-    magic: TMagic;
-    tab: TStrTable;          // interface table for modules
-    ast: PNode;              // syntax tree of proc, iterator, etc.:
-                             // the whole proc including header; this is used
-                             // for easy generation of proper error messages
-                             // for variant record fields the discriminant
-                             // expression
-    options: TOptions;
-    position: int;           // used for many different things:
-                             // for enum fields its position;
-                             // for fields its offset
-                             // for parameters its position
-                             // for a conditional:
-                             // 1 iff the symbol is defined, else 0
-                             // (or not in symbol table)
-    offset: int;             // offset of record field
-    loc: TLoc;
-    annex: PObject;          // additional fields (seldom used, so we use a
-                             // reference to another object to safe space)
-  end;
-
-  PTypeSeq = array of PType;
-  TType = object(TIdObj)     // types are identical iff they have the
-                             // same id; there may be multiple copies of a type
-                             // in memory!
-    kind: TTypeKind;         // kind of type
-    sons: PTypeSeq;          // base types, etc.
-    n: PNode;                // node for types:
-                             // for range types a nkRange node
-                             // for record types a nkRecord node
-                             // for enum types a list of symbols
-                             // else: unused
-    flags: TTypeFlags;       // flags of the type
-    callConv: TCallingConvention; // for procs
-    owner: PSym;             // the 'owner' of the type
-    sym: PSym;               // types have the sym associated with them
-                             // it is used for converting types to strings
-    size: BiggestInt;        // the size of the type in bytes
-                             // -1 means that the size is unkwown
-    align: int;              // the type's alignment requirements
-    containerID: int;        // used for type checking of generics
-    loc: TLoc;
-  end;
-
-  // these are not part of the syntax tree, but nevertherless inherit from TNode
-  TPair = record
-    key, val: PObject;
-  end;
-  TPairSeq = array of TPair;
-
-  TTable = record // the same as table[PObject] of PObject
-    counter: int;
-    data: TPairSeq;
-  end;
-
-  TIdPair = record
-    key: PIdObj;
-    val: PObject;
-  end;
-  TIdPairSeq = array of TIdPair;
-
-  TIdTable = record // the same as table[PIdent] of PObject
-    counter: int;
-    data: TIdPairSeq;
-  end;
-
-  TIdNodePair = record
-    key: PIdObj;
-    val: PNode;
-  end;
-  TIdNodePairSeq = array of TIdNodePair;
-
-  TIdNodeTable = record // the same as table[PIdObj] of PNode
-    counter: int;
-    data: TIdNodePairSeq;
-  end;
-
-  TNodePair = record
-    h: THash;   // because it is expensive to compute!
-    key: PNode;
-    val: PNode;
-  end;
-  TNodePairSeq = array of TNodePair;
-
-  TNodeTable = record // the same as table[PNode] of PNode;
-                      // nodes are compared by structure!
-    counter: int;
-    data: TNodePairSeq;
-  end;
-
-  TObjectSeq = array of PObject;
-
-  TObjectSet = record
-    counter: int;
-    data: TObjectSeq;
-  end;
-  TLibKind = (libHeader, libDynamic, libDynamicGenerated);
-  TLib = object(lists.TListEntry) // also misused for headers!
-    kind: TLibKind;
-    // needed for the backends:
-    name: PRope;
-    path: string;
-    syms: TObjectSet;
-  end;
-  PLib = ^TLib;
-
-const
-  OverloadableSyms = {@set}[skProc, skIterator, skConverter];
-
-const // "MagicToStr" array:
-  MagicToStr: array [TMagic] of string = (
-    //[[[cog
-    //for i in range(0, len(magics)-1):
-    //  cog.out("'%s', " % magics[i])
-    //  if (i+1) % 6 == 0: cog.outl("")
-    //cog.outl("'%s'" % magics[-1])
-    //]]]
-    'None', 'Defined', 'New', 'NewFinalize', 'Low', 'High', 
-    'SizeOf', 'RegisterFinalizer', 'Succ', 'Pred', 'Inc', 'Dec', 
-    'LengthOpenArray', 'LengthStr', 'LengthArray', 'LengthSeq', 'Incl', 'Excl', 
-    'Card', 'Ord', 'Chr', 'AddI', 'SubI', 'MulI', 
-    'DivI', 'ModI', 'AddI64', 'SubI64', 'MulI64', 'DivI64', 
-    'ModI64', 'ShrI', 'ShlI', 'BitandI', 'BitorI', 'BitxorI', 
-    'MinI', 'MaxI', 'ShrI64', 'ShlI64', 'BitandI64', 'BitorI64', 
-    'BitxorI64', 'MinI64', 'MaxI64', 'AddF64', 'SubF64', 'MulF64', 
-    'DivF64', 'MinF64', 'MaxF64', 'AddU', 'SubU', 'MulU', 
-    'DivU', 'ModU', 'AddU64', 'SubU64', 'MulU64', 'DivU64', 
-    'ModU64', 'EqI', 'LeI', 'LtI', 'EqI64', 'LeI64', 
-    'LtI64', 'EqF64', 'LeF64', 'LtF64', 'LeU', 'LtU', 
-    'LeU64', 'LtU64', 'EqEnum', 'LeEnum', 'LtEnum', 'EqCh', 
-    'LeCh', 'LtCh', 'EqB', 'LeB', 'LtB', 'EqRef', 
-    'EqProc', 'EqUntracedRef', 'LePtr', 'LtPtr', 'EqCString', 'Xor', 
-    'UnaryMinusI', 'UnaryMinusI64', 'AbsI', 'AbsI64', 'Not', 'UnaryPlusI', 
-    'BitnotI', 'UnaryPlusI64', 'BitnotI64', 'UnaryPlusF64', 'UnaryMinusF64', 'AbsF64', 
-    'Ze8ToI', 'Ze8ToI64', 'Ze16ToI', 'Ze16ToI64', 'Ze32ToI64', 'ZeIToI64', 
-    'ToU8', 'ToU16', 'ToU32', 'ToFloat', 'ToBiggestFloat', 'ToInt', 
-    'ToBiggestInt', 'CharToStr', 'BoolToStr', 'IntToStr', 'Int64ToStr', 'FloatToStr', 
-    'CStrToStr', 'StrToStr', 'And', 'Or', 'EqStr', 'LeStr', 
-    'LtStr', 'EqSet', 'LeSet', 'LtSet', 'MulSet', 'PlusSet', 
-    'MinusSet', 'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT', 'ConTArr', 
-    'ConTT', 'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'AppendSeqSeq', 
-    'InRange', 'InSet', 'Is', 'Asgn', 'Repr', 'Exit', 
-    'SetLengthStr', 'SetLengthSeq', 'Assert', 'Swap', 'IsNil', 'Array', 
-    'OpenArray', 'Range', 'Set', 'Seq', 'CompileDate', 'CompileTime', 
-    'NimrodVersion', 'NimrodMajor', 'NimrodMinor', 'NimrodPatch', 'CpuEndian', 'NaN', 
-    'Inf', 'NegInf', 'NLen', 'NChild', 'NSetChild', 'NAdd', 
-    'NAddMultiple', 'NDel', 'NKind', 'NIntVal', 'NFloatVal', 'NSymbol', 
-    'NIdent', 'NGetType', 'NStrVal', 'NSetIntVal', 'NSetFloatVal', 'NSetSymbol', 
-    'NSetIdent', 'NSetType', 'NSetStrVal', 'NNewNimNode', 'NCopyNimNode', 'NCopyNimTree', 
-    'StrToIdent', 'IdentToStr', 'EqIdent', 'NHint', 'NWarning', 'NError'
-    //[[[end]]]
-  );
-
-const
-  GenericTypes: TTypeKinds = {@set}[tyGeneric, tyGenericParam];
-
-  StructuralEquivTypes: TTypeKinds = {@set}[
-    tyEmptySet, tyArrayConstr, tyNil, tyTuple,
-    tyArray,
-    tySet,
-    tyRange,
-    tyPtr, tyRef,
-    tyVar,
-    tySequence,
-    tyProc, tyOpenArray
-  ];
-
-  ConcreteTypes: TTypeKinds = {@set}[
-  // types of the expr that may occur in::
-  // var x = expr
-    tyBool, tyChar, tyEnum, tyArray, tyObject, tySet, tyTuple,
-    tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc,
-    tyPointer, tyOpenArray,
-    tyString, tyCString,
-    tyInt..tyInt64,
-    tyFloat..tyFloat128
-  ];
-  ConstantDataTypes: TTypeKinds = {@set}[tyArray, tySet, tyTuple];
-  ExportableSymKinds = {@set}[skVar, skConst, skProc, skType,
-                              skIterator, skMacro, skTemplate, skConverter];
-  namePos = 0;
-  genericParamsPos = 1;
-  paramsPos = 2;
-  pragmasPos = 3;
-  codePos = 4;
-  resultPos = 5;
-
-function getID: int;
-procedure setID(id: int);
-
-// creator procs:
-function NewSym(symKind: TSymKind; Name: PIdent; owner: PSym): PSym;
-
-function NewType(kind: TTypeKind; owner: PSym): PType; overload;
-
-function newNode(kind: TNodeKind): PNode;
-function newIntNode(kind: TNodeKind; const intVal: BiggestInt): PNode;
-function newIntTypeNode(kind: TNodeKind; const intVal: BiggestInt;
-                        typ: PType): PNode;
-function newFloatNode(kind: TNodeKind; const floatVal: BiggestFloat): PNode;
-function newStrNode(kind: TNodeKind; const strVal: string): PNode;
-function newIdentNode(ident: PIdent; const info: TLineInfo): PNode;
-function newSymNode(sym: PSym): PNode;
-function newNodeI(kind: TNodeKind; const info: TLineInfo): PNode;
-function newNodeIT(kind: TNodeKind; const info: TLineInfo; typ: PType): PNode;
-
-procedure initStrTable(out x: TStrTable);
-procedure initTable(out x: TTable);
-procedure initIdTable(out x: TIdTable);
-procedure initObjectSet(out x: TObjectSet);
-procedure initIdNodeTable(out x: TIdNodeTable);
-procedure initNodeTable(out x: TNodeTable);
-
-// copy procs:
-function copyType(t: PType; owner: PSym): PType;
-function copySym(s: PSym; keepId: bool = false): PSym;
-procedure assignType(dest, src: PType);
-
-procedure copyStrTable(out dest: TStrTable; const src: TStrTable);
-procedure copyTable(out dest: TTable; const src: TTable);
-procedure copyObjectSet(out dest: TObjectSet; const src: TObjectSet);
-
-function sonsLen(n: PNode): int; overload;
-function sonsLen(n: PType): int; overload;
-
-function lastSon(n: PNode): PNode; overload;
-function lastSon(n: PType): PType; overload;
-procedure newSons(father: PNode; len: int); overload;
-procedure newSons(father: PType; len: int); overload;
-
-procedure addSon(father, son: PNode); overload;
-procedure addSon(father, son: PType); overload;
-
-procedure addSonIfNotNil(father, n: PNode);
-procedure delSon(father: PNode; idx: int);
-function hasSonWith(n: PNode; kind: TNodeKind): boolean;
-function hasSubnodeWith(n: PNode; kind: TNodeKind): boolean;
-procedure replaceSons(n: PNode; oldKind, newKind: TNodeKind);
-function sonsNotNil(n: PNode): bool; // for assertions
-
-function copyNode(src: PNode): PNode;
-// does not copy its sons!
-
-function copyTree(src: PNode): PNode;
-// does copy its sons!
-
-procedure discardSons(father: PNode);
-
-const // for all kind of hash tables:
-  GrowthFactor = 2; // must be power of 2, > 0
-  StartSize = 8;    // must be power of 2, > 0
-
-function SameValue(a, b: PNode): Boolean; // a, b are literals
-function leValue(a, b: PNode): Boolean; // a <= b? a, b are literals
-
-function ValueToString(a: PNode): string;
-
-implementation
-
-var
-  gId: int;
-
-function getID: int;
-begin
-  inc(gId);
-  result := gId
-end;
-
-procedure setId(id: int);
-begin
-  gId := max(gId, id)
-end;
-
-function leValue(a, b: PNode): Boolean; // a <= b?
-begin
-  result := false;
-  case a.kind of
-    nkCharLit..nkInt64Lit:
-      if b.kind in [nkCharLit..nkInt64Lit] then
-        result := a.intVal <= b.intVal;
-    nkFloatLit..nkFloat64Lit:
-      if b.kind in [nkFloatLit..nkFloat64Lit] then
-        result := a.floatVal <= b.floatVal;
-    nkStrLit..nkTripleStrLit: begin
-      if b.kind in [nkStrLit..nkTripleStrLit] then
-        result := a.strVal <= b.strVal;
-    end
-    else InternalError(a.info, 'leValue');
-  end
-end;
-
-function SameValue(a, b: PNode): Boolean;
-begin
-  result := false;
-  case a.kind of
-    nkCharLit..nkInt64Lit:
-      if b.kind in [nkCharLit..nkInt64Lit] then
-        result := a.intVal = b.intVal;
-    nkFloatLit..nkFloat64Lit:
-      if b.kind in [nkFloatLit..nkFloat64Lit] then
-        result := a.floatVal = b.floatVal;
-    nkStrLit..nkTripleStrLit: begin
-      if b.kind in [nkStrLit..nkTripleStrLit] then
-        result := a.strVal = b.strVal;
-    end
-    else InternalError(a.info, 'SameValue');
-  end
-end;
-
-function ValueToString(a: PNode): string;
-begin
-  case a.kind of
-    nkCharLit..nkInt64Lit:
-      result := ToString(a.intVal);
-    nkFloatLit, nkFloat32Lit, nkFloat64Lit:
-      result := toStringF(a.floatVal);
-    nkStrLit..nkTripleStrLit:
-      result := a.strVal;
-    else begin
-      InternalError(a.info, 'valueToString');
-      result := ''
-    end
-  end
-end;
-
-procedure copyStrTable(out dest: TStrTable; const src: TStrTable);
-var
-  i: int;
-begin
-  dest.counter := src.counter;
-{@emit
-  if isNil(src.data) then exit;
-}
-  setLength(dest.data, length(src.data));
-  for i := 0 to high(src.data) do
-    dest.data[i] := src.data[i];
-end;
-
-procedure copyTable(out dest: TTable; const src: TTable);
-var
-  i: int;
-begin
-  dest.counter := src.counter;
-{@emit
-  if isNil(src.data) then exit;
-}
-  setLength(dest.data, length(src.data));
-  for i := 0 to high(src.data) do
-    dest.data[i] := src.data[i];
-end;
-
-procedure copyObjectSet(out dest: TObjectSet; const src: TObjectSet);
-var
-  i: int;
-begin
-  dest.counter := src.counter;
-{@emit
-  if isNil(src.data) then exit;
-}
-  setLength(dest.data, length(src.data));
-  for i := 0 to high(src.data) do
-    dest.data[i] := src.data[i];
-end;
-
-procedure discardSons(father: PNode);
-begin
-  father.sons := nil;
-end;
-
-function newNode(kind: TNodeKind): PNode;
-begin
-  new(result);
-{@ignore}
-  FillChar(result^, sizeof(result^), 0);
-{@emit}
-  result.kind := kind;
-  result.info := UnknownLineInfo();
-end;
-
-function newIntNode(kind: TNodeKind; const intVal: BiggestInt): PNode;
-begin
-  result := newNode(kind);
-  result.intVal := intVal
-end;
-
-function newIntTypeNode(kind: TNodeKind; const intVal: BiggestInt;
-                        typ: PType): PNode;
-begin
-  result := newIntNode(kind, intVal);
-  result.typ := typ;
-end;
-
-function newFloatNode(kind: TNodeKind; const floatVal: BiggestFloat): PNode;
-begin
-  result := newNode(kind);
-  result.floatVal := floatVal
-end;
-
-function newStrNode(kind: TNodeKind; const strVal: string): PNode;
-begin
-  result := newNode(kind);
-  result.strVal := strVal
-end;
-
-function newIdentNode(ident: PIdent; const info: TLineInfo): PNode;
-begin
-  result := newNode(nkIdent);
-  result.ident := ident;
-  result.info := info;
-end;
-
-function newSymNode(sym: PSym): PNode;
-begin
-  result := newNode(nkSym);
-  result.sym := sym;
-  result.typ := sym.typ;
-  result.info := sym.info;
-end;
-
-function newNodeI(kind: TNodeKind; const info: TLineInfo): PNode;
-begin
-  result := newNode(kind);
-  result.info := info;
-end;
-
-function newNodeIT(kind: TNodeKind; const info: TLineInfo; typ: PType): PNode;
-begin
-  result := newNode(kind);
-  result.info := info;
-  result.typ := typ;
-end;
-
-function NewType(kind: TTypeKind; owner: PSym): PType; overload;
-begin
-  new(result);
-{@ignore}
-  FillChar(result^, sizeof(result^), 0);
-{@emit}
-  result.kind := kind;
-  result.owner := owner;
-  result.size := -1;
-  result.align := 2; // default alignment
-  result.id := getID()
-end;
-
-procedure assignType(dest, src: PType);
-var
-  i: int;
-begin
-  dest.kind := src.kind;
-  dest.flags := src.flags;
-  dest.callConv := src.callConv;
-  dest.n := src.n;
-  dest.size := src.size;
-  dest.align := src.align;
-  dest.containerID := src.containerID;
-  newSons(dest, sonsLen(src));
-  for i := 0 to sonsLen(src)-1 do 
-    dest.sons[i] := src.sons[i];
-end;
-
-function copyType(t: PType; owner: PSym): PType;
-begin
-  result := newType(t.Kind, owner);
-  assignType(result, t);
-  if owner = t.owner then result.id := t.id
-  else result.id := getID();
-  result.sym := t.sym;
-  // backend-info should not be copied
-end;
-
-function copySym(s: PSym; keepId: bool = false): PSym;
-begin
-  result := newSym(s.kind, s.name, s.owner);
-  result.ast := nil; // BUGFIX; was: s.ast which made problems
-  result.info := s.info;
-  result.typ := s.typ;
-  if keepId then result.id := s.id else result.id := getID();
-  result.flags := s.flags;
-  result.magic := s.magic;
-  copyStrTable(result.tab, s.tab);
-  result.options := s.options;
-  result.position := s.position;
-  result.loc := s.loc;
-  result.annex := s.annex; // BUGFIX
-end;
-
-function NewSym(symKind: TSymKind; Name: PIdent; owner: PSym): PSym;
-// generates a symbol and initializes the hash field too
-begin
-  new(result);
-{@ignore}
-  FillChar(result^, sizeof(result^), 0);
-{@emit}
-  result.Name := Name;
-  result.Kind := symKind;
-  result.flags := {@set}[];
-  result.info := UnknownLineInfo();
-  result.options := gOptions;
-  result.owner := owner;
-  result.offset := -1;
-  result.id := getID()
-end;
-
-procedure initStrTable(out x: TStrTable);
-begin
-  x.counter := 0;
-{@emit
-  x.data := []; }
-  setLength(x.data, startSize);
-{@ignore}
-  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);
-{@emit}
-end;
-
-procedure initTable(out x: TTable);
-begin
-  x.counter := 0;
-{@emit
-  x.data := []; }
-  setLength(x.data, startSize);
-{@ignore}
-  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);
-{@emit}
-end;
-
-procedure initIdTable(out x: TIdTable);
-begin
-  x.counter := 0;
-{@emit
-  x.data := []; }
-  setLength(x.data, startSize);
-{@ignore}
-  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);
-{@emit}
-end;
-
-procedure initObjectSet(out x: TObjectSet);
-begin
-  x.counter := 0;
-{@emit
-  x.data := []; }
-  setLength(x.data, startSize);
-{@ignore}
-  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);
-{@emit}
-end;
-
-procedure initIdNodeTable(out x: TIdNodeTable);
-begin
-  x.counter := 0;
-{@emit
-  x.data := []; }
-  setLength(x.data, startSize);
-{@ignore}
-  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);
-{@emit}
-end;
-
-procedure initNodeTable(out x: TNodeTable);
-begin
-  x.counter := 0;
-{@emit
-  x.data := []; }
-  setLength(x.data, startSize);
-{@ignore}
-  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);
-{@emit}
-end;
-
-function sonsLen(n: PType): int;
-begin
-  if n.sons = nil then result := 0
-  else result := length(n.sons)
-end;
-
-procedure newSons(father: PType; len: int);
-var
-  i, L: int;
-begin
-{@emit
-  if father.sons = nil then father.sons := []; }
-  L := length(father.sons);
-  setLength(father.sons, L + len);
-{@ignore}
-  for i := L to L+len-1 do father.sons[i] := nil // needed for FPC
-{@emit}
-end;
-
-procedure addSon(father, son: PType);
-var
-  L: int;
-begin
-{@emit
-  if father.sons = nil then father.sons := []; }
-  L := length(father.sons);
-  setLength(father.sons, L+1);
-  father.sons[L] := son;
-end;
-
-function sonsLen(n: PNode): int;
-begin
-  if n.sons = nil then result := 0
-  else result := length(n.sons)
-end;
-
-procedure newSons(father: PNode; len: int);
-var
-  i, L: int;
-begin
-{@emit
-  if father.sons = nil then father.sons := []; }
-  L := length(father.sons);
-  setLength(father.sons, L + len);
-{@ignore}
-  for i := L to L+len-1 do father.sons[i] := nil // needed for FPC
-{@emit}
-end;
-
-procedure addSon(father, son: PNode);
-var
-  L: int;
-begin
-{@emit
-  if father.sons = nil then father.sons := []; }
-  L := length(father.sons);
-  setLength(father.sons, L+1);
-  father.sons[L] := son;
-end;
-
-procedure delSon(father: PNode; idx: int);
-var
-  len, i: int;
-begin
-{@emit
-  if father.sons = nil then exit; }
-  len := sonsLen(father);
-  for i := idx to len-2 do
-    father.sons[i] := father.sons[i+1];
-  setLength(father.sons, len-1);
-end;
-
-function copyNode(src: PNode): PNode;
-// does not copy its sons!
-begin
-  if src = nil then begin result := nil; exit end;
-  result := newNode(src.kind);
-  result.info := src.info;
-  result.typ := src.typ;
-  result.flags := src.flags;
-  case src.Kind of
-    nkCharLit..nkInt64Lit:
-      result.intVal := src.intVal;
-    nkFloatLit, nkFloat32Lit, nkFloat64Lit:
-      result.floatVal := src.floatVal;
-    nkSym:
-      result.sym := src.sym;
-    nkIdent:
-      result.ident := src.ident;
-    nkStrLit..nkTripleStrLit:
-      result.strVal := src.strVal;
-    nkMetaNode:
-      result.nodePtr := src.nodePtr;
-    else begin end;
-  end;
-end;
-
-function copyTree(src: PNode): PNode;
-// copy a whole syntax tree; performs deep copying
-var
-  i: int;
-begin
-  if src = nil then begin result := nil; exit end;
-  result := newNode(src.kind);
-  result.info := src.info;
-  result.typ := src.typ;
-  result.flags := src.flags;
-  case src.Kind of
-    nkCharLit..nkInt64Lit:
-      result.intVal := src.intVal;
-    nkFloatLit, nkFloat32Lit, nkFloat64Lit:
-      result.floatVal := src.floatVal;
-    nkSym:
-      result.sym := src.sym;
-    nkIdent:
-      result.ident := src.ident;
-    nkStrLit..nkTripleStrLit:
-      result.strVal := src.strVal;
-    nkMetaNode:
-      result.nodePtr := src.nodePtr;
-    else begin
-      result.sons := nil;
-      newSons(result, sonsLen(src));
-      for i := 0 to sonsLen(src)-1 do
-        result.sons[i] := copyTree(src.sons[i]);
-    end;
-  end
-end;
-
-function lastSon(n: PNode): PNode;
-begin
-  result := n.sons[sonsLen(n)-1];
-end;
-
-function lastSon(n: PType): PType;
-begin
-  result := n.sons[sonsLen(n)-1];
-end;
-
-function hasSonWith(n: PNode; kind: TNodeKind): boolean;
-var
-  i: int;
-begin
-  for i := 0 to sonsLen(n)-1 do begin
-    if (n.sons[i] <> nil) and (n.sons[i].kind = kind) then begin
-      result := true; exit
-    end
-  end;
-  result := false
-end;
-
-function hasSubnodeWith(n: PNode; kind: TNodeKind): boolean;
-var
-  i: int;
-begin
-  case n.kind of
-    nkEmpty..nkNilLit: result := n.kind = kind;
-    else begin
-      for i := 0 to sonsLen(n)-1 do begin
-        if (n.sons[i] <> nil) and (n.sons[i].kind = kind)
-        or hasSubnodeWith(n.sons[i], kind) then begin
-          result := true; exit
-        end
-      end;
-      result := false
-    end
-  end
-end;
-
-procedure replaceSons(n: PNode; oldKind, newKind: TNodeKind);
-var
-  i: int;
-begin
-  for i := 0 to sonsLen(n)-1 do
-    if n.sons[i].kind = oldKind then n.sons[i].kind := newKind
-end;
-
-function sonsNotNil(n: PNode): bool;
-var
-  i: int;
-begin
-  for i := 0 to sonsLen(n)-1 do
-    if n.sons[i] = nil then begin result := false; exit end;
-  result := true
-end;
-
-procedure addSonIfNotNil(father, n: PNode);
-begin
-  if n <> nil then addSon(father, n)
-end;
-
-end.
+//

+//

+//           The Nimrod Compiler

+//        (c) Copyright 2008 Andreas Rumpf

+//

+//    See the file "copying.txt", included in this

+//    distribution, for details about the copyright.

+//

+unit ast;

+

+// abstract syntax tree + symbol table

+

+interface

+

+{$include 'config.inc'}

+

+uses

+  nsystem, charsets, msgs, hashes,

+  nversion, options, strutils, crc, ropes, idents, lists;

+

+const

+  ImportTablePos = 0;

+  ModuleTablePos = 1;

+

+type

+  TCallingConvention = (

+    ccDefault,   // proc has no explicit calling convention

+    ccStdCall,   // procedure is stdcall

+    ccCDecl,     // cdecl

+    ccSafeCall,  // safecall

+    ccSysCall,   // system call

+    ccInline,    // proc should be inlined

+    ccNoInline,  // proc should not be inlined

+    ccFastCall,  // fastcall (pass parameters in registers)

+    ccClosure,   // proc has a closure

+    ccNoConvention // needed for generating proper C procs sometimes

+  );

+

+const

+  CallingConvToStr: array [TCallingConvention] of string = (

+    '', 'stdcall', 'cdecl', 'safecall', 'syscall', 'inline', 'noinline',

+    'fastcall', 'closure', 'noconv');

+

+(*[[[cog

+def toEnum(name, elems, prefixlen=0):

+  body = ""

+  strs = ""

+  prefix = ""

+  counter = 0

+  for e in elems:

+    if counter % 4 == 0: prefix = "\n    "

+    else: prefix = ""

+    body = body + prefix + e + ', '

+    strs = strs + prefix + "'%s', " % e[prefixlen:]

+    counter = counter + 1

+

+  return ("type\n  T%s = (%s);\n  T%ss = set of T%s;\n"

+            % (name, body[:-2], name, name),

+          "const\n  %sToStr: array [T%s] of string = (%s);\n"

+            % (name, name, strs[:-2]))

+

+enums = eval(open("data/ast.yml").read())

+for key, val in enums.items():

+  (a, b) = toEnum(key, val)

+  cog.out(a)

+  cog.out(b)

+]]]*)

+type

+  TTypeFlag = (

+    tfVarargs, tfFinal, tfAcyclic, tfEnumHasWholes);

+  TTypeFlags = set of TTypeFlag;

+const

+  TypeFlagToStr: array [TTypeFlag] of string = (

+    'tfVarargs', 'tfFinal', 'tfAcyclic', 'tfEnumHasWholes');

+type

+  TTypeKind = (

+    tyNone, tyBool, tyChar, tyEmpty, 

+    tyArrayConstr, tyNil, tyGeneric, tyGenericInst, 

+    tyGenericParam, tyEnum, tyAnyEnum, tyArray, 

+    tyObject, tyTuple, tySet, tyRange, 

+    tyPtr, tyRef, tyVar, tySequence, 

+    tyProc, tyPointer, tyOpenArray, tyString, 

+    tyCString, tyForward, tyInt, tyInt8, 

+    tyInt16, tyInt32, tyInt64, tyFloat, 

+    tyFloat32, tyFloat64, tyFloat128);

+  TTypeKinds = set of TTypeKind;

+const

+  TypeKindToStr: array [TTypeKind] of string = (

+    'tyNone', 'tyBool', 'tyChar', 'tyEmpty', 

+    'tyArrayConstr', 'tyNil', 'tyGeneric', 'tyGenericInst', 

+    'tyGenericParam', 'tyEnum', 'tyAnyEnum', 'tyArray', 

+    'tyObject', 'tyTuple', 'tySet', 'tyRange', 

+    'tyPtr', 'tyRef', 'tyVar', 'tySequence', 

+    'tyProc', 'tyPointer', 'tyOpenArray', 'tyString', 

+    'tyCString', 'tyForward', 'tyInt', 'tyInt8', 

+    'tyInt16', 'tyInt32', 'tyInt64', 'tyFloat', 

+    'tyFloat32', 'tyFloat64', 'tyFloat128');

+type

+  TSymFlag = (

+    sfUsed, sfStar, sfMinus, sfInInterface, 

+    sfFromGeneric, sfGlobal, sfForward, sfImportc, 

+    sfExportc, sfVolatile, sfRegister, sfPure, 

+    sfResult, sfNoSideEffect, sfMainModule, sfSystemModule, 

+    sfNoReturn, sfAddrTaken, sfCompilerProc, sfCppMethod, 

+    sfDiscriminant, sfDeprecated, sfInClosure, sfTypeCheck, 

+    sfCompileTime, sfThreadVar, sfMerge);

+  TSymFlags = set of TSymFlag;

+const

+  SymFlagToStr: array [TSymFlag] of string = (

+    'sfUsed', 'sfStar', 'sfMinus', 'sfInInterface', 

+    'sfFromGeneric', 'sfGlobal', 'sfForward', 'sfImportc', 

+    'sfExportc', 'sfVolatile', 'sfRegister', 'sfPure', 

+    'sfResult', 'sfNoSideEffect', 'sfMainModule', 'sfSystemModule', 

+    'sfNoReturn', 'sfAddrTaken', 'sfCompilerProc', 'sfCppMethod', 

+    'sfDiscriminant', 'sfDeprecated', 'sfInClosure', 'sfTypeCheck', 

+    'sfCompileTime', 'sfThreadVar', 'sfMerge');

+type

+  TNodeFlag = (

+    nfNone, nfBase2, nfBase8, nfBase16, 

+    nfAllConst, nfTransf, nfSem);

+  TNodeFlags = set of TNodeFlag;

+const

+  NodeFlagToStr: array [TNodeFlag] of string = (

+    'nfNone', 'nfBase2', 'nfBase8', 'nfBase16', 

+    'nfAllConst', 'nfTransf', 'nfSem');

+type

+  TSymKind = (

+    skUnknownSym, skConditional, skDynLib, skParam, 

+    skTypeParam, skTemp, skType, skConst, 

+    skVar, skProc, skIterator, skConverter, 

+    skMacro, skTemplate, skField, skEnumField, 

+    skForVar, skModule, skLabel, skStub);

+  TSymKinds = set of TSymKind;

+const

+  SymKindToStr: array [TSymKind] of string = (

+    'skUnknownSym', 'skConditional', 'skDynLib', 'skParam', 

+    'skTypeParam', 'skTemp', 'skType', 'skConst', 

+    'skVar', 'skProc', 'skIterator', 'skConverter', 

+    'skMacro', 'skTemplate', 'skField', 'skEnumField', 

+    'skForVar', 'skModule', 'skLabel', 'skStub');

+type

+  TNodeKind = (

+    nkNone, nkEmpty, nkIdent, nkSym, 

+    nkType, nkCharLit, nkIntLit, nkInt8Lit, 

+    nkInt16Lit, nkInt32Lit, nkInt64Lit, nkFloatLit, 

+    nkFloat32Lit, nkFloat64Lit, nkStrLit, nkRStrLit, 

+    nkTripleStrLit, nkMetaNode, nkNilLit, nkDotCall, 

+    nkCommand, nkCall, nkGenericCall, nkExplicitTypeListCall, 

+    nkExprEqExpr, nkExprColonExpr, nkIdentDefs, nkInfix, 

+    nkPrefix, nkPostfix, nkPar, nkCurly, 

+    nkBracket, nkBracketExpr, nkPragmaExpr, nkRange, 

+    nkDotExpr, nkCheckedFieldExpr, nkDerefExpr, nkIfExpr, 

+    nkElifExpr, nkElseExpr, nkLambda, nkAccQuoted, 

+    nkHeaderQuoted, nkTableConstr, nkQualified, nkHiddenStdConv, 

+    nkHiddenSubConv, nkHiddenCallConv, nkConv, nkCast, 

+    nkAddr, nkHiddenAddr, nkHiddenDeref, nkObjDownConv, 

+    nkObjUpConv, nkChckRangeF, nkChckRange64, nkChckRange, 

+    nkStringToCString, nkCStringToString, nkPassAsOpenArray, nkAsgn, 

+    nkDefaultTypeParam, nkGenericParams, nkFormalParams, nkOfInherit, 

+    nkModule, nkProcDef, nkConverterDef, nkMacroDef, 

+    nkTemplateDef, nkIteratorDef, nkOfBranch, nkElifBranch, 

+    nkExceptBranch, nkElse, nkMacroStmt, nkAsmStmt, 

+    nkPragma, nkIfStmt, nkWhenStmt, nkForStmt, 

+    nkWhileStmt, nkCaseStmt, nkVarSection, nkConstSection, 

+    nkConstDef, nkTypeSection, nkTypeDef, nkYieldStmt, 

+    nkTryStmt, nkFinally, nkRaiseStmt, nkReturnStmt, 

+    nkBreakStmt, nkContinueStmt, nkBlockStmt, nkDiscardStmt, 

+    nkStmtList, nkImportStmt, nkFromStmt, nkImportAs, 

+    nkIncludeStmt, nkAccessStmt, nkCommentStmt, nkStmtListExpr, 

+    nkBlockExpr, nkStmtListType, nkBlockType, nkVm, 

+    nkTypeOfExpr, nkObjectTy, nkTupleTy, nkRecList, 

+    nkRecCase, nkRecWhen, nkRefTy, nkPtrTy, 

+    nkVarTy, nkProcTy, nkEnumTy, nkEnumFieldDef, 

+    nkReturnToken);

+  TNodeKinds = set of TNodeKind;

+const

+  NodeKindToStr: array [TNodeKind] of string = (

+    'nkNone', 'nkEmpty', 'nkIdent', 'nkSym', 

+    'nkType', 'nkCharLit', 'nkIntLit', 'nkInt8Lit', 

+    'nkInt16Lit', 'nkInt32Lit', 'nkInt64Lit', 'nkFloatLit', 

+    'nkFloat32Lit', 'nkFloat64Lit', 'nkStrLit', 'nkRStrLit', 

+    'nkTripleStrLit', 'nkMetaNode', 'nkNilLit', 'nkDotCall', 

+    'nkCommand', 'nkCall', 'nkGenericCall', 'nkExplicitTypeListCall', 

+    'nkExprEqExpr', 'nkExprColonExpr', 'nkIdentDefs', 'nkInfix', 

+    'nkPrefix', 'nkPostfix', 'nkPar', 'nkCurly', 

+    'nkBracket', 'nkBracketExpr', 'nkPragmaExpr', 'nkRange', 

+    'nkDotExpr', 'nkCheckedFieldExpr', 'nkDerefExpr', 'nkIfExpr', 

+    'nkElifExpr', 'nkElseExpr', 'nkLambda', 'nkAccQuoted', 

+    'nkHeaderQuoted', 'nkTableConstr', 'nkQualified', 'nkHiddenStdConv', 

+    'nkHiddenSubConv', 'nkHiddenCallConv', 'nkConv', 'nkCast', 

+    'nkAddr', 'nkHiddenAddr', 'nkHiddenDeref', 'nkObjDownConv', 

+    'nkObjUpConv', 'nkChckRangeF', 'nkChckRange64', 'nkChckRange', 

+    'nkStringToCString', 'nkCStringToString', 'nkPassAsOpenArray', 'nkAsgn', 

+    'nkDefaultTypeParam', 'nkGenericParams', 'nkFormalParams', 'nkOfInherit', 

+    'nkModule', 'nkProcDef', 'nkConverterDef', 'nkMacroDef', 

+    'nkTemplateDef', 'nkIteratorDef', 'nkOfBranch', 'nkElifBranch', 

+    'nkExceptBranch', 'nkElse', 'nkMacroStmt', 'nkAsmStmt', 

+    'nkPragma', 'nkIfStmt', 'nkWhenStmt', 'nkForStmt', 

+    'nkWhileStmt', 'nkCaseStmt', 'nkVarSection', 'nkConstSection', 

+    'nkConstDef', 'nkTypeSection', 'nkTypeDef', 'nkYieldStmt', 

+    'nkTryStmt', 'nkFinally', 'nkRaiseStmt', 'nkReturnStmt', 

+    'nkBreakStmt', 'nkContinueStmt', 'nkBlockStmt', 'nkDiscardStmt', 

+    'nkStmtList', 'nkImportStmt', 'nkFromStmt', 'nkImportAs', 

+    'nkIncludeStmt', 'nkAccessStmt', 'nkCommentStmt', 'nkStmtListExpr', 

+    'nkBlockExpr', 'nkStmtListType', 'nkBlockType', 'nkVm', 

+    'nkTypeOfExpr', 'nkObjectTy', 'nkTupleTy', 'nkRecList', 

+    'nkRecCase', 'nkRecWhen', 'nkRefTy', 'nkPtrTy', 

+    'nkVarTy', 'nkProcTy', 'nkEnumTy', 'nkEnumFieldDef', 

+    'nkReturnToken');

+{[[[end]]]}

+

+type

+  // symbols that require compiler magic:

+  TMagic = (

+    //[[[cog

+    //magics = eval(open("data/magic.yml").read())

+    //for i in range(0, len(magics)-1):

+    //  cog.out("m" + magics[i] + ", ")

+    //  if (i+1) % 6 == 0: cog.outl("")

+    //cog.outl("m" + magics[-1])

+    //]]]

+    mNone, mDefined, mLow, mHigh, mSizeOf, mIs, 

+    mSucc, mPred, mInc, mDec, mOrd, mNew, 

+    mNewFinalize, mNewSeq, mRegisterFinalizer, mLengthOpenArray, mLengthStr, mLengthArray, 

+    mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref, 

+    mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, 

+    mAddI64, mSubI64, mMulI64, mDivI64, mModI64, mShrI, 

+    mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, 

+    mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, 

+    mMaxI64, mAddF64, mSubF64, mMulF64, mDivF64, mMinF64, 

+    mMaxF64, mAddU, mSubU, mMulU, mDivU, mModU, 

+    mAddU64, mSubU64, mMulU64, mDivU64, mModU64, mEqI, 

+    mLeI, mLtI, mEqI64, mLeI64, mLtI64, mEqF64, 

+    mLeF64, mLtF64, mLeU, mLtU, mLeU64, mLtU64, 

+    mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, 

+    mEqB, mLeB, mLtB, mEqRef, mEqProc, mEqUntracedRef, 

+    mLePtr, mLtPtr, mEqCString, mXor, mUnaryMinusI, mUnaryMinusI64, 

+    mAbsI, mAbsI64, mNot, mUnaryPlusI, mBitnotI, mUnaryPlusI64, 

+    mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, mZe8ToI64, 

+    mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, mToU16, 

+    mToU32, mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, mCharToStr, 

+    mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, 

+    mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, 

+    mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mSymDiffSet, 

+    mConStrStr, mConArrArr, mConArrT, mConTArr, mConTT, mSlice, 

+    mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq, mInRange, mInSet, 

+    mAsgn, mRepr, mExit, mSetLengthStr, mSetLengthSeq, mAssert, 

+    mSwap, mIsNil, mArrToSeq, mArray, mOpenArray, mRange, 

+    mSet, mSeq, mInt, mInt8, mInt16, mInt32, 

+    mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, 

+    mString, mCstring, mPointer, mAnyEnum, mEmptySet, mIntSetBaseType, 

+    mNil, mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor, 

+    mNimrodMinor, mNimrodPatch, mCpuEndian, mNaN, mInf, mNegInf, 

+    mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, 

+    mNKind, mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, 

+    mNStrVal, mNSetIntVal, mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, 

+    mNSetStrVal, mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr, 

+    mEqIdent, mNHint, mNWarning, mNError

+    //[[[end]]]

+  );

+

+type

+  PNode = ^TNode;

+  PNodePtr = ^{@ptr}PNode;

+  TNodeSeq = array of PNode;

+

+  PType = ^TType;

+  PSym = ^TSym;

+

+  TNode = {@ignore} record

+    typ: PType;

+    strVal: string;

+    comment: string;

+    sons: TNodeSeq; // else!

+    info: TLineInfo;

+    flags: TNodeFlags;

+    case Kind: TNodeKind of

+      nkCharLit, nkIntLit, nkInt8Lit, nkInt16Lit, nkInt32Lit, nkInt64Lit:

+        (intVal: biggestInt);

+      nkFloatLit, nkFloat32Lit, nkFloat64Lit:

+        (floatVal: biggestFloat);

+      nkSym: (sym: PSym);

+      nkIdent: (ident: PIdent);

+      nkMetaNode: (nodePtr: PNodePtr);

+  end;

+  {@emit

+  record // on a 32bit machine, this takes 32 bytes

+    typ: PType;

+    comment: string;

+    info: TLineInfo;

+    flags: TNodeFlags;

+    case Kind: TNodeKind of

+      nkCharLit..nkInt64Lit:

+        (intVal: biggestInt);

+      nkFloatLit..nkFloat64Lit:

+        (floatVal: biggestFloat);

+      nkStrLit..nkTripleStrLit:

+        (strVal: string);

+      nkSym: (sym: PSym);

+      nkIdent: (ident: PIdent);

+      nkMetaNode: (nodePtr: PNodePtr);

+      else (sons: TNodeSeq);

+  end acyclic; }

+

+  TSymSeq = array of PSym;

+  TStrTable = object           // a table[PIdent] of PSym

+    counter: int;

+    data: TSymSeq;

+  end;

+

+// -------------- backend information -------------------------------

+

+  TLocKind = (

+    locNone,       // no location

+    locTemp,       // temporary location

+    locLocalVar,   // location is a local variable

+    locGlobalVar,  // location is a global variable

+    locParam,      // location is a parameter

+    locField,      // location is a record field

+    locArrayElem,  // location is an array element

+    locExpr,       // "location" is really an expression

+    locImmediate,  // location is an immediate value

+    locProc,       // location is a proc (an address of a procedure)

+    locData,       // location is a constant

+    locCall,       // location is a call expression

+    locOther       // location is something other

+  );

+

+  TLocFlag = (

+    lfIndirect,    // backend introduced a pointer

+    lfNoDeepCopy,  // no need for a deep copy

+    lfNoDecl,      // do not declare it in C

+    lfDynamicLib,  // link symbol to dynamic library

+    lfHeader       // include header file for symbol

+  );

+

+  TStorageLoc = (

+    OnUnknown,     // location is unknown (stack, heap or static)

+    OnStack,       // location is on hardware stack

+    OnHeap         // location is on heap or global (reference counting needed)

+  );

+

+  TLocFlags = set of TLocFlag;

+  TLoc = record

+    k: TLocKind;    // kind of location

+    s: TStorageLoc;

+    flags: TLocFlags;  // location's flags

+    t: PType;       // type of location

+    r: PRope;       // rope value of location (code generators)

+    a: int;         // location's "address", i.e. slot for temporaries

+  end;

+

+// ---------------- end of backend information ------------------------------

+  TLibKind = (libHeader, libDynamic, libDynamicGenerated);

+  TLib = object(lists.TListEntry) // also misused for headers!

+    kind: TLibKind;

+    // needed for the backends:

+    name: PRope;

+    path: string;

+  end;

+  PLib = ^TLib;

+

+  TSym = object(TIdObj)      // symbols are identical iff they have the same

+                             // id!

+    kind: TSymKind;

+    magic: TMagic;

+    typ: PType;

+    name: PIdent;

+    info: TLineInfo;

+    owner: PSym;

+    flags: TSymFlags;

+    tab: TStrTable;          // interface table for modules

+    ast: PNode;              // syntax tree of proc, iterator, etc.:

+                             // the whole proc including header; this is used

+                             // for easy generation of proper error messages

+                             // for variant record fields the discriminant

+                             // expression

+    options: TOptions;

+    position: int;           // used for many different things:

+                             // for enum fields its position;

+                             // for fields its offset

+                             // for parameters its position

+                             // for a conditional:

+                             // 1 iff the symbol is defined, else 0

+                             // (or not in symbol table)

+    offset: int;             // offset of record field

+    loc: TLoc;

+    annex: PLib;             // additional fields (seldom used, so we use a

+                             // reference to another object to safe space)

+  end;

+

+  TTypeSeq = array of PType;

+  TType = object(TIdObj)     // types are identical iff they have the

+                             // same id; there may be multiple copies of a type

+                             // in memory!

+    kind: TTypeKind;         // kind of type

+    sons: TTypeSeq;          // base types, etc.

+    n: PNode;                // node for types:

+                             // for range types a nkRange node

+                             // for record types a nkRecord node

+                             // for enum types a list of symbols

+                             // else: unused

+    flags: TTypeFlags;       // flags of the type

+    callConv: TCallingConvention; // for procs

+    owner: PSym;             // the 'owner' of the type

+    sym: PSym;               // types have the sym associated with them

+                             // it is used for converting types to strings

+    size: BiggestInt;        // the size of the type in bytes

+                             // -1 means that the size is unkwown

+    align: int;              // the type's alignment requirements

+    containerID: int;        // used for type checking of generics

+    loc: TLoc;

+  end;

+

+  // these are not part of the syntax tree, but nevertherless inherit from TNode

+  TPair = record

+    key, val: PObject;

+  end;

+  TPairSeq = array of TPair;

+

+  TTable = record // the same as table[PObject] of PObject

+    counter: int;

+    data: TPairSeq;

+  end;

+

+  TIdPair = record

+    key: PIdObj;

+    val: PObject;

+  end;

+  TIdPairSeq = array of TIdPair;

+

+  TIdTable = record // the same as table[PIdent] of PObject

+    counter: int;

+    data: TIdPairSeq;

+  end;

+

+  TIdNodePair = record

+    key: PIdObj;

+    val: PNode;

+  end;

+  TIdNodePairSeq = array of TIdNodePair;

+

+  TIdNodeTable = record // the same as table[PIdObj] of PNode

+    counter: int;

+    data: TIdNodePairSeq;

+  end;

+

+  TNodePair = record

+    h: THash;   // because it is expensive to compute!

+    key: PNode;

+    val: int;

+  end;

+  TNodePairSeq = array of TNodePair;

+

+  TNodeTable = record // the same as table[PNode] of int;

+                      // nodes are compared by structure!

+    counter: int;

+    data: TNodePairSeq;

+  end;

+

+  TObjectSeq = array of PObject;

+

+  TObjectSet = record

+    counter: int;

+    data: TObjectSeq;

+  end;

+

+const

+  OverloadableSyms = {@set}[skProc, skIterator, skConverter];

+

+const // "MagicToStr" array:

+  MagicToStr: array [TMagic] of string = (

+    //[[[cog

+    //for i in range(0, len(magics)-1):

+    //  cog.out("'%s', " % magics[i])

+    //  if (i+1) % 6 == 0: cog.outl("")

+    //cog.outl("'%s'" % magics[-1])

+    //]]]

+    'None', 'Defined', 'Low', 'High', 'SizeOf', 'Is', 

+    'Succ', 'Pred', 'Inc', 'Dec', 'Ord', 'New', 

+    'NewFinalize', 'NewSeq', 'RegisterFinalizer', 'LengthOpenArray', 'LengthStr', 'LengthArray', 

+    'LengthSeq', 'Incl', 'Excl', 'Card', 'Chr', 'GCref', 

+    'GCunref', 'AddI', 'SubI', 'MulI', 'DivI', 'ModI', 

+    'AddI64', 'SubI64', 'MulI64', 'DivI64', 'ModI64', 'ShrI', 

+    'ShlI', 'BitandI', 'BitorI', 'BitxorI', 'MinI', 'MaxI', 

+    'ShrI64', 'ShlI64', 'BitandI64', 'BitorI64', 'BitxorI64', 'MinI64', 

+    'MaxI64', 'AddF64', 'SubF64', 'MulF64', 'DivF64', 'MinF64', 

+    'MaxF64', 'AddU', 'SubU', 'MulU', 'DivU', 'ModU', 

+    'AddU64', 'SubU64', 'MulU64', 'DivU64', 'ModU64', 'EqI', 

+    'LeI', 'LtI', 'EqI64', 'LeI64', 'LtI64', 'EqF64', 

+    'LeF64', 'LtF64', 'LeU', 'LtU', 'LeU64', 'LtU64', 

+    'EqEnum', 'LeEnum', 'LtEnum', 'EqCh', 'LeCh', 'LtCh', 

+    'EqB', 'LeB', 'LtB', 'EqRef', 'EqProc', 'EqUntracedRef', 

+    'LePtr', 'LtPtr', 'EqCString', 'Xor', 'UnaryMinusI', 'UnaryMinusI64', 

+    'AbsI', 'AbsI64', 'Not', 'UnaryPlusI', 'BitnotI', 'UnaryPlusI64', 

+    'BitnotI64', 'UnaryPlusF64', 'UnaryMinusF64', 'AbsF64', 'Ze8ToI', 'Ze8ToI64', 

+    'Ze16ToI', 'Ze16ToI64', 'Ze32ToI64', 'ZeIToI64', 'ToU8', 'ToU16', 

+    'ToU32', 'ToFloat', 'ToBiggestFloat', 'ToInt', 'ToBiggestInt', 'CharToStr', 

+    'BoolToStr', 'IntToStr', 'Int64ToStr', 'FloatToStr', 'CStrToStr', 'StrToStr', 

+    'And', 'Or', 'EqStr', 'LeStr', 'LtStr', 'EqSet', 

+    'LeSet', 'LtSet', 'MulSet', 'PlusSet', 'MinusSet', 'SymDiffSet', 

+    'ConStrStr', 'ConArrArr', 'ConArrT', 'ConTArr', 'ConTT', 'Slice', 

+    'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'AppendSeqSeq', 'InRange', 'InSet', 

+    'Asgn', 'Repr', 'Exit', 'SetLengthStr', 'SetLengthSeq', 'Assert', 

+    'Swap', 'IsNil', 'ArrToSeq', 'Array', 'OpenArray', 'Range', 

+    'Set', 'Seq', 'Int', 'Int8', 'Int16', 'Int32', 

+    'Int64', 'Float', 'Float32', 'Float64', 'Bool', 'Char', 

+    'String', 'Cstring', 'Pointer', 'AnyEnum', 'EmptySet', 'IntSetBaseType', 

+    'Nil', 'IsMainModule', 'CompileDate', 'CompileTime', 'NimrodVersion', 'NimrodMajor', 

+    'NimrodMinor', 'NimrodPatch', 'CpuEndian', 'NaN', 'Inf', 'NegInf', 

+    'NLen', 'NChild', 'NSetChild', 'NAdd', 'NAddMultiple', 'NDel', 

+    'NKind', 'NIntVal', 'NFloatVal', 'NSymbol', 'NIdent', 'NGetType', 

+    'NStrVal', 'NSetIntVal', 'NSetFloatVal', 'NSetSymbol', 'NSetIdent', 'NSetType', 

+    'NSetStrVal', 'NNewNimNode', 'NCopyNimNode', 'NCopyNimTree', 'StrToIdent', 'IdentToStr', 

+    'EqIdent', 'NHint', 'NWarning', 'NError'

+    //[[[end]]]

+  );

+

+const

+  GenericTypes: TTypeKinds = {@set}[tyGeneric, tyGenericParam];

+

+  StructuralEquivTypes: TTypeKinds = {@set}[

+    tyArrayConstr, tyNil, tyTuple,

+    tyArray,

+    tySet,

+    tyRange,

+    tyPtr, tyRef,

+    tyVar,

+    tySequence,

+    tyProc, tyOpenArray

+  ];

+

+  ConcreteTypes: TTypeKinds = {@set}[

+  // types of the expr that may occur in::

+  // var x = expr

+    tyBool, tyChar, tyEnum, tyArray, tyObject, tySet, tyTuple,

+    tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc,

+    tyPointer, tyOpenArray,

+    tyString, tyCString,

+    tyInt..tyInt64,

+    tyFloat..tyFloat128

+  ];

+  ConstantDataTypes: TTypeKinds = {@set}[tyArray, tySet, tyTuple];

+  ExportableSymKinds = {@set}[skVar, skConst, skProc, skType,

+                              skIterator, skMacro, skTemplate, skConverter,

+                              skStub];

+  PersistentNodeFlags: TNodeFlags = {@set}[

+    nfBase2, nfBase8, nfBase16, nfAllConst];

+  namePos = 0;

+  genericParamsPos = 1;

+  paramsPos = 2;

+  pragmasPos = 3;

+  codePos = 4;

+  resultPos = 5;

+

+var

+  gId: int;

+

+function getID: int;

+procedure setID(id: int);

+procedure IDsynchronizationPoint(idRange: int);

+

+// creator procs:

+function NewSym(symKind: TSymKind; Name: PIdent; owner: PSym): PSym;

+

+function NewType(kind: TTypeKind; owner: PSym): PType; overload;

+

+function newNode(kind: TNodeKind): PNode;

+function newIntNode(kind: TNodeKind; const intVal: BiggestInt): PNode;

+function newIntTypeNode(kind: TNodeKind; const intVal: BiggestInt;

+                        typ: PType): PNode;

+function newFloatNode(kind: TNodeKind; const floatVal: BiggestFloat): PNode;

+function newStrNode(kind: TNodeKind; const strVal: string): PNode;

+function newIdentNode(ident: PIdent; const info: TLineInfo): PNode;

+function newSymNode(sym: PSym): PNode;

+function newNodeI(kind: TNodeKind; const info: TLineInfo): PNode;

+function newNodeIT(kind: TNodeKind; const info: TLineInfo; typ: PType): PNode;

+

+procedure initStrTable(out x: TStrTable);

+procedure initTable(out x: TTable);

+procedure initIdTable(out x: TIdTable);

+procedure initObjectSet(out x: TObjectSet);

+procedure initIdNodeTable(out x: TIdNodeTable);

+procedure initNodeTable(out x: TNodeTable);

+

+// copy procs:

+function copyType(t: PType; owner: PSym; keepId: bool): PType;

+function copySym(s: PSym; keepId: bool = false): PSym;

+procedure assignType(dest, src: PType);

+

+procedure copyStrTable(out dest: TStrTable; const src: TStrTable);

+procedure copyTable(out dest: TTable; const src: TTable);

+procedure copyObjectSet(out dest: TObjectSet; const src: TObjectSet);

+procedure copyIdTable(var dest: TIdTable; const src: TIdTable);

+

+function sonsLen(n: PNode): int; overload; 

+function sonsLen(n: PType): int; overload; 

+

+function lastSon(n: PNode): PNode; overload;

+function lastSon(n: PType): PType; overload;

+procedure newSons(father: PNode; len: int); overload;

+procedure newSons(father: PType; len: int); overload;

+

+procedure addSon(father, son: PNode); overload;

+procedure addSon(father, son: PType); overload;

+

+procedure addSonIfNotNil(father, n: PNode);

+procedure delSon(father: PNode; idx: int);

+function hasSonWith(n: PNode; kind: TNodeKind): boolean;

+function hasSubnodeWith(n: PNode; kind: TNodeKind): boolean;

+procedure replaceSons(n: PNode; oldKind, newKind: TNodeKind);

+function sonsNotNil(n: PNode): bool; // for assertions

+

+function copyNode(src: PNode): PNode;

+// does not copy its sons!

+

+function copyTree(src: PNode): PNode;

+// does copy its sons!

+

+procedure discardSons(father: PNode);

+

+const // for all kind of hash tables:

+  GrowthFactor = 2; // must be power of 2, > 0

+  StartSize = 8;    // must be power of 2, > 0

+

+function SameValue(a, b: PNode): Boolean; // a, b are literals

+function leValue(a, b: PNode): Boolean; // a <= b? a, b are literals

+

+function ValueToString(a: PNode): string;

+

+// ------------- efficient integer sets -------------------------------------

+const

+  IntsPerTrunk = 8;

+  InitIntSetSize = 8; // must be a power of two!

+  BitsPerTrunk = IntsPerTrunk * sizeof(int) * 8;

+  BitsPerInt = sizeof(int) * 8;

+

+type

+  PTrunk = ^TTrunk;

+  TTrunk = record

+    next: PTrunk; // all nodes are connected with this pointer

+    key: int;    // start address at bit 0

+    bits: array [0..IntsPerTrunk-1] of int; // a bit vector

+  end;

+  TTrunkSeq = array of PTrunk;

+  TIntSet = record

+    counter, max: int;

+    head: PTrunk;

+    data: TTrunkSeq;

+  end;

+

+function IntSetContains(const s: TIntSet; key: int): bool;

+procedure IntSetIncl(var s: TIntSet; key: int);

+procedure IntSetInit(var s: TIntSet);

+

+function IntSetContainsOrIncl(var s: TIntSet; key: int): bool;

+

+

+const

+  debugIds = false;

+

+procedure registerID(id: PIdObj);

+

+// owner handling:

+function getCurrOwner(): PSym;

+procedure PushOwner(owner: PSym);

+procedure PopOwner;

+

+implementation

+

+var

+  gOwners: array of PSym; // owner stack (used for initializing the

+                          // owner field of syms)

+                          // the documentation comment always gets

+                          // assigned to the current owner

+                          // BUGFIX: global array is needed!

+{@emit gOwners := @[]; }

+

+function getCurrOwner(): PSym;

+begin

+  result := gOwners[high(gOwners)];

+end;

+

+procedure PushOwner(owner: PSym);

+var

+  len: int;

+begin

+  len := length(gOwners);

+  setLength(gOwners, len+1);

+  gOwners[len] := owner;

+end;

+

+procedure PopOwner;

+var

+  len: int;

+begin

+  len := length(gOwners);

+  if (len <= 0) then InternalError('popOwner');

+  setLength(gOwners, len - 1);

+end;

+

+var

+  usedIds: TIntSet;

+

+procedure registerID(id: PIdObj);

+begin

+  if debugIDs then

+    if (id.id = -1) or IntSetContainsOrIncl(usedIds, id.id) then

+      InternalError('ID already used: ' + toString(id.id));

+end;

+

+function getID: int;

+begin

+  result := gId;

+  inc(gId)

+end;

+

+procedure setId(id: int);

+begin

+  gId := max(gId, id+1);

+end;

+

+procedure IDsynchronizationPoint(idRange: int);

+begin

+  gId := (gId div IdRange +1) * IdRange + 1;

+end;

+

+function leValue(a, b: PNode): Boolean; // a <= b?

+begin

+  result := false;

+  case a.kind of

+    nkCharLit..nkInt64Lit:

+      if b.kind in [nkCharLit..nkInt64Lit] then

+        result := a.intVal <= b.intVal;

+    nkFloatLit..nkFloat64Lit:

+      if b.kind in [nkFloatLit..nkFloat64Lit] then

+        result := a.floatVal <= b.floatVal;

+    nkStrLit..nkTripleStrLit: begin

+      if b.kind in [nkStrLit..nkTripleStrLit] then

+        result := a.strVal <= b.strVal;

+    end

+    else InternalError(a.info, 'leValue');

+  end

+end;

+

+function SameValue(a, b: PNode): Boolean;

+begin

+  result := false;

+  case a.kind of

+    nkCharLit..nkInt64Lit:

+      if b.kind in [nkCharLit..nkInt64Lit] then

+        result := a.intVal = b.intVal;

+    nkFloatLit..nkFloat64Lit:

+      if b.kind in [nkFloatLit..nkFloat64Lit] then

+        result := a.floatVal = b.floatVal;

+    nkStrLit..nkTripleStrLit: begin

+      if b.kind in [nkStrLit..nkTripleStrLit] then

+        result := a.strVal = b.strVal;

+    end

+    else InternalError(a.info, 'SameValue');

+  end

+end;

+

+function ValueToString(a: PNode): string;

+begin

+  case a.kind of

+    nkCharLit..nkInt64Lit:

+      result := ToString(a.intVal);

+    nkFloatLit, nkFloat32Lit, nkFloat64Lit:

+      result := toStringF(a.floatVal);

+    nkStrLit..nkTripleStrLit:

+      result := a.strVal;

+    else begin

+      InternalError(a.info, 'valueToString');

+      result := ''

+    end

+  end

+end;

+

+procedure copyStrTable(out dest: TStrTable; const src: TStrTable);

+var

+  i: int;

+begin

+  dest.counter := src.counter;

+{@emit

+  if isNil(src.data) then exit;

+}

+  setLength(dest.data, length(src.data));

+  for i := 0 to high(src.data) do

+    dest.data[i] := src.data[i];

+end;

+

+procedure copyIdTable(var dest: TIdTable; const src: TIdTable);

+var

+  i: int;

+begin

+  dest.counter := src.counter;

+{@emit

+  if isNil(src.data) then exit;

+}

+{@ignore}

+  setLength(dest.data, length(src.data));

+{@emit

+  newSeq(dest.data, length(src.data)); }

+  for i := 0 to high(src.data) do

+    dest.data[i] := src.data[i];

+end;

+

+procedure copyTable(out dest: TTable; const src: TTable);

+var

+  i: int;

+begin

+  dest.counter := src.counter;

+{@emit

+  if isNil(src.data) then exit;

+}

+  setLength(dest.data, length(src.data));

+  for i := 0 to high(src.data) do

+    dest.data[i] := src.data[i];

+end;

+

+procedure copyObjectSet(out dest: TObjectSet; const src: TObjectSet);

+var

+  i: int;

+begin

+  dest.counter := src.counter;

+{@emit

+  if isNil(src.data) then exit;

+}

+  setLength(dest.data, length(src.data));

+  for i := 0 to high(src.data) do

+    dest.data[i] := src.data[i];

+end;

+

+procedure discardSons(father: PNode);

+begin

+  father.sons := nil;

+end;

+

+function newNode(kind: TNodeKind): PNode;

+begin

+  new(result);

+{@ignore}

+  FillChar(result^, sizeof(result^), 0);

+{@emit}

+  result.kind := kind;

+  //result.info := UnknownLineInfo(); inlined:

+  result.info.fileIndex := int32(-1);

+  result.info.col := int16(-1);

+  result.info.line := int16(-1);

+end;

+

+function newIntNode(kind: TNodeKind; const intVal: BiggestInt): PNode;

+begin

+  result := newNode(kind);

+  result.intVal := intVal

+end;

+

+function newIntTypeNode(kind: TNodeKind; const intVal: BiggestInt;

+                        typ: PType): PNode;

+begin

+  result := newIntNode(kind, intVal);

+  result.typ := typ;

+end;

+

+function newFloatNode(kind: TNodeKind; const floatVal: BiggestFloat): PNode;

+begin

+  result := newNode(kind);

+  result.floatVal := floatVal

+end;

+

+function newStrNode(kind: TNodeKind; const strVal: string): PNode;

+begin

+  result := newNode(kind);

+  result.strVal := strVal

+end;

+

+function newIdentNode(ident: PIdent; const info: TLineInfo): PNode;

+begin

+  result := newNode(nkIdent);

+  result.ident := ident;

+  result.info := info;

+end;

+

+function newSymNode(sym: PSym): PNode;

+begin

+  result := newNode(nkSym);

+  result.sym := sym;

+  result.typ := sym.typ;

+  result.info := sym.info;

+end;

+

+function newNodeI(kind: TNodeKind; const info: TLineInfo): PNode;

+begin

+  result := newNode(kind);

+  result.info := info;

+end;

+

+function newNodeIT(kind: TNodeKind; const info: TLineInfo; typ: PType): PNode;

+begin

+  result := newNode(kind);

+  result.info := info;

+  result.typ := typ;

+end;

+

+function NewType(kind: TTypeKind; owner: PSym): PType; overload;

+begin

+  new(result);

+{@ignore}

+  FillChar(result^, sizeof(result^), 0);

+{@emit}

+  result.kind := kind;

+  result.owner := owner;

+  result.size := -1;

+  result.align := 2; // default alignment

+  result.id := getID();

+  if debugIds then RegisterId(result);

+  //if result.id < 2000 then

+  //  MessageOut(typeKindToStr[kind] +{&} ' has id: ' +{&} toString(result.id));

+end;

+

+procedure assignType(dest, src: PType);

+var

+  i: int;

+begin

+  dest.kind := src.kind;

+  dest.flags := src.flags;

+  dest.callConv := src.callConv;

+  dest.n := src.n;

+  dest.size := src.size;

+  dest.align := src.align;

+  dest.containerID := src.containerID;

+  newSons(dest, sonsLen(src));

+  for i := 0 to sonsLen(src)-1 do

+    dest.sons[i] := src.sons[i];

+end;

+

+function copyType(t: PType; owner: PSym; keepId: bool): PType;

+begin

+  result := newType(t.Kind, owner);

+  assignType(result, t);

+  if keepId then result.id := t.id

+  else begin

+    result.id := getID();

+    if debugIds then RegisterId(result);

+  end;

+  result.sym := t.sym;

+  // backend-info should not be copied

+end;

+

+function copySym(s: PSym; keepId: bool = false): PSym;

+begin

+  result := newSym(s.kind, s.name, s.owner);

+  result.ast := nil; // BUGFIX; was: s.ast which made problems

+  result.info := s.info;

+  result.typ := s.typ;

+  if keepId then result.id := s.id

+  else begin

+    result.id := getID();

+    if debugIds then RegisterId(result);

+  end;

+  result.flags := s.flags;

+  result.magic := s.magic;

+  copyStrTable(result.tab, s.tab);

+  result.options := s.options;

+  result.position := s.position;

+  result.loc := s.loc;

+  result.annex := s.annex; // BUGFIX

+end;

+

+function NewSym(symKind: TSymKind; Name: PIdent; owner: PSym): PSym;

+// generates a symbol and initializes the hash field too

+begin

+  new(result);

+{@ignore}

+  FillChar(result^, sizeof(result^), 0);

+{@emit}

+  result.Name := Name;

+  result.Kind := symKind;

+  result.flags := {@set}[];

+  result.info := UnknownLineInfo();

+  result.options := gOptions;

+  result.owner := owner;

+  result.offset := -1;

+  result.id := getID();

+  if debugIds then RegisterId(result);

+  //if result.id < 2000 then

+  //  MessageOut(name.s +{&} ' has id: ' +{&} toString(result.id));

+end;

+

+procedure initStrTable(out x: TStrTable);

+begin

+  x.counter := 0;

+{@emit

+  newSeq(x.data, startSize); }

+{@ignore}

+  setLength(x.data, startSize);

+  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);

+{@emit}

+end;

+

+procedure initTable(out x: TTable);

+begin

+  x.counter := 0;

+{@emit

+  newSeq(x.data, startSize); }

+{@ignore}

+  setLength(x.data, startSize);

+  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);

+{@emit}

+end;

+

+procedure initIdTable(out x: TIdTable);

+begin

+  x.counter := 0;

+{@emit

+  newSeq(x.data, startSize); }

+{@ignore}

+  setLength(x.data, startSize);

+  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);

+{@emit}

+end;

+

+procedure initObjectSet(out x: TObjectSet);

+begin

+  x.counter := 0;

+{@emit

+  newSeq(x.data, startSize); }

+{@ignore}

+  setLength(x.data, startSize);

+  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);

+{@emit}

+end;

+

+procedure initIdNodeTable(out x: TIdNodeTable);

+begin

+  x.counter := 0;

+{@emit

+  newSeq(x.data, startSize); }

+{@ignore}

+  setLength(x.data, startSize);

+  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);

+{@emit}

+end;

+

+procedure initNodeTable(out x: TNodeTable);

+begin

+  x.counter := 0;

+{@emit

+  newSeq(x.data, startSize); }

+{@ignore}

+  setLength(x.data, startSize);

+  fillChar(x.data[0], length(x.data)*sizeof(x.data[0]), 0);

+{@emit}

+end;

+

+function sonsLen(n: PType): int;

+begin

+{@ignore}

+  result := length(n.sons);

+{@emit

+  if isNil(n.sons) then result := 0

+  else result := length(n.sons); }

+end;

+

+procedure newSons(father: PType; len: int);

+var

+  i, L: int;

+begin

+{@emit

+  if isNil(father.sons) then father.sons := @[]; }

+  L := length(father.sons);

+  setLength(father.sons, L + len);

+{@ignore}

+  for i := L to L+len-1 do father.sons[i] := nil // needed for FPC

+{@emit}

+end;

+

+procedure addSon(father, son: PType);

+var

+  L: int;

+begin

+{@ignore}

+  L := length(father.sons);

+  setLength(father.sons, L+1);

+  father.sons[L] := son;

+{@emit

+  if isNil(father.sons) then father.sons := @[]; }

+{@emit add(father.sons, son); }

+end;

+

+function sonsLen(n: PNode): int;

+begin

+{@ignore}

+  result := length(n.sons);

+{@emit

+  if isNil(n.sons) then result := 0

+  else result := length(n.sons); }

+end;

+

+procedure newSons(father: PNode; len: int);

+var

+  i, L: int;

+begin

+{@emit

+  if isNil(father.sons) then father.sons := @[]; }

+  L := length(father.sons);

+  setLength(father.sons, L + len);

+{@ignore}

+  for i := L to L+len-1 do father.sons[i] := nil // needed for FPC

+{@emit}

+end;

+

+procedure addSon(father, son: PNode);

+var

+  L: int;

+begin

+{@ignore}

+  L := length(father.sons);

+  setLength(father.sons, L+1);

+  father.sons[L] := son;

+{@emit

+  if isNil(father.sons) then father.sons := @[]; }

+{@emit add(father.sons, son); }

+end;

+

+procedure delSon(father: PNode; idx: int);

+var

+  len, i: int;

+begin

+{@emit

+  if isNil(father.sons) then exit; }

+  len := sonsLen(father);

+  for i := idx to len-2 do

+    father.sons[i] := father.sons[i+1];

+  setLength(father.sons, len-1);

+end;

+

+function copyNode(src: PNode): PNode;

+// does not copy its sons!

+begin

+  if src = nil then begin result := nil; exit end;

+  result := newNode(src.kind);

+  result.info := src.info;

+  result.typ := src.typ;

+  result.flags := src.flags * PersistentNodeFlags;

+  case src.Kind of

+    nkCharLit..nkInt64Lit:

+      result.intVal := src.intVal;

+    nkFloatLit, nkFloat32Lit, nkFloat64Lit:

+      result.floatVal := src.floatVal;

+    nkSym:

+      result.sym := src.sym;

+    nkIdent:

+      result.ident := src.ident;

+    nkStrLit..nkTripleStrLit:

+      result.strVal := src.strVal;

+    nkMetaNode:

+      result.nodePtr := src.nodePtr;

+    else begin end;

+  end;

+end;

+

+function copyTree(src: PNode): PNode;

+// copy a whole syntax tree; performs deep copying

+var

+  i: int;

+begin

+  if src = nil then begin result := nil; exit end;

+  result := newNode(src.kind);

+  result.info := src.info;

+  result.typ := src.typ;

+  result.flags := src.flags * PersistentNodeFlags;

+  case src.Kind of

+    nkCharLit..nkInt64Lit:

+      result.intVal := src.intVal;

+    nkFloatLit, nkFloat32Lit, nkFloat64Lit:

+      result.floatVal := src.floatVal;

+    nkSym:

+      result.sym := src.sym;

+    nkIdent:

+      result.ident := src.ident;

+    nkStrLit..nkTripleStrLit:

+      result.strVal := src.strVal;

+    nkMetaNode:

+      result.nodePtr := src.nodePtr;

+    else begin

+      result.sons := nil;

+      newSons(result, sonsLen(src));

+      for i := 0 to sonsLen(src)-1 do

+        result.sons[i] := copyTree(src.sons[i]);

+    end;

+  end

+end;

+

+function lastSon(n: PNode): PNode;

+begin

+  result := n.sons[sonsLen(n)-1];

+end;

+

+function lastSon(n: PType): PType;

+begin

+  result := n.sons[sonsLen(n)-1];

+end;

+

+function hasSonWith(n: PNode; kind: TNodeKind): boolean;

+var

+  i: int;

+begin

+  for i := 0 to sonsLen(n)-1 do begin

+    if (n.sons[i] <> nil) and (n.sons[i].kind = kind) then begin

+      result := true; exit

+    end

+  end;

+  result := false

+end;

+

+function hasSubnodeWith(n: PNode; kind: TNodeKind): boolean;

+var

+  i: int;

+begin

+  case n.kind of

+    nkEmpty..nkNilLit: result := n.kind = kind;

+    else begin

+      for i := 0 to sonsLen(n)-1 do begin

+        if (n.sons[i] <> nil) and (n.sons[i].kind = kind)

+        or hasSubnodeWith(n.sons[i], kind) then begin

+          result := true; exit

+        end

+      end;

+      result := false

+    end

+  end

+end;

+

+procedure replaceSons(n: PNode; oldKind, newKind: TNodeKind);

+var

+  i: int;

+begin

+  for i := 0 to sonsLen(n)-1 do

+    if n.sons[i].kind = oldKind then n.sons[i].kind := newKind

+end;

+

+function sonsNotNil(n: PNode): bool;

+var

+  i: int;

+begin

+  for i := 0 to sonsLen(n)-1 do

+    if n.sons[i] = nil then begin result := false; exit end;

+  result := true

+end;

+

+procedure addSonIfNotNil(father, n: PNode);

+begin

+  if n <> nil then addSon(father, n)

+end;

+

+// ---------------- efficient integer sets ----------------------------------

+// Same algorithm as the one the GC uses

+

+function mustRehash(len, counter: int): bool;

+begin

+  assert(len > counter);

+  result := (len * 2 < counter * 3) or (len-counter < 4);

+end;

+

+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;

+

+procedure IntSetInit(var s: TIntSet);

+begin

+{@ignore}

+  fillChar(s, sizeof(s), 0);

+{@emit}

+{@ignore}

+  setLength(s.data, InitIntSetSize);

+  fillChar(s.data[0], length(s.data)*sizeof(s.data[0]), 0);

+{@emit

+  newSeq(s.data, InitIntSetSize); }

+  s.max := InitIntSetSize-1;

+  s.counter := 0;

+  s.head := nil

+end;

+

+function IntSetGet(const t: TIntSet; key: int): PTrunk;

+var

+  h: int;

+begin

+  h := key and t.max;

+  while t.data[h] <> nil do begin

+    if t.data[h].key = key then begin

+      result := t.data[h]; exit

+    end;

+    h := nextTry(h, t.max)

+  end;

+  result := nil

+end;

+

+procedure IntSetRawInsert(const t: TIntSet; var data: TTrunkSeq;

+                          desc: PTrunk);

+var

+  h: int;

+begin

+  h := desc.key and t.max;

+  while data[h] <> nil do begin

+    assert(data[h] <> desc);

+    h := nextTry(h, t.max)

+  end;

+  assert(data[h] = nil);

+  data[h] := desc

+end;

+

+procedure IntSetEnlarge(var t: TIntSet);

+var

+  n: TTrunkSeq;

+  i, oldMax: int;

+begin

+  oldMax := t.max;

+  t.max := ((t.max+1)*2)-1;

+{@ignore}

+  setLength(n, t.max + 1);

+  fillChar(n[0], length(n)*sizeof(n[0]), 0);

+{@emit

+  newSeq(n, t.max+1); }

+  for i := 0 to oldmax do

+    if t.data[i] <> nil then

+      IntSetRawInsert(t, n, t.data[i]);

+{@ignore}

+  t.data := n;

+{@emit

+  swap(t.data, n); }

+end;

+

+function IntSetPut(var t: TIntSet; key: int): PTrunk;

+var

+  h: int;

+begin

+  h := key and t.max;

+  while t.data[h] <> nil do begin

+    if t.data[h].key = key then begin

+      result := t.data[h]; exit

+    end;

+    h := nextTry(h, t.max)

+  end;

+

+  if mustRehash(t.max+1, t.counter) then IntSetEnlarge(t);

+  inc(t.counter);

+  h := key and t.max;

+  while t.data[h] <> nil do h := nextTry(h, t.max);

+  assert(t.data[h] = nil);

+  new(result);

+{@ignore}

+  fillChar(result^, sizeof(result^), 0);

+{@emit}

+  result.next := t.head;

+  result.key := key;

+  t.head := result;

+  t.data[h] := result;

+end;

+

+// ---------- slightly higher level procs ----------------------------------

+

+function transform(key: int): int;

+begin

+  if key < 0 then result := 1000000000 + key // avoid negative numbers!

+  else result := key

+end;

+

+function IntSetContains(const s: TIntSet; key: int): bool;

+var

+  u: int;

+  t: PTrunk;

+begin

+  u := transform(key);

+  t := IntSetGet(s, u div BitsPerTrunk);

+  if t <> nil then begin

+    u := u mod BitsPerTrunk;

+    result := (t.bits[u div BitsPerInt]

+      and (1 shl (u mod BitsPerInt))) <> 0

+  end

+  else

+    result := false

+end;

+

+procedure IntSetIncl(var s: TIntSet; key: int);

+var

+  u: int;

+  t: PTrunk;

+begin

+  u := transform(key);

+  t := IntSetPut(s, u div BitsPerTrunk);

+  u := u mod BitsPerTrunk;

+  t.bits[u div BitsPerInt] := t.bits[u div BitsPerInt]

+                            or (1 shl (u mod BitsPerInt));

+end;

+

+function IntSetContainsOrIncl(var s: TIntSet; key: int): bool;

+var

+  u: int;

+  t: PTrunk;

+begin

+  u := transform(key);

+  t := IntSetGet(s, u div BitsPerTrunk);

+  if t <> nil then begin

+    u := u mod BitsPerTrunk;

+    result := (t.bits[u div BitsPerInt]

+          and (1 shl (u mod BitsPerInt))) <> 0;

+    if not result then

+      t.bits[u div BitsPerInt] := t.bits[u div BitsPerInt]

+                                or (1 shl (u mod BitsPerInt));

+  end

+  else begin

+    IntSetIncl(s, key);

+    result := false

+  end

+end;

+

+

+initialization

+  if debugIDs then IntSetInit(usedIds);

+end.