diff options
Diffstat (limited to 'compiler/ast.nim')
-rw-r--r-- | compiler/ast.nim | 638 |
1 files changed, 304 insertions, 334 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 883b68d71..d94f09ccb 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -9,12 +9,12 @@ # abstract syntax tree + symbol table -import - msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, +import + msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, intsets, idgen type - TCallingConvention* = enum + TCallingConvention* = enum ccDefault, # proc has no explicit calling convention ccStdCall, # procedure is stdcall ccCDecl, # cdecl @@ -26,12 +26,12 @@ type ccClosure, # proc has a closure ccNoConvention # needed for generating proper C procs sometimes -const - CallingConvToStr*: array[TCallingConvention, string] = ["", "stdcall", +const + CallingConvToStr*: array[TCallingConvention, string] = ["", "stdcall", "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure", "noconv"] -type +type TNodeKind* = enum # order is extremely important, because ranges are used # to check whether a node belongs to a certain class nkNone, # unknown node kind: indicates an error @@ -64,13 +64,13 @@ type # end of atoms nkMetaNode_Obsolete, # difficult to explain; represents itself # (used for macros) - nkDotCall, # used to temporarily flag a nkCall node; + nkDotCall, # used to temporarily flag a nkCall node; # this is used # for transforming ``s.len`` to ``len(s)`` nkCommand, # a call like ``p 2, 4`` without parenthesis nkCall, # a call like p(x, y) or an operation like +(a, b) - nkCallStrLit, # a call with a string literal + nkCallStrLit, # a call with a string literal # x"abc" has two sons: nkIdent, nkRStrLit # x"""abc""" has two sons: nkIdent, nkTripleStrLit nkInfix, # a call like (a + b) @@ -126,7 +126,7 @@ type nkAsgn, # a = b nkFastAsgn, # internal node for a fast ``a = b`` - # (no string copy) + # (no string copy) nkGenericParams, # generic parameters nkFormalParams, # formal parameters nkOfInherit, # inherited from symbol @@ -192,10 +192,11 @@ type nkWith, # distinct with `foo` nkWithout, # distinct without `foo` - + nkTypeOfExpr, # type(1+2) nkObjectTy, # object body nkTupleTy, # tuple body + nkTupleClassTy, # tuple type class nkTypeClassTy, # user-defined type class nkStaticTy, # ``static[T]`` nkRecList, # list of object parts @@ -226,7 +227,7 @@ type TSymFlag* = enum # already 32 flags! sfUsed, # read access of sym (for warnings) or simply used sfExported, # symbol is exported from module - sfFromGeneric, # symbol is instantiation of a generic; this is needed + sfFromGeneric, # symbol is instantiation of a generic; this is needed # for symbol file generation; such symbols should always # be written into the ROD file sfGlobal, # symbol is at global scope @@ -256,7 +257,7 @@ type sfThread, # proc will run as a thread # variable is a thread variable sfCompileTime, # proc can be evaluated at compile time - sfMerge, # proc can be merged with itself + sfConstructor, # proc is a C++ constructor sfDeadCodeElim, # dead code elimination for the module is turned on sfBorrow, # proc is borrowed sfInfixCall, # symbol needs infix call syntax in target language; @@ -284,9 +285,9 @@ const sfAnon* = sfDiscardable # symbol name that was generated by the compiler - # the compiler will avoid printing such names + # the compiler will avoid printing such names # in user messages. - + sfNoForward* = sfRegister # forward declarations are not required (per module) @@ -300,7 +301,7 @@ const # getting ready for the future expr/stmt merge nkWhen* = nkWhenStmt nkWhenExpr* = nkWhenStmt - nkEffectList* = nkArgList + nkEffectList* = nkArgList # hacks ahead: an nkEffectList is a node with 4 children: exceptionEffects* = 0 # exceptions at position 0 usesEffects* = 1 # read effects at position 1 @@ -314,14 +315,14 @@ type # XXX put this into an include file to avoid this issue! tyNone, tyBool, tyChar, tyEmpty, tyArrayConstr, tyNil, tyExpr, tyStmt, tyTypeDesc, - tyGenericInvokation, # ``T[a, b]`` for types to invoke + tyGenericInvocation, # ``T[a, b]`` for types to invoke tyGenericBody, # ``T[a, b, body]`` last parameter is the body tyGenericInst, # ``T[a, b, realInstance]`` instantiated generic type # realInstance will be a concrete type like tyObject # unless this is an instance of a generic alias type. # then realInstance will be the tyGenericInst of the # completely (recursively) resolved alias. - + tyGenericParam, # ``a`` in the above patterns tyDistinct, tyEnum, @@ -340,14 +341,14 @@ type tyInt, tyInt8, tyInt16, tyInt32, tyInt64, # signed integers tyFloat, tyFloat32, tyFloat64, tyFloat128, tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64, - tyBigNum, - tyConst, tyMutable, tyVarargs, + tyBigNum, + tyConst, tyMutable, tyVarargs, tyIter, # unused tyProxy # used as errornous type (for idetools) - + tyBuiltInTypeClass #\ # Type such as the catch-all object, tuple, seq, etc - + tyUserTypeClass #\ # the body of a user-defined type class @@ -357,27 +358,27 @@ type # tyGenericInst represents concrete types, while # this is still a "generic param" that will bind types # and resolves them during sigmatch and instantiation. - + tyCompositeTypeClass #\ # Type such as seq[Number] - # The notes for tyUserTypeClassInst apply here as well + # The notes for tyUserTypeClassInst apply here as well # sons[0]: the original expression used by the user. # sons[1]: fully expanded and instantiated meta type # (potentially following aliases) - + tyAnd, tyOr, tyNot #\ # boolean type classes such as `string|int`,`not seq`, # `Sortable and Enumable`, etc - + tyAnything #\ # a type class matching any type - + tyStatic #\ # a value known at compile type (the underlying type is .base) - + tyFromExpr #\ # This is a type representing an expression that depends - # on generic parameters (the exprsesion is stored in t.n) + # on generic parameters (the expression is stored in t.n) # It will be converted to a real type only during generic # instantiation and prior to this it has the potential to # be any type. @@ -390,7 +391,7 @@ type # sons[0]: type of containing object or tuple # sons[1]: field type # .n: nkDotExpr storing the field name - + static: # remind us when TTypeKind stops to fit in a single 64-bit word assert TTypeKind.high.ord <= 63 @@ -408,7 +409,7 @@ const tyAnd, tyOr, tyNot, tyAnything} tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyExpr} + tyTypeClasses - + type TTypeKinds* = set[TTypeKind] @@ -428,7 +429,8 @@ type nfExplicitCall # x.y() was used instead of x.y nfExprCall # this is an attempt to call a regular expression nfIsRef # this node is a 'ref' node; used for the VM - + nfIsCursor # this node is attached a cursor; used for idetools + TNodeFlags* = set[TNodeFlag] TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 28) tfVarargs, # procedure has C styled varargs @@ -447,7 +449,7 @@ type # proc foo(L: static[int]): array[L, int] # can be attached to ranges to indicate that the range # depends on unresolved static params. - tfRetType, # marks return types in proc (used to detect type classes + tfRetType, # marks return types in proc (used to detect type classes # used as return types for return type inference) tfCapturesEnv, # whether proc really captures some environment tfByCopy, # pass object/tuple by copy (C backend) @@ -455,10 +457,10 @@ type tfIterator, # type is really an iterator, not a tyProc tfShared, # type is 'shared' tfNotNil, # type cannot be 'nil' - + tfNeedsInit, # type constains a "not nil" constraint somewhere or some - # other type so that it requires inititalization - tfHasShared, # type constains a "shared" constraint modifier somewhere + # other type so that it requires initalization + tfVarIsPtr, # 'var' type is translated like 'ptr' even in C++ mode tfHasMeta, # type contains "wildcard" sub-types such as generic params # or other type classes tfHasGCedMem, # type contains GC'ed memory @@ -519,41 +521,42 @@ const tfGcSafe* = tfThread tfObjHasKids* = tfEnumHasHoles skError* = skUnknown - + # type flags that are essential for type equality: - eqTypeFlags* = {tfIterator, tfShared, tfNotNil} + eqTypeFlags* = {tfIterator, tfShared, tfNotNil, tfVarIsPtr} type TMagic* = enum # symbols that require compiler magic: mNone, mDefined, mDefinedInScope, mCompiles, - mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, + mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf, mAddr, mTypeOf, mEcho, mShallowCopy, mSlurp, mStaticExec, mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst, - mUnaryLt, mSucc, - mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray, - mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref, - mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64, - mDivI64, mModI64, + mUnaryLt, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray, + mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref, + mGCunref, + + mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64, + mDivI64, mModI64, mSucc, mPred, mAddF64, mSubF64, mMulF64, mDivF64, - mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, + + mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, mMaxI64, - mMinF64, mMaxF64, mAddU, mSubU, mMulU, + mMinF64, mMaxF64, mAddU, mSubU, mMulU, mDivU, mModU, mEqI, mLeI, - mLtI, - mEqI64, mLeI64, mLtI64, mEqF64, mLeF64, mLtF64, - mLeU, mLtU, mLeU64, mLtU64, - mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef, + mLtI, + mEqI64, mLeI64, mLtI64, mEqF64, mLeF64, mLtF64, + mLeU, mLtU, mLeU64, mLtU64, + mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mEqProc, 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, mEnumToStr, - mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, - mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, - mConTArr, mConTT, mSlice, + 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, mEnumToStr, + mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, + mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mSlice, mFields, mFieldPairs, mOmpParFor, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, @@ -583,36 +586,35 @@ type # things that we can evaluate safely at compile time, even if not asked for it: const - ctfeWhitelist* = {mNone, mUnaryLt, mSucc, - mPred, mInc, mDec, mOrd, mLengthOpenArray, - mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, - mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64, + ctfeWhitelist* = {mNone, mUnaryLt, mSucc, + mPred, mInc, mDec, mOrd, mLengthOpenArray, + mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, + mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64, mDivI64, mModI64, mAddF64, mSubF64, mMulF64, mDivF64, - mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, + mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, mMaxI64, - mMinF64, mMaxF64, mAddU, mSubU, mMulU, + mMinF64, mMaxF64, mAddU, mSubU, mMulU, mDivU, mModU, 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, mEnumToStr, - mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, - mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, - mConTArr, mConTT, - mAppendStrCh, mAppendStrStr, mAppendSeqElem, + 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, mEnumToStr, + mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, + mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, + mAppendStrCh, mAppendStrStr, mAppendSeqElem, mInRange, mInSet, mRepr, mCopyStr, mCopyStrLast} # magics that require special semantic checking and # thus cannot be overloaded (also documented in the spec!): SpecialSemMagics* = { - mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf, + mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf, mEcho, mShallowCopy, mExpandToAst, mParallel, mSpawn, mAstToStr} type @@ -633,49 +635,51 @@ type floatVal*: BiggestFloat of nkStrLit..nkTripleStrLit: strVal*: string - of nkSym: + of nkSym: sym*: PSym - of nkIdent: + of nkIdent: ident*: PIdent else: sons*: TNodeSeq comment*: string - + TSymSeq* = seq[PSym] TStrTable* = object # a table[PIdent] of PSym counter*: int data*: TSymSeq - + # -------------- backend information ------------------------------- - TLocKind* = enum + TLocKind* = enum 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 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* = enum + TLocFlag* = enum lfIndirect, # backend introduced a pointer - lfParamCopy, # backend introduced a parameter copy (LLVM) + lfFullExternalName, # only used when 'gCmd == cmdPretty': Indicates + # that the symbol has been imported via 'importc: "fullname"' and + # no format string. lfNoDeepCopy, # no need for a deep copy lfNoDecl, # do not declare it in C lfDynamicLib, # link symbol to dynamic library lfExportLib, # export symbol for dynamic library generation lfHeader, # include header file for symbol - lfImportCompilerProc # ``importc`` of a compilerproc - TStorageLoc* = enum + lfImportCompilerProc, # ``importc`` of a compilerproc + lfSingleUse # no location yet and will only be used once + TStorageLoc* = enum 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[TLocFlag] - TLoc*{.final.} = object + TLoc* = object k*: TLocKind # kind of location s*: TStorageLoc flags*: TLocFlags # location's flags @@ -687,7 +691,7 @@ type # ---------------- end of backend information ------------------------------ - TLibKind* = enum + TLibKind* = enum libHeader, libDynamic TLib* = object of lists.TListEntry # also misused for headers! kind*: TLibKind @@ -695,17 +699,17 @@ type isOverriden*: bool name*: PRope path*: PNode # can be a string literal! - + TInstantiation* = object sym*: PSym concreteTypes*: seq[PType] usedBy*: seq[int32] # list of modules using the generic # needed in caas mode for purging the cache - # XXX: it's possible to switch to a + # XXX: it's possible to switch to a # simple ref count here - + PInstantiation* = ref TInstantiation - + TScope* = object depthLevel*: int symbols*: TStrTable @@ -772,7 +776,7 @@ type constraint*: PNode # additional constraints like 'lit|result'; also # misused for the codegenDecl pragma in the hope # it won't cause problems - + TTypeSeq* = seq[PType] TLockLevel* = distinct int16 TType* {.acyclic.} = object of TIdObj # \ @@ -805,45 +809,45 @@ type lockLevel*: TLockLevel # lock level as required for deadlock checking loc*: TLoc - TPair*{.final.} = object + TPair* = object key*, val*: RootRef TPairSeq* = seq[TPair] - TTable*{.final.} = object # the same as table[PObject] of PObject + TTable* = object # the same as table[PObject] of PObject counter*: int data*: TPairSeq - TIdPair*{.final.} = object + TIdPair* = object key*: PIdObj val*: RootRef TIdPairSeq* = seq[TIdPair] - TIdTable*{.final.} = object # the same as table[PIdent] of PObject + TIdTable* = object # the same as table[PIdent] of PObject counter*: int data*: TIdPairSeq - TIdNodePair*{.final.} = object + TIdNodePair* = object key*: PIdObj val*: PNode TIdNodePairSeq* = seq[TIdNodePair] - TIdNodeTable*{.final.} = object # the same as table[PIdObj] of PNode + TIdNodeTable* = object # the same as table[PIdObj] of PNode counter*: int data*: TIdNodePairSeq - TNodePair*{.final.} = object + TNodePair* = object h*: THash # because it is expensive to compute! key*: PNode val*: int TNodePairSeq* = seq[TNodePair] - TNodeTable*{.final.} = object # the same as table[PNode] of int; + TNodeTable* = object # the same as table[PNode] of int; # nodes are compared by structure! counter*: int data*: TNodePairSeq TObjectSeq* = seq[RootRef] - TObjectSet*{.final.} = object + TObjectSet* = object counter*: int data*: TObjectSeq @@ -854,27 +858,27 @@ type # same name as an imported module. This is necessary because of # the poor naming choices in the standard library. -const +const OverloadableSyms* = {skProc, skMethod, skIterator, skClosureIterator, skConverter, skModule, skTemplate, skMacro} - GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody, + GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody, tyGenericParam} - - StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray, + + StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray, tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyOpenArray, tyVarargs} - + ConcreteTypes*: TTypeKinds = { # types of the expr that may occur in:: # var x = expr - tyBool, tyChar, tyEnum, tyArray, tyObject, + tyBool, tyChar, tyEnum, tyArray, tyObject, tySet, tyTuple, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, - tyPointer, + tyPointer, tyOpenArray, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128, tyUInt..tyUInt64} IntegralTypes* = {tyBool, tyChar, tyEnum, tyInt..tyInt64, tyFloat..tyFloat128, tyUInt..tyUInt64} - ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet, + ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet, tyTuple, tySequence} NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence, tyProc, tyString, tyError} @@ -883,7 +887,7 @@ const skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias} PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfDotSetter, nfDotField, - nfIsRef} + nfIsRef, nfIsCursor} namePos* = 0 patternPos* = 1 # empty except for term rewriting macros genericParamsPos* = 2 @@ -913,53 +917,7 @@ const skIterators* = {skIterator, skClosureIterator} - lfFullExternalName* = lfParamCopy # \ - # only used when 'gCmd == cmdPretty': Indicates that the symbol has been - # imported via 'importc: "fullname"' and no format string. - -# creator procs: -proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym, - info: TLineInfo): PSym -proc newType*(kind: TTypeKind, owner: PSym): PType -proc newNode*(kind: TNodeKind): PNode -proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode -proc newIntTypeNode*(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode -proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode -proc newStrNode*(kind: TNodeKind, strVal: string): PNode -proc newIdentNode*(ident: PIdent, info: TLineInfo): PNode -proc newSymNode*(sym: PSym): PNode -proc newNodeI*(kind: TNodeKind, info: TLineInfo): PNode -proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode -proc initStrTable*(x: var TStrTable) -proc initTable*(x: var TTable) -proc initIdTable*(x: var TIdTable) -proc initObjectSet*(x: var TObjectSet) -proc initIdNodeTable*(x: var TIdNodeTable) -proc initNodeTable*(x: var TNodeTable) - -# copy procs: -proc copyType*(t: PType, owner: PSym, keepId: bool): PType -proc copySym*(s: PSym, keepId: bool = false): PSym -proc assignType*(dest, src: PType) -proc copyStrTable*(dest: var TStrTable, src: TStrTable) -proc copyTable*(dest: var TTable, src: TTable) -proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) -proc copyIdTable*(dest: var TIdTable, src: TIdTable) -proc sonsLen*(n: PNode): int {.inline.} -proc sonsLen*(n: PType): int {.inline.} -proc lastSon*(n: PNode): PNode {.inline.} -proc lastSon*(n: PType): PType {.inline.} -proc newSons*(father: PNode, length: int) -proc newSons*(father: PType, length: int) -proc addSon*(father, son: PNode) -proc delSon*(father: PNode, idx: int) -proc hasSonWith*(n: PNode, kind: TNodeKind): bool -proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool -proc replaceSons*(n: PNode, oldKind, newKind: TNodeKind) -proc copyNode*(src: PNode): PNode - # does not copy its sons! -proc copyTree*(src: PNode): PNode - # does copy its sons! +var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things proc isCallExpr*(n: PNode): bool = result = n.kind in nkCallKinds @@ -969,17 +927,17 @@ proc discardSons*(father: PNode) proc len*(n: PNode): int {.inline.} = if isNil(n.sons): result = 0 else: result = len(n.sons) - + proc safeLen*(n: PNode): int {.inline.} = ## works even for leaves. if n.kind in {nkNone..nkNilLit} or isNil(n.sons): result = 0 else: result = len(n.sons) - + proc add*(father, son: PNode) = assert son != nil if isNil(father.sons): father.sons = @[] add(father.sons, son) - + proc `[]`*(n: PNode, i: int): PNode {.inline.} = result = n.sons[i] @@ -987,7 +945,58 @@ proc `[]`*(n: PNode, i: int): PNode {.inline.} = template `{}`*(n: PNode, i: int): expr = n[i -| n] template `{}=`*(n: PNode, i: int, s: PNode): stmt = n.sons[i -| n] = s - + +when defined(useNodeIds): + const nodeIdToDebug* = -1 # 299750 # 300761 #300863 # 300879 + var gNodeId: int + +proc newNode*(kind: TNodeKind): PNode = + new(result) + result.kind = kind + #result.info = UnknownLineInfo() inlined: + result.info.fileIndex = int32(- 1) + result.info.col = int16(- 1) + result.info.line = int16(- 1) + when defined(useNodeIds): + result.id = gNodeId + if result.id == nodeIdToDebug: + echo "KIND ", result.kind + writeStackTrace() + inc gNodeId + +proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode = + result = newNode(kind) + result.intVal = intVal + +proc newIntTypeNode*(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode = + result = newIntNode(kind, intVal) + result.typ = typ + +proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode = + result = newNode(kind) + result.floatVal = floatVal + +proc newStrNode*(kind: TNodeKind, strVal: string): PNode = + result = newNode(kind) + result.strVal = strVal + +proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym, + info: TLineInfo): PSym = + # generates a symbol and initializes the hash field too + new(result) + result.name = name + result.kind = symKind + result.flags = {} + result.info = info + result.options = gOptions + result.owner = owner + result.offset = - 1 + result.id = getID() + when debugIds: + registerId(result) + #if result.id < 2000: + # MessageOut(name.s & " has id: " & toString(result.id)) + var emptyNode* = newNode(nkEmpty) # There is a single empty node that is shared! Do not overwrite it! @@ -1025,97 +1034,60 @@ proc appendToModule*(m: PSym, n: PNode) = else: assert m.ast.kind == nkStmtList m.ast.sons.add(n) - + const # for all kind of hash tables: GrowthFactor* = 2 # must be power of 2, > 0 StartSize* = 8 # must be power of 2, > 0 -proc copyStrTable(dest: var TStrTable, src: TStrTable) = +proc copyStrTable*(dest: var TStrTable, src: TStrTable) = dest.counter = src.counter - if isNil(src.data): return + if isNil(src.data): return setLen(dest.data, len(src.data)) for i in countup(0, high(src.data)): dest.data[i] = src.data[i] - -proc copyIdTable(dest: var TIdTable, src: TIdTable) = + +proc copyIdTable*(dest: var TIdTable, src: TIdTable) = dest.counter = src.counter - if isNil(src.data): return + if isNil(src.data): return newSeq(dest.data, len(src.data)) for i in countup(0, high(src.data)): dest.data[i] = src.data[i] - -proc copyTable(dest: var TTable, src: TTable) = + +proc copyTable*(dest: var TTable, src: TTable) = dest.counter = src.counter - if isNil(src.data): return + if isNil(src.data): return setLen(dest.data, len(src.data)) for i in countup(0, high(src.data)): dest.data[i] = src.data[i] - -proc copyObjectSet(dest: var TObjectSet, src: TObjectSet) = + +proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) = dest.counter = src.counter - if isNil(src.data): return + if isNil(src.data): return setLen(dest.data, len(src.data)) for i in countup(0, high(src.data)): dest.data[i] = src.data[i] - -proc discardSons(father: PNode) = - father.sons = nil -when defined(useNodeIds): - const nodeIdToDebug* = -1 # 884953 # 612794 - #612840 # 612905 # 614635 # 614637 # 614641 - # 423408 - #429107 # 430443 # 441048 # 441090 # 441153 - var gNodeId: int - -proc newNode(kind: TNodeKind): PNode = - new(result) - result.kind = kind - #result.info = UnknownLineInfo() inlined: - result.info.fileIndex = int32(- 1) - result.info.col = int16(- 1) - result.info.line = int16(- 1) - when defined(useNodeIds): - result.id = gNodeId - if result.id == nodeIdToDebug: - echo "KIND ", result.kind - writeStackTrace() - inc gNodeId - -proc newIntNode(kind: TNodeKind, intVal: BiggestInt): PNode = - result = newNode(kind) - result.intVal = intVal - -proc newIntTypeNode(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode = - result = newIntNode(kind, intVal) - result.typ = typ - -proc newFloatNode(kind: TNodeKind, floatVal: BiggestFloat): PNode = - result = newNode(kind) - result.floatVal = floatVal - -proc newStrNode(kind: TNodeKind, strVal: string): PNode = - result = newNode(kind) - result.strVal = strVal +proc discardSons*(father: PNode) = + father.sons = nil proc withInfo*(n: PNode, info: TLineInfo): PNode = n.info = info return n -proc newIdentNode(ident: PIdent, info: TLineInfo): PNode = +proc newIdentNode*(ident: PIdent, info: TLineInfo): PNode = result = newNode(nkIdent) result.ident = ident result.info = info -proc newSymNode(sym: PSym): PNode = +proc newSymNode*(sym: PSym): PNode = result = newNode(nkSym) result.sym = sym result.typ = sym.typ result.info = sym.info -proc newSymNode*(sym: PSym, info: TLineInfo): PNode = +proc newSymNode*(sym: PSym, info: TLineInfo): PNode = result = newNode(nkSym) result.sym = sym result.typ = sym.typ result.info = info -proc newNodeI(kind: TNodeKind, info: TLineInfo): PNode = +proc newNodeI*(kind: TNodeKind, info: TLineInfo): PNode = new(result) result.kind = kind result.info = info @@ -1154,11 +1126,16 @@ proc newNode*(kind: TNodeKind, info: TLineInfo, sons: TNodeSeq = @[], writeStackTrace() inc gNodeId -proc newNodeIT(kind: TNodeKind, info: TLineInfo, typ: PType): PNode = +proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode = result = newNode(kind) result.info = info result.typ = typ +proc addSon*(father, son: PNode) = + assert son != nil + if isNil(father.sons): father.sons = @[] + add(father.sons, son) + var emptyParams = newNode(nkFormalParams) emptyParams.addSon(emptyNode) @@ -1180,7 +1157,7 @@ proc `$`*(x: TLockLevel): string = elif x.ord == UnknownLockLevel.ord: result = "<unknown>" else: result = $int16(x) -proc newType(kind: TTypeKind, owner: PSym): PType = +proc newType*(kind: TTypeKind, owner: PSym): PType = new(result) result.kind = kind result.owner = owner @@ -1192,7 +1169,7 @@ proc newType(kind: TTypeKind, owner: PSym): PType = registerId(result) #if result.id < 2000: # messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id)) - + proc mergeLoc(a: var TLoc, b: TLoc) = if a.k == low(a.k): a.k = b.k if a.s == low(a.s): a.s = b.s @@ -1200,8 +1177,38 @@ proc mergeLoc(a: var TLoc, b: TLoc) = if a.t == nil: a.t = b.t if a.r == nil: a.r = b.r #if a.a == 0: a.a = b.a - -proc assignType(dest, src: PType) = + +proc newSons*(father: PNode, length: int) = + if isNil(father.sons): + newSeq(father.sons, length) + else: + setLen(father.sons, length) + +proc newSons*(father: PType, length: int) = + if isNil(father.sons): + newSeq(father.sons, length) + else: + setLen(father.sons, length) + +proc sonsLen*(n: PType): int = + if isNil(n.sons): result = 0 + else: result = len(n.sons) + +proc len*(n: PType): int = + if isNil(n.sons): result = 0 + else: result = len(n.sons) + +proc sonsLen*(n: PNode): int = + if isNil(n.sons): result = 0 + else: result = len(n.sons) + +proc lastSon*(n: PNode): PNode = + result = n.sons[sonsLen(n) - 1] + +proc lastSon*(n: PType): PType = + result = n.sons[sonsLen(n) - 1] + +proc assignType*(dest, src: PType) = dest.kind = src.kind dest.flags = src.flags dest.callConv = src.callConv @@ -1221,23 +1228,23 @@ proc assignType(dest, src: PType) = dest.sym = src.sym newSons(dest, sonsLen(src)) for i in countup(0, sonsLen(src) - 1): dest.sons[i] = src.sons[i] - -proc copyType(t: PType, owner: PSym, keepId: bool): PType = + +proc copyType*(t: PType, owner: PSym, keepId: bool): PType = result = newType(t.kind, owner) assignType(result, t) - if keepId: + if keepId: result.id = t.id - else: + else: when debugIds: registerId(result) result.sym = t.sym # backend-info should not be copied - -proc copySym(s: PSym, keepId: bool = false): PSym = + +proc copySym*(s: PSym, keepId: bool = false): PSym = result = newSym(s.kind, s.name, s.owner, s.info) #result.ast = nil # BUGFIX; was: s.ast which made problems result.typ = s.typ if keepId: result.id = s.id - else: + else: result.id = getID() when debugIds: registerId(result) result.flags = s.flags @@ -1264,74 +1271,39 @@ proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym = result.annex = s.annex # XXX once usedGenerics is used, ensure module aliases keep working! assert s.usedGenerics == nil - -proc newSym(symKind: TSymKind, name: PIdent, owner: PSym, - info: TLineInfo): PSym = - # generates a symbol and initializes the hash field too - new(result) - result.name = name - result.kind = symKind - result.flags = {} - result.info = info - result.options = gOptions - result.owner = owner - result.offset = - 1 - result.id = getID() - when debugIds: - registerId(result) - #if result.id < 2000: - # MessageOut(name.s & " has id: " & toString(result.id)) - -proc initStrTable(x: var TStrTable) = + +proc initStrTable*(x: var TStrTable) = x.counter = 0 newSeq(x.data, StartSize) proc newStrTable*: TStrTable = initStrTable(result) -proc initTable(x: var TTable) = +proc initTable(x: var TTable) = x.counter = 0 newSeq(x.data, StartSize) -proc initIdTable(x: var TIdTable) = +proc initIdTable*(x: var TIdTable) = x.counter = 0 newSeq(x.data, StartSize) -proc initObjectSet(x: var TObjectSet) = +proc resetIdTable*(x: var TIdTable) = x.counter = 0 - newSeq(x.data, StartSize) + # clear and set to old initial size: + setLen(x.data, 0) + setLen(x.data, StartSize) -proc initIdNodeTable(x: var TIdNodeTable) = +proc initObjectSet*(x: var TObjectSet) = x.counter = 0 newSeq(x.data, StartSize) -proc initNodeTable(x: var TNodeTable) = +proc initIdNodeTable*(x: var TIdNodeTable) = x.counter = 0 newSeq(x.data, StartSize) -proc sonsLen(n: PType): int = - if isNil(n.sons): result = 0 - else: result = len(n.sons) - -proc len*(n: PType): int = - if isNil(n.sons): result = 0 - else: result = len(n.sons) - -proc newSons(father: PType, length: int) = - if isNil(father.sons): - newSeq(father.sons, length) - else: - setLen(father.sons, length) - -proc sonsLen(n: PNode): int = - if isNil(n.sons): result = 0 - else: result = len(n.sons) - -proc newSons(father: PNode, length: int) = - if isNil(father.sons): - newSeq(father.sons, length) - else: - setLen(father.sons, length) +proc initNodeTable*(x: var TNodeTable) = + x.counter = 0 + newSeq(x.data, StartSize) proc skipTypes*(t: PType, kinds: TTypeKinds): PType = ## Used throughout the compiler code to test whether a type tree contains or @@ -1346,26 +1318,27 @@ proc isGCedMem*(t: PType): bool {.inline.} = t.kind == tyProc and t.callConv == ccClosure proc propagateToOwner*(owner, elem: PType) = - const HaveTheirOwnEmpty = {tySequence, tySet} - owner.flags = owner.flags + (elem.flags * {tfHasShared, tfHasMeta}) + const HaveTheirOwnEmpty = {tySequence, tySet, tyPtr, tyRef, tyProc} + owner.flags = owner.flags + (elem.flags * {tfHasMeta}) if tfNotNil in elem.flags: - if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvokation}: + if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvocation}: owner.flags.incl tfNotNil elif owner.kind notin HaveTheirOwnEmpty: owner.flags.incl tfNeedsInit - + if tfNeedsInit in elem.flags: if owner.kind in HaveTheirOwnEmpty: discard else: owner.flags.incl tfNeedsInit - - if tfShared in elem.flags: - owner.flags.incl tfHasShared if elem.isMetaType: owner.flags.incl tfHasMeta - if owner.kind != tyProc: - if elem.isGCedMem or tfHasGCedMem in elem.flags: + if owner.kind notin {tyProc, tyGenericInst, tyGenericBody, + tyGenericInvocation}: + let elemB = elem.skipTypes({tyGenericInst}) + if elemB.isGCedMem or tfHasGCedMem in elemB.flags: + # for simplicity, we propagate this flag even to generics. We then + # ensure this doesn't bite us in sempass2. owner.flags.incl tfHasGCedMem proc rawAddSon*(father, son: PType) = @@ -1373,24 +1346,19 @@ proc rawAddSon*(father, son: PType) = add(father.sons, son) if not son.isNil: propagateToOwner(father, son) -proc addSon(father, son: PNode) = - assert son != nil - if isNil(father.sons): father.sons = @[] - add(father.sons, son) - proc addSonNilAllowed*(father, son: PNode) = if isNil(father.sons): father.sons = @[] add(father.sons, son) -proc delSon(father: PNode, idx: int) = - if isNil(father.sons): return +proc delSon*(father: PNode, idx: int) = + if isNil(father.sons): return var length = sonsLen(father) for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1] setLen(father.sons, length - 1) -proc copyNode(src: PNode): PNode = +proc copyNode*(src: PNode): PNode = # does not copy its sons! - if src == nil: + if src == nil: return nil result = newNode(src.kind) result.info = src.info @@ -1407,7 +1375,7 @@ proc copyNode(src: PNode): PNode = of nkStrLit..nkTripleStrLit: result.strVal = src.strVal else: discard -proc shallowCopy*(src: PNode): PNode = +proc shallowCopy*(src: PNode): PNode = # does not copy its sons, but provides space for them: if src == nil: return nil result = newNode(src.kind) @@ -1425,9 +1393,9 @@ proc shallowCopy*(src: PNode): PNode = of nkStrLit..nkTripleStrLit: result.strVal = src.strVal else: newSeq(result.sons, sonsLen(src)) -proc copyTree(src: PNode): PNode = +proc copyTree*(src: PNode): PNode = # copy a whole syntax tree; performs deep copying - if src == nil: + if src == nil: return nil result = newNode(src.kind) result.info = src.info @@ -1442,26 +1410,20 @@ proc copyTree(src: PNode): PNode = of nkSym: result.sym = src.sym of nkIdent: result.ident = src.ident of nkStrLit..nkTripleStrLit: result.strVal = src.strVal - else: + else: newSeq(result.sons, sonsLen(src)) - for i in countup(0, sonsLen(src) - 1): + for i in countup(0, sonsLen(src) - 1): result.sons[i] = copyTree(src.sons[i]) - -proc lastSon(n: PNode): PNode = - result = n.sons[sonsLen(n) - 1] - -proc lastSon(n: PType): PType = - result = n.sons[sonsLen(n) - 1] -proc hasSonWith(n: PNode, kind: TNodeKind): bool = - for i in countup(0, sonsLen(n) - 1): - if n.sons[i].kind == kind: +proc hasSonWith*(n: PNode, kind: TNodeKind): bool = + for i in countup(0, sonsLen(n) - 1): + if n.sons[i].kind == kind: return true result = false -proc hasNilSon*(n: PNode): bool = - for i in countup(0, safeLen(n) - 1): - if n.sons[i] == nil: +proc hasNilSon*(n: PNode): bool = + for i in countup(0, safeLen(n) - 1): + if n.sons[i] == nil: return true elif hasNilSon(n.sons[i]): return true @@ -1475,47 +1437,47 @@ proc containsNode*(n: PNode, kinds: TNodeKinds): bool = for i in countup(0, sonsLen(n) - 1): if n.kind in kinds or containsNode(n.sons[i], kinds): return true -proc hasSubnodeWith(n: PNode, kind: TNodeKind): bool = +proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool = case n.kind of nkEmpty..nkNilLit: result = n.kind == kind - else: - for i in countup(0, sonsLen(n) - 1): - if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind): + else: + for i in countup(0, sonsLen(n) - 1): + if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind): return true result = false -proc replaceSons(n: PNode, oldKind, newKind: TNodeKind) = - for i in countup(0, sonsLen(n) - 1): +proc replaceSons(n: PNode, oldKind, newKind: TNodeKind) = + for i in countup(0, sonsLen(n) - 1): if n.sons[i].kind == oldKind: n.sons[i].kind = newKind - -proc sonsNotNil(n: PNode): bool = - for i in countup(0, sonsLen(n) - 1): - if n.sons[i] == nil: + +proc sonsNotNil(n: PNode): bool = + for i in countup(0, sonsLen(n) - 1): + if n.sons[i] == nil: return false result = true -proc getInt*(a: PNode): BiggestInt = +proc getInt*(a: PNode): BiggestInt = case a.kind of nkIntLit..nkUInt64Lit: result = a.intVal - else: + else: internalError(a.info, "getInt") result = 0 -proc getFloat*(a: PNode): BiggestFloat = +proc getFloat*(a: PNode): BiggestFloat = case a.kind of nkFloatLit..nkFloat128Lit: result = a.floatVal - else: + else: internalError(a.info, "getFloat") result = 0.0 -proc getStr*(a: PNode): string = +proc getStr*(a: PNode): string = case a.kind of nkStrLit..nkTripleStrLit: result = a.strVal - else: + else: internalError(a.info, "getStr") result = "" -proc getStrOrChar*(a: PNode): string = +proc getStrOrChar*(a: PNode): string = case a.kind of nkStrLit..nkTripleStrLit: result = a.strVal of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal)) @@ -1523,7 +1485,7 @@ proc getStrOrChar*(a: PNode): string = internalError(a.info, "getStrOrChar") result = "" -proc isGenericRoutine*(s: PSym): bool = +proc isGenericRoutine*(s: PSym): bool = case s.kind of skProcKinds: result = sfFromGeneric in s.flags or @@ -1567,3 +1529,11 @@ proc makeStmtList*(n: PNode): PNode = else: result = newNodeI(nkStmtList, n.info) result.add n + +proc createMagic*(name: string, m: TMagic): PSym = + result = newSym(skProc, getIdent(name), nil, unknownLineInfo()) + result.magic = m + +let + opNot* = createMagic("not", mNot) + opContains* = createMagic("contains", mInSet) |