fixes #1940; code breakage! stricter template evaluation
This commit is contained in:
parent
c914532c26
commit
d58212ccc5
6 changed files with 479 additions and 435 deletions
383
compiler/ast.nim
383
compiler/ast.nim
|
|
@ -9,12 +9,12 @@
|
||||||
|
|
||||||
# abstract syntax tree + symbol table
|
# abstract syntax tree + symbol table
|
||||||
|
|
||||||
import
|
import
|
||||||
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists,
|
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists,
|
||||||
intsets, idgen
|
intsets, idgen
|
||||||
|
|
||||||
type
|
type
|
||||||
TCallingConvention* = enum
|
TCallingConvention* = enum
|
||||||
ccDefault, # proc has no explicit calling convention
|
ccDefault, # proc has no explicit calling convention
|
||||||
ccStdCall, # procedure is stdcall
|
ccStdCall, # procedure is stdcall
|
||||||
ccCDecl, # cdecl
|
ccCDecl, # cdecl
|
||||||
|
|
@ -26,12 +26,12 @@ type
|
||||||
ccClosure, # proc has a closure
|
ccClosure, # proc has a closure
|
||||||
ccNoConvention # needed for generating proper C procs sometimes
|
ccNoConvention # needed for generating proper C procs sometimes
|
||||||
|
|
||||||
const
|
const
|
||||||
CallingConvToStr*: array[TCallingConvention, string] = ["", "stdcall",
|
CallingConvToStr*: array[TCallingConvention, string] = ["", "stdcall",
|
||||||
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall",
|
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall",
|
||||||
"closure", "noconv"]
|
"closure", "noconv"]
|
||||||
|
|
||||||
type
|
type
|
||||||
TNodeKind* = enum # order is extremely important, because ranges are used
|
TNodeKind* = enum # order is extremely important, because ranges are used
|
||||||
# to check whether a node belongs to a certain class
|
# to check whether a node belongs to a certain class
|
||||||
nkNone, # unknown node kind: indicates an error
|
nkNone, # unknown node kind: indicates an error
|
||||||
|
|
@ -64,13 +64,13 @@ type
|
||||||
# end of atoms
|
# end of atoms
|
||||||
nkMetaNode_Obsolete, # difficult to explain; represents itself
|
nkMetaNode_Obsolete, # difficult to explain; represents itself
|
||||||
# (used for macros)
|
# (used for macros)
|
||||||
nkDotCall, # used to temporarily flag a nkCall node;
|
nkDotCall, # used to temporarily flag a nkCall node;
|
||||||
# this is used
|
# this is used
|
||||||
# for transforming ``s.len`` to ``len(s)``
|
# for transforming ``s.len`` to ``len(s)``
|
||||||
|
|
||||||
nkCommand, # a call like ``p 2, 4`` without parenthesis
|
nkCommand, # a call like ``p 2, 4`` without parenthesis
|
||||||
nkCall, # a call like p(x, y) or an operation like +(a, b)
|
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, nkRStrLit
|
||||||
# x"""abc""" has two sons: nkIdent, nkTripleStrLit
|
# x"""abc""" has two sons: nkIdent, nkTripleStrLit
|
||||||
nkInfix, # a call like (a + b)
|
nkInfix, # a call like (a + b)
|
||||||
|
|
@ -126,7 +126,7 @@ type
|
||||||
|
|
||||||
nkAsgn, # a = b
|
nkAsgn, # a = b
|
||||||
nkFastAsgn, # internal node for a fast ``a = b``
|
nkFastAsgn, # internal node for a fast ``a = b``
|
||||||
# (no string copy)
|
# (no string copy)
|
||||||
nkGenericParams, # generic parameters
|
nkGenericParams, # generic parameters
|
||||||
nkFormalParams, # formal parameters
|
nkFormalParams, # formal parameters
|
||||||
nkOfInherit, # inherited from symbol
|
nkOfInherit, # inherited from symbol
|
||||||
|
|
@ -192,7 +192,7 @@ type
|
||||||
|
|
||||||
nkWith, # distinct with `foo`
|
nkWith, # distinct with `foo`
|
||||||
nkWithout, # distinct without `foo`
|
nkWithout, # distinct without `foo`
|
||||||
|
|
||||||
nkTypeOfExpr, # type(1+2)
|
nkTypeOfExpr, # type(1+2)
|
||||||
nkObjectTy, # object body
|
nkObjectTy, # object body
|
||||||
nkTupleTy, # tuple body
|
nkTupleTy, # tuple body
|
||||||
|
|
@ -226,7 +226,7 @@ type
|
||||||
TSymFlag* = enum # already 32 flags!
|
TSymFlag* = enum # already 32 flags!
|
||||||
sfUsed, # read access of sym (for warnings) or simply used
|
sfUsed, # read access of sym (for warnings) or simply used
|
||||||
sfExported, # symbol is exported from module
|
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
|
# for symbol file generation; such symbols should always
|
||||||
# be written into the ROD file
|
# be written into the ROD file
|
||||||
sfGlobal, # symbol is at global scope
|
sfGlobal, # symbol is at global scope
|
||||||
|
|
@ -284,9 +284,9 @@ const
|
||||||
|
|
||||||
sfAnon* = sfDiscardable
|
sfAnon* = sfDiscardable
|
||||||
# symbol name that was generated by the compiler
|
# 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.
|
# in user messages.
|
||||||
|
|
||||||
sfNoForward* = sfRegister
|
sfNoForward* = sfRegister
|
||||||
# forward declarations are not required (per module)
|
# forward declarations are not required (per module)
|
||||||
|
|
||||||
|
|
@ -300,7 +300,7 @@ const
|
||||||
# getting ready for the future expr/stmt merge
|
# getting ready for the future expr/stmt merge
|
||||||
nkWhen* = nkWhenStmt
|
nkWhen* = nkWhenStmt
|
||||||
nkWhenExpr* = nkWhenStmt
|
nkWhenExpr* = nkWhenStmt
|
||||||
nkEffectList* = nkArgList
|
nkEffectList* = nkArgList
|
||||||
# hacks ahead: an nkEffectList is a node with 4 children:
|
# hacks ahead: an nkEffectList is a node with 4 children:
|
||||||
exceptionEffects* = 0 # exceptions at position 0
|
exceptionEffects* = 0 # exceptions at position 0
|
||||||
usesEffects* = 1 # read effects at position 1
|
usesEffects* = 1 # read effects at position 1
|
||||||
|
|
@ -321,7 +321,7 @@ type
|
||||||
# unless this is an instance of a generic alias type.
|
# unless this is an instance of a generic alias type.
|
||||||
# then realInstance will be the tyGenericInst of the
|
# then realInstance will be the tyGenericInst of the
|
||||||
# completely (recursively) resolved alias.
|
# completely (recursively) resolved alias.
|
||||||
|
|
||||||
tyGenericParam, # ``a`` in the above patterns
|
tyGenericParam, # ``a`` in the above patterns
|
||||||
tyDistinct,
|
tyDistinct,
|
||||||
tyEnum,
|
tyEnum,
|
||||||
|
|
@ -340,14 +340,14 @@ type
|
||||||
tyInt, tyInt8, tyInt16, tyInt32, tyInt64, # signed integers
|
tyInt, tyInt8, tyInt16, tyInt32, tyInt64, # signed integers
|
||||||
tyFloat, tyFloat32, tyFloat64, tyFloat128,
|
tyFloat, tyFloat32, tyFloat64, tyFloat128,
|
||||||
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64,
|
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64,
|
||||||
tyBigNum,
|
tyBigNum,
|
||||||
tyConst, tyMutable, tyVarargs,
|
tyConst, tyMutable, tyVarargs,
|
||||||
tyIter, # unused
|
tyIter, # unused
|
||||||
tyProxy # used as errornous type (for idetools)
|
tyProxy # used as errornous type (for idetools)
|
||||||
|
|
||||||
tyBuiltInTypeClass #\
|
tyBuiltInTypeClass #\
|
||||||
# Type such as the catch-all object, tuple, seq, etc
|
# Type such as the catch-all object, tuple, seq, etc
|
||||||
|
|
||||||
tyUserTypeClass #\
|
tyUserTypeClass #\
|
||||||
# the body of a user-defined type class
|
# the body of a user-defined type class
|
||||||
|
|
||||||
|
|
@ -357,24 +357,24 @@ type
|
||||||
# tyGenericInst represents concrete types, while
|
# tyGenericInst represents concrete types, while
|
||||||
# this is still a "generic param" that will bind types
|
# this is still a "generic param" that will bind types
|
||||||
# and resolves them during sigmatch and instantiation.
|
# and resolves them during sigmatch and instantiation.
|
||||||
|
|
||||||
tyCompositeTypeClass #\
|
tyCompositeTypeClass #\
|
||||||
# Type such as seq[Number]
|
# 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[0]: the original expression used by the user.
|
||||||
# sons[1]: fully expanded and instantiated meta type
|
# sons[1]: fully expanded and instantiated meta type
|
||||||
# (potentially following aliases)
|
# (potentially following aliases)
|
||||||
|
|
||||||
tyAnd, tyOr, tyNot #\
|
tyAnd, tyOr, tyNot #\
|
||||||
# boolean type classes such as `string|int`,`not seq`,
|
# boolean type classes such as `string|int`,`not seq`,
|
||||||
# `Sortable and Enumable`, etc
|
# `Sortable and Enumable`, etc
|
||||||
|
|
||||||
tyAnything #\
|
tyAnything #\
|
||||||
# a type class matching any type
|
# a type class matching any type
|
||||||
|
|
||||||
tyStatic #\
|
tyStatic #\
|
||||||
# a value known at compile type (the underlying type is .base)
|
# a value known at compile type (the underlying type is .base)
|
||||||
|
|
||||||
tyFromExpr #\
|
tyFromExpr #\
|
||||||
# This is a type representing an expression that depends
|
# This is a type representing an expression that depends
|
||||||
# on generic parameters (the expression is stored in t.n)
|
# on generic parameters (the expression is stored in t.n)
|
||||||
|
|
@ -390,7 +390,7 @@ type
|
||||||
# sons[0]: type of containing object or tuple
|
# sons[0]: type of containing object or tuple
|
||||||
# sons[1]: field type
|
# sons[1]: field type
|
||||||
# .n: nkDotExpr storing the field name
|
# .n: nkDotExpr storing the field name
|
||||||
|
|
||||||
static:
|
static:
|
||||||
# remind us when TTypeKind stops to fit in a single 64-bit word
|
# remind us when TTypeKind stops to fit in a single 64-bit word
|
||||||
assert TTypeKind.high.ord <= 63
|
assert TTypeKind.high.ord <= 63
|
||||||
|
|
@ -408,7 +408,7 @@ const
|
||||||
tyAnd, tyOr, tyNot, tyAnything}
|
tyAnd, tyOr, tyNot, tyAnything}
|
||||||
|
|
||||||
tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyExpr} + tyTypeClasses
|
tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyExpr} + tyTypeClasses
|
||||||
|
|
||||||
type
|
type
|
||||||
TTypeKinds* = set[TTypeKind]
|
TTypeKinds* = set[TTypeKind]
|
||||||
|
|
||||||
|
|
@ -429,7 +429,7 @@ type
|
||||||
nfExprCall # this is an attempt to call a regular expression
|
nfExprCall # this is an attempt to call a regular expression
|
||||||
nfIsRef # this node is a 'ref' node; used for the VM
|
nfIsRef # this node is a 'ref' node; used for the VM
|
||||||
nfIsCursor # this node is attached a cursor; used for idetools
|
nfIsCursor # this node is attached a cursor; used for idetools
|
||||||
|
|
||||||
TNodeFlags* = set[TNodeFlag]
|
TNodeFlags* = set[TNodeFlag]
|
||||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 28)
|
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 28)
|
||||||
tfVarargs, # procedure has C styled varargs
|
tfVarargs, # procedure has C styled varargs
|
||||||
|
|
@ -448,7 +448,7 @@ type
|
||||||
# proc foo(L: static[int]): array[L, int]
|
# proc foo(L: static[int]): array[L, int]
|
||||||
# can be attached to ranges to indicate that the range
|
# can be attached to ranges to indicate that the range
|
||||||
# depends on unresolved static params.
|
# 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)
|
# used as return types for return type inference)
|
||||||
tfCapturesEnv, # whether proc really captures some environment
|
tfCapturesEnv, # whether proc really captures some environment
|
||||||
tfByCopy, # pass object/tuple by copy (C backend)
|
tfByCopy, # pass object/tuple by copy (C backend)
|
||||||
|
|
@ -456,7 +456,7 @@ type
|
||||||
tfIterator, # type is really an iterator, not a tyProc
|
tfIterator, # type is really an iterator, not a tyProc
|
||||||
tfShared, # type is 'shared'
|
tfShared, # type is 'shared'
|
||||||
tfNotNil, # type cannot be 'nil'
|
tfNotNil, # type cannot be 'nil'
|
||||||
|
|
||||||
tfNeedsInit, # type constains a "not nil" constraint somewhere or some
|
tfNeedsInit, # type constains a "not nil" constraint somewhere or some
|
||||||
# other type so that it requires inititalization
|
# other type so that it requires inititalization
|
||||||
tfVarIsPtr, # 'var' type is translated like 'ptr' even in C++ mode
|
tfVarIsPtr, # 'var' type is translated like 'ptr' even in C++ mode
|
||||||
|
|
@ -520,7 +520,7 @@ const
|
||||||
tfGcSafe* = tfThread
|
tfGcSafe* = tfThread
|
||||||
tfObjHasKids* = tfEnumHasHoles
|
tfObjHasKids* = tfEnumHasHoles
|
||||||
skError* = skUnknown
|
skError* = skUnknown
|
||||||
|
|
||||||
# type flags that are essential for type equality:
|
# type flags that are essential for type equality:
|
||||||
eqTypeFlags* = {tfIterator, tfShared, tfNotNil, tfVarIsPtr}
|
eqTypeFlags* = {tfIterator, tfShared, tfNotNil, tfVarIsPtr}
|
||||||
|
|
||||||
|
|
@ -531,29 +531,29 @@ type
|
||||||
mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf,
|
mLow, mHigh, mSizeOf, mTypeTrait, mIs, mOf,
|
||||||
mEcho, mShallowCopy, mSlurp, mStaticExec,
|
mEcho, mShallowCopy, mSlurp, mStaticExec,
|
||||||
mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
|
mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
|
||||||
mUnaryLt, mSucc,
|
mUnaryLt, mSucc,
|
||||||
mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray,
|
mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray,
|
||||||
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref,
|
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref,
|
||||||
mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64,
|
mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64,
|
||||||
mDivI64, mModI64,
|
mDivI64, mModI64,
|
||||||
mAddF64, mSubF64, mMulF64, mDivF64,
|
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,
|
mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, mMaxI64,
|
||||||
mMinF64, mMaxF64, mAddU, mSubU, mMulU,
|
mMinF64, mMaxF64, mAddU, mSubU, mMulU,
|
||||||
mDivU, mModU, mEqI, mLeI,
|
mDivU, mModU, mEqI, mLeI,
|
||||||
mLtI,
|
mLtI,
|
||||||
mEqI64, mLeI64, mLtI64, mEqF64, mLeF64, mLtF64,
|
mEqI64, mLeI64, mLtI64, mEqF64, mLeF64, mLtF64,
|
||||||
mLeU, mLtU, mLeU64, mLtU64,
|
mLeU, mLtU, mLeU64, mLtU64,
|
||||||
mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef,
|
mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef,
|
||||||
mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mEqProc, mUnaryMinusI,
|
mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mEqProc, mUnaryMinusI,
|
||||||
mUnaryMinusI64, mAbsI, mAbsI64, mNot,
|
mUnaryMinusI64, mAbsI, mAbsI64, mNot,
|
||||||
mUnaryPlusI, mBitnotI, mUnaryPlusI64,
|
mUnaryPlusI, mBitnotI, mUnaryPlusI64,
|
||||||
mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, mZe8ToI64,
|
mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, mZe8ToI64,
|
||||||
mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, mToU16, mToU32,
|
mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, mToU16, mToU32,
|
||||||
mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, mCharToStr, mBoolToStr,
|
mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, mCharToStr, mBoolToStr,
|
||||||
mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr,
|
mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr,
|
||||||
mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
|
mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
|
||||||
mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT,
|
mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT,
|
||||||
mConTArr, mConTT, mSlice,
|
mConTArr, mConTT, mSlice,
|
||||||
mFields, mFieldPairs, mOmpParFor,
|
mFields, mFieldPairs, mOmpParFor,
|
||||||
mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
||||||
|
|
@ -584,36 +584,36 @@ type
|
||||||
|
|
||||||
# things that we can evaluate safely at compile time, even if not asked for it:
|
# things that we can evaluate safely at compile time, even if not asked for it:
|
||||||
const
|
const
|
||||||
ctfeWhitelist* = {mNone, mUnaryLt, mSucc,
|
ctfeWhitelist* = {mNone, mUnaryLt, mSucc,
|
||||||
mPred, mInc, mDec, mOrd, mLengthOpenArray,
|
mPred, mInc, mDec, mOrd, mLengthOpenArray,
|
||||||
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr,
|
mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr,
|
||||||
mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64,
|
mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64,
|
||||||
mDivI64, mModI64, mAddF64, mSubF64, mMulF64, mDivF64,
|
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,
|
mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, mMaxI64,
|
||||||
mMinF64, mMaxF64, mAddU, mSubU, mMulU,
|
mMinF64, mMaxF64, mAddU, mSubU, mMulU,
|
||||||
mDivU, mModU, mEqI, mLeI,
|
mDivU, mModU, mEqI, mLeI,
|
||||||
mLtI,
|
mLtI,
|
||||||
mEqI64, mLeI64, mLtI64, mEqF64, mLeF64, mLtF64,
|
mEqI64, mLeI64, mLtI64, mEqF64, mLeF64, mLtF64,
|
||||||
mLeU, mLtU, mLeU64, mLtU64,
|
mLeU, mLtU, mLeU64, mLtU64,
|
||||||
mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef,
|
mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, mEqRef,
|
||||||
mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mUnaryMinusI,
|
mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mUnaryMinusI,
|
||||||
mUnaryMinusI64, mAbsI, mAbsI64, mNot,
|
mUnaryMinusI64, mAbsI, mAbsI64, mNot,
|
||||||
mUnaryPlusI, mBitnotI, mUnaryPlusI64,
|
mUnaryPlusI, mBitnotI, mUnaryPlusI64,
|
||||||
mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, mZe8ToI64,
|
mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, mZe8ToI64,
|
||||||
mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, mToU16, mToU32,
|
mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, mToU16, mToU32,
|
||||||
mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, mCharToStr, mBoolToStr,
|
mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, mCharToStr, mBoolToStr,
|
||||||
mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr,
|
mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr,
|
||||||
mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
|
mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
|
||||||
mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT,
|
mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT,
|
||||||
mConTArr, mConTT,
|
mConTArr, mConTT,
|
||||||
mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
||||||
mInRange, mInSet, mRepr,
|
mInRange, mInSet, mRepr,
|
||||||
mCopyStr, mCopyStrLast}
|
mCopyStr, mCopyStrLast}
|
||||||
# magics that require special semantic checking and
|
# magics that require special semantic checking and
|
||||||
# thus cannot be overloaded (also documented in the spec!):
|
# thus cannot be overloaded (also documented in the spec!):
|
||||||
SpecialSemMagics* = {
|
SpecialSemMagics* = {
|
||||||
mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf,
|
mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf,
|
||||||
mEcho, mShallowCopy, mExpandToAst, mParallel, mSpawn, mAstToStr}
|
mEcho, mShallowCopy, mExpandToAst, mParallel, mSpawn, mAstToStr}
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -634,21 +634,21 @@ type
|
||||||
floatVal*: BiggestFloat
|
floatVal*: BiggestFloat
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
strVal*: string
|
strVal*: string
|
||||||
of nkSym:
|
of nkSym:
|
||||||
sym*: PSym
|
sym*: PSym
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
ident*: PIdent
|
ident*: PIdent
|
||||||
else:
|
else:
|
||||||
sons*: TNodeSeq
|
sons*: TNodeSeq
|
||||||
comment*: string
|
comment*: string
|
||||||
|
|
||||||
TSymSeq* = seq[PSym]
|
TSymSeq* = seq[PSym]
|
||||||
TStrTable* = object # a table[PIdent] of PSym
|
TStrTable* = object # a table[PIdent] of PSym
|
||||||
counter*: int
|
counter*: int
|
||||||
data*: TSymSeq
|
data*: TSymSeq
|
||||||
|
|
||||||
# -------------- backend information -------------------------------
|
# -------------- backend information -------------------------------
|
||||||
TLocKind* = enum
|
TLocKind* = enum
|
||||||
locNone, # no location
|
locNone, # no location
|
||||||
locTemp, # temporary location
|
locTemp, # temporary location
|
||||||
locLocalVar, # location is a local variable
|
locLocalVar, # location is a local variable
|
||||||
|
|
@ -660,7 +660,7 @@ type
|
||||||
locData, # location is a constant
|
locData, # location is a constant
|
||||||
locCall, # location is a call expression
|
locCall, # location is a call expression
|
||||||
locOther # location is something other
|
locOther # location is something other
|
||||||
TLocFlag* = enum
|
TLocFlag* = enum
|
||||||
lfIndirect, # backend introduced a pointer
|
lfIndirect, # backend introduced a pointer
|
||||||
lfParamCopy, # backend introduced a parameter copy (LLVM)
|
lfParamCopy, # backend introduced a parameter copy (LLVM)
|
||||||
lfNoDeepCopy, # no need for a deep copy
|
lfNoDeepCopy, # no need for a deep copy
|
||||||
|
|
@ -670,13 +670,13 @@ type
|
||||||
lfHeader, # include header file for symbol
|
lfHeader, # include header file for symbol
|
||||||
lfImportCompilerProc, # ``importc`` of a compilerproc
|
lfImportCompilerProc, # ``importc`` of a compilerproc
|
||||||
lfSingleUse # no location yet and will only be used once
|
lfSingleUse # no location yet and will only be used once
|
||||||
TStorageLoc* = enum
|
TStorageLoc* = enum
|
||||||
OnUnknown, # location is unknown (stack, heap or static)
|
OnUnknown, # location is unknown (stack, heap or static)
|
||||||
OnStack, # location is on hardware stack
|
OnStack, # location is on hardware stack
|
||||||
OnHeap # location is on heap or global
|
OnHeap # location is on heap or global
|
||||||
# (reference counting needed)
|
# (reference counting needed)
|
||||||
TLocFlags* = set[TLocFlag]
|
TLocFlags* = set[TLocFlag]
|
||||||
TLoc* = object
|
TLoc* = object
|
||||||
k*: TLocKind # kind of location
|
k*: TLocKind # kind of location
|
||||||
s*: TStorageLoc
|
s*: TStorageLoc
|
||||||
flags*: TLocFlags # location's flags
|
flags*: TLocFlags # location's flags
|
||||||
|
|
@ -688,7 +688,7 @@ type
|
||||||
|
|
||||||
# ---------------- end of backend information ------------------------------
|
# ---------------- end of backend information ------------------------------
|
||||||
|
|
||||||
TLibKind* = enum
|
TLibKind* = enum
|
||||||
libHeader, libDynamic
|
libHeader, libDynamic
|
||||||
TLib* = object of lists.TListEntry # also misused for headers!
|
TLib* = object of lists.TListEntry # also misused for headers!
|
||||||
kind*: TLibKind
|
kind*: TLibKind
|
||||||
|
|
@ -696,17 +696,17 @@ type
|
||||||
isOverriden*: bool
|
isOverriden*: bool
|
||||||
name*: PRope
|
name*: PRope
|
||||||
path*: PNode # can be a string literal!
|
path*: PNode # can be a string literal!
|
||||||
|
|
||||||
TInstantiation* = object
|
TInstantiation* = object
|
||||||
sym*: PSym
|
sym*: PSym
|
||||||
concreteTypes*: seq[PType]
|
concreteTypes*: seq[PType]
|
||||||
usedBy*: seq[int32] # list of modules using the generic
|
usedBy*: seq[int32] # list of modules using the generic
|
||||||
# needed in caas mode for purging the cache
|
# 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
|
# simple ref count here
|
||||||
|
|
||||||
PInstantiation* = ref TInstantiation
|
PInstantiation* = ref TInstantiation
|
||||||
|
|
||||||
TScope* = object
|
TScope* = object
|
||||||
depthLevel*: int
|
depthLevel*: int
|
||||||
symbols*: TStrTable
|
symbols*: TStrTable
|
||||||
|
|
@ -773,7 +773,7 @@ type
|
||||||
constraint*: PNode # additional constraints like 'lit|result'; also
|
constraint*: PNode # additional constraints like 'lit|result'; also
|
||||||
# misused for the codegenDecl pragma in the hope
|
# misused for the codegenDecl pragma in the hope
|
||||||
# it won't cause problems
|
# it won't cause problems
|
||||||
|
|
||||||
TTypeSeq* = seq[PType]
|
TTypeSeq* = seq[PType]
|
||||||
TLockLevel* = distinct int16
|
TLockLevel* = distinct int16
|
||||||
TType* {.acyclic.} = object of TIdObj # \
|
TType* {.acyclic.} = object of TIdObj # \
|
||||||
|
|
@ -806,7 +806,7 @@ type
|
||||||
lockLevel*: TLockLevel # lock level as required for deadlock checking
|
lockLevel*: TLockLevel # lock level as required for deadlock checking
|
||||||
loc*: TLoc
|
loc*: TLoc
|
||||||
|
|
||||||
TPair*{.final.} = object
|
TPair*{.final.} = object
|
||||||
key*, val*: RootRef
|
key*, val*: RootRef
|
||||||
|
|
||||||
TPairSeq* = seq[TPair]
|
TPairSeq* = seq[TPair]
|
||||||
|
|
@ -814,7 +814,7 @@ type
|
||||||
counter*: int
|
counter*: int
|
||||||
data*: TPairSeq
|
data*: TPairSeq
|
||||||
|
|
||||||
TIdPair*{.final.} = object
|
TIdPair*{.final.} = object
|
||||||
key*: PIdObj
|
key*: PIdObj
|
||||||
val*: RootRef
|
val*: RootRef
|
||||||
|
|
||||||
|
|
@ -823,7 +823,7 @@ type
|
||||||
counter*: int
|
counter*: int
|
||||||
data*: TIdPairSeq
|
data*: TIdPairSeq
|
||||||
|
|
||||||
TIdNodePair*{.final.} = object
|
TIdNodePair*{.final.} = object
|
||||||
key*: PIdObj
|
key*: PIdObj
|
||||||
val*: PNode
|
val*: PNode
|
||||||
|
|
||||||
|
|
@ -832,7 +832,7 @@ type
|
||||||
counter*: int
|
counter*: int
|
||||||
data*: TIdNodePairSeq
|
data*: TIdNodePairSeq
|
||||||
|
|
||||||
TNodePair*{.final.} = object
|
TNodePair*{.final.} = object
|
||||||
h*: THash # because it is expensive to compute!
|
h*: THash # because it is expensive to compute!
|
||||||
key*: PNode
|
key*: PNode
|
||||||
val*: int
|
val*: int
|
||||||
|
|
@ -844,7 +844,7 @@ type
|
||||||
data*: TNodePairSeq
|
data*: TNodePairSeq
|
||||||
|
|
||||||
TObjectSeq* = seq[RootRef]
|
TObjectSeq* = seq[RootRef]
|
||||||
TObjectSet*{.final.} = object
|
TObjectSet*{.final.} = object
|
||||||
counter*: int
|
counter*: int
|
||||||
data*: TObjectSeq
|
data*: TObjectSeq
|
||||||
|
|
||||||
|
|
@ -855,27 +855,27 @@ type
|
||||||
# same name as an imported module. This is necessary because of
|
# same name as an imported module. This is necessary because of
|
||||||
# the poor naming choices in the standard library.
|
# the poor naming choices in the standard library.
|
||||||
|
|
||||||
const
|
const
|
||||||
OverloadableSyms* = {skProc, skMethod, skIterator, skClosureIterator,
|
OverloadableSyms* = {skProc, skMethod, skIterator, skClosureIterator,
|
||||||
skConverter, skModule, skTemplate, skMacro}
|
skConverter, skModule, skTemplate, skMacro}
|
||||||
|
|
||||||
GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody,
|
GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody,
|
||||||
tyGenericParam}
|
tyGenericParam}
|
||||||
|
|
||||||
StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray,
|
StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray,
|
||||||
tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyOpenArray,
|
tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyOpenArray,
|
||||||
tyVarargs}
|
tyVarargs}
|
||||||
|
|
||||||
ConcreteTypes*: TTypeKinds = { # types of the expr that may occur in::
|
ConcreteTypes*: TTypeKinds = { # types of the expr that may occur in::
|
||||||
# var x = expr
|
# var x = expr
|
||||||
tyBool, tyChar, tyEnum, tyArray, tyObject,
|
tyBool, tyChar, tyEnum, tyArray, tyObject,
|
||||||
tySet, tyTuple, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc,
|
tySet, tyTuple, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc,
|
||||||
tyPointer,
|
tyPointer,
|
||||||
tyOpenArray, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128,
|
tyOpenArray, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128,
|
||||||
tyUInt..tyUInt64}
|
tyUInt..tyUInt64}
|
||||||
IntegralTypes* = {tyBool, tyChar, tyEnum, tyInt..tyInt64,
|
IntegralTypes* = {tyBool, tyChar, tyEnum, tyInt..tyInt64,
|
||||||
tyFloat..tyFloat128, tyUInt..tyUInt64}
|
tyFloat..tyFloat128, tyUInt..tyUInt64}
|
||||||
ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet,
|
ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet,
|
||||||
tyTuple, tySequence}
|
tyTuple, tySequence}
|
||||||
NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
|
NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
|
||||||
tyProc, tyString, tyError}
|
tyProc, tyString, tyError}
|
||||||
|
|
@ -926,17 +926,17 @@ proc discardSons*(father: PNode)
|
||||||
proc len*(n: PNode): int {.inline.} =
|
proc len*(n: PNode): int {.inline.} =
|
||||||
if isNil(n.sons): result = 0
|
if isNil(n.sons): result = 0
|
||||||
else: result = len(n.sons)
|
else: result = len(n.sons)
|
||||||
|
|
||||||
proc safeLen*(n: PNode): int {.inline.} =
|
proc safeLen*(n: PNode): int {.inline.} =
|
||||||
## works even for leaves.
|
## works even for leaves.
|
||||||
if n.kind in {nkNone..nkNilLit} or isNil(n.sons): result = 0
|
if n.kind in {nkNone..nkNilLit} or isNil(n.sons): result = 0
|
||||||
else: result = len(n.sons)
|
else: result = len(n.sons)
|
||||||
|
|
||||||
proc add*(father, son: PNode) =
|
proc add*(father, son: PNode) =
|
||||||
assert son != nil
|
assert son != nil
|
||||||
if isNil(father.sons): father.sons = @[]
|
if isNil(father.sons): father.sons = @[]
|
||||||
add(father.sons, son)
|
add(father.sons, son)
|
||||||
|
|
||||||
proc `[]`*(n: PNode, i: int): PNode {.inline.} =
|
proc `[]`*(n: PNode, i: int): PNode {.inline.} =
|
||||||
result = n.sons[i]
|
result = n.sons[i]
|
||||||
|
|
||||||
|
|
@ -946,13 +946,10 @@ template `{}=`*(n: PNode, i: int, s: PNode): stmt =
|
||||||
n.sons[i -| n] = s
|
n.sons[i -| n] = s
|
||||||
|
|
||||||
when defined(useNodeIds):
|
when defined(useNodeIds):
|
||||||
const nodeIdToDebug* = -1 # 884953 # 612794
|
const nodeIdToDebug* = -1 # 299750 # 300761 #300863 # 300879
|
||||||
#612840 # 612905 # 614635 # 614637 # 614641
|
|
||||||
# 423408
|
|
||||||
#429107 # 430443 # 441048 # 441090 # 441153
|
|
||||||
var gNodeId: int
|
var gNodeId: int
|
||||||
|
|
||||||
proc newNode*(kind: TNodeKind): PNode =
|
proc newNode*(kind: TNodeKind): PNode =
|
||||||
new(result)
|
new(result)
|
||||||
result.kind = kind
|
result.kind = kind
|
||||||
#result.info = UnknownLineInfo() inlined:
|
#result.info = UnknownLineInfo() inlined:
|
||||||
|
|
@ -966,24 +963,24 @@ proc newNode*(kind: TNodeKind): PNode =
|
||||||
writeStackTrace()
|
writeStackTrace()
|
||||||
inc gNodeId
|
inc gNodeId
|
||||||
|
|
||||||
proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode =
|
proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode =
|
||||||
result = newNode(kind)
|
result = newNode(kind)
|
||||||
result.intVal = intVal
|
result.intVal = intVal
|
||||||
|
|
||||||
proc newIntTypeNode*(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode =
|
proc newIntTypeNode*(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode =
|
||||||
result = newIntNode(kind, intVal)
|
result = newIntNode(kind, intVal)
|
||||||
result.typ = typ
|
result.typ = typ
|
||||||
|
|
||||||
proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode =
|
proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode =
|
||||||
result = newNode(kind)
|
result = newNode(kind)
|
||||||
result.floatVal = floatVal
|
result.floatVal = floatVal
|
||||||
|
|
||||||
proc newStrNode*(kind: TNodeKind, strVal: string): PNode =
|
proc newStrNode*(kind: TNodeKind, strVal: string): PNode =
|
||||||
result = newNode(kind)
|
result = newNode(kind)
|
||||||
result.strVal = strVal
|
result.strVal = strVal
|
||||||
|
|
||||||
proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
|
proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
# generates a symbol and initializes the hash field too
|
# generates a symbol and initializes the hash field too
|
||||||
new(result)
|
new(result)
|
||||||
result.name = name
|
result.name = name
|
||||||
|
|
@ -994,7 +991,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
|
||||||
result.owner = owner
|
result.owner = owner
|
||||||
result.offset = - 1
|
result.offset = - 1
|
||||||
result.id = getID()
|
result.id = getID()
|
||||||
when debugIds:
|
when debugIds:
|
||||||
registerId(result)
|
registerId(result)
|
||||||
#if result.id < 2000:
|
#if result.id < 2000:
|
||||||
# MessageOut(name.s & " has id: " & toString(result.id))
|
# MessageOut(name.s & " has id: " & toString(result.id))
|
||||||
|
|
@ -1036,54 +1033,54 @@ proc appendToModule*(m: PSym, n: PNode) =
|
||||||
else:
|
else:
|
||||||
assert m.ast.kind == nkStmtList
|
assert m.ast.kind == nkStmtList
|
||||||
m.ast.sons.add(n)
|
m.ast.sons.add(n)
|
||||||
|
|
||||||
const # for all kind of hash tables:
|
const # for all kind of hash tables:
|
||||||
GrowthFactor* = 2 # must be power of 2, > 0
|
GrowthFactor* = 2 # must be power of 2, > 0
|
||||||
StartSize* = 8 # 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
|
dest.counter = src.counter
|
||||||
if isNil(src.data): return
|
if isNil(src.data): return
|
||||||
setLen(dest.data, len(src.data))
|
setLen(dest.data, len(src.data))
|
||||||
for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
|
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
|
dest.counter = src.counter
|
||||||
if isNil(src.data): return
|
if isNil(src.data): return
|
||||||
newSeq(dest.data, len(src.data))
|
newSeq(dest.data, len(src.data))
|
||||||
for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
|
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
|
dest.counter = src.counter
|
||||||
if isNil(src.data): return
|
if isNil(src.data): return
|
||||||
setLen(dest.data, len(src.data))
|
setLen(dest.data, len(src.data))
|
||||||
for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
|
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
|
dest.counter = src.counter
|
||||||
if isNil(src.data): return
|
if isNil(src.data): return
|
||||||
setLen(dest.data, len(src.data))
|
setLen(dest.data, len(src.data))
|
||||||
for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
|
for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
|
||||||
|
|
||||||
proc discardSons*(father: PNode) =
|
proc discardSons*(father: PNode) =
|
||||||
father.sons = nil
|
father.sons = nil
|
||||||
|
|
||||||
proc withInfo*(n: PNode, info: TLineInfo): PNode =
|
proc withInfo*(n: PNode, info: TLineInfo): PNode =
|
||||||
n.info = info
|
n.info = info
|
||||||
return n
|
return n
|
||||||
|
|
||||||
proc newIdentNode*(ident: PIdent, info: TLineInfo): PNode =
|
proc newIdentNode*(ident: PIdent, info: TLineInfo): PNode =
|
||||||
result = newNode(nkIdent)
|
result = newNode(nkIdent)
|
||||||
result.ident = ident
|
result.ident = ident
|
||||||
result.info = info
|
result.info = info
|
||||||
|
|
||||||
proc newSymNode*(sym: PSym): PNode =
|
proc newSymNode*(sym: PSym): PNode =
|
||||||
result = newNode(nkSym)
|
result = newNode(nkSym)
|
||||||
result.sym = sym
|
result.sym = sym
|
||||||
result.typ = sym.typ
|
result.typ = sym.typ
|
||||||
result.info = sym.info
|
result.info = sym.info
|
||||||
|
|
||||||
proc newSymNode*(sym: PSym, info: TLineInfo): PNode =
|
proc newSymNode*(sym: PSym, info: TLineInfo): PNode =
|
||||||
result = newNode(nkSym)
|
result = newNode(nkSym)
|
||||||
result.sym = sym
|
result.sym = sym
|
||||||
result.typ = sym.typ
|
result.typ = sym.typ
|
||||||
|
|
@ -1128,12 +1125,12 @@ proc newNode*(kind: TNodeKind, info: TLineInfo, sons: TNodeSeq = @[],
|
||||||
writeStackTrace()
|
writeStackTrace()
|
||||||
inc gNodeId
|
inc gNodeId
|
||||||
|
|
||||||
proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode =
|
proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode =
|
||||||
result = newNode(kind)
|
result = newNode(kind)
|
||||||
result.info = info
|
result.info = info
|
||||||
result.typ = typ
|
result.typ = typ
|
||||||
|
|
||||||
proc addSon*(father, son: PNode) =
|
proc addSon*(father, son: PNode) =
|
||||||
assert son != nil
|
assert son != nil
|
||||||
if isNil(father.sons): father.sons = @[]
|
if isNil(father.sons): father.sons = @[]
|
||||||
add(father.sons, son)
|
add(father.sons, son)
|
||||||
|
|
@ -1159,7 +1156,7 @@ proc `$`*(x: TLockLevel): string =
|
||||||
elif x.ord == UnknownLockLevel.ord: result = "<unknown>"
|
elif x.ord == UnknownLockLevel.ord: result = "<unknown>"
|
||||||
else: result = $int16(x)
|
else: result = $int16(x)
|
||||||
|
|
||||||
proc newType*(kind: TTypeKind, owner: PSym): PType =
|
proc newType*(kind: TTypeKind, owner: PSym): PType =
|
||||||
new(result)
|
new(result)
|
||||||
result.kind = kind
|
result.kind = kind
|
||||||
result.owner = owner
|
result.owner = owner
|
||||||
|
|
@ -1171,7 +1168,7 @@ proc newType*(kind: TTypeKind, owner: PSym): PType =
|
||||||
registerId(result)
|
registerId(result)
|
||||||
#if result.id < 2000:
|
#if result.id < 2000:
|
||||||
# messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
|
# messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
|
||||||
|
|
||||||
proc mergeLoc(a: var TLoc, b: TLoc) =
|
proc mergeLoc(a: var TLoc, b: TLoc) =
|
||||||
if a.k == low(a.k): a.k = b.k
|
if a.k == low(a.k): a.k = b.k
|
||||||
if a.s == low(a.s): a.s = b.s
|
if a.s == low(a.s): a.s = b.s
|
||||||
|
|
@ -1180,37 +1177,37 @@ proc mergeLoc(a: var TLoc, b: TLoc) =
|
||||||
if a.r == nil: a.r = b.r
|
if a.r == nil: a.r = b.r
|
||||||
#if a.a == 0: a.a = b.a
|
#if a.a == 0: a.a = b.a
|
||||||
|
|
||||||
proc newSons*(father: PNode, length: int) =
|
proc newSons*(father: PNode, length: int) =
|
||||||
if isNil(father.sons):
|
if isNil(father.sons):
|
||||||
newSeq(father.sons, length)
|
newSeq(father.sons, length)
|
||||||
else:
|
else:
|
||||||
setLen(father.sons, length)
|
setLen(father.sons, length)
|
||||||
|
|
||||||
proc newSons*(father: PType, length: int) =
|
proc newSons*(father: PType, length: int) =
|
||||||
if isNil(father.sons):
|
if isNil(father.sons):
|
||||||
newSeq(father.sons, length)
|
newSeq(father.sons, length)
|
||||||
else:
|
else:
|
||||||
setLen(father.sons, length)
|
setLen(father.sons, length)
|
||||||
|
|
||||||
proc sonsLen*(n: PType): int =
|
proc sonsLen*(n: PType): int =
|
||||||
if isNil(n.sons): result = 0
|
if isNil(n.sons): result = 0
|
||||||
else: result = len(n.sons)
|
else: result = len(n.sons)
|
||||||
|
|
||||||
proc len*(n: PType): int =
|
proc len*(n: PType): int =
|
||||||
if isNil(n.sons): result = 0
|
if isNil(n.sons): result = 0
|
||||||
else: result = len(n.sons)
|
else: result = len(n.sons)
|
||||||
|
|
||||||
proc sonsLen*(n: PNode): int =
|
proc sonsLen*(n: PNode): int =
|
||||||
if isNil(n.sons): result = 0
|
if isNil(n.sons): result = 0
|
||||||
else: result = len(n.sons)
|
else: result = len(n.sons)
|
||||||
|
|
||||||
proc lastSon*(n: PNode): PNode =
|
proc lastSon*(n: PNode): PNode =
|
||||||
result = n.sons[sonsLen(n) - 1]
|
result = n.sons[sonsLen(n) - 1]
|
||||||
|
|
||||||
proc lastSon*(n: PType): PType =
|
proc lastSon*(n: PType): PType =
|
||||||
result = n.sons[sonsLen(n) - 1]
|
result = n.sons[sonsLen(n) - 1]
|
||||||
|
|
||||||
proc assignType*(dest, src: PType) =
|
proc assignType*(dest, src: PType) =
|
||||||
dest.kind = src.kind
|
dest.kind = src.kind
|
||||||
dest.flags = src.flags
|
dest.flags = src.flags
|
||||||
dest.callConv = src.callConv
|
dest.callConv = src.callConv
|
||||||
|
|
@ -1230,23 +1227,23 @@ proc assignType*(dest, src: PType) =
|
||||||
dest.sym = src.sym
|
dest.sym = src.sym
|
||||||
newSons(dest, sonsLen(src))
|
newSons(dest, sonsLen(src))
|
||||||
for i in countup(0, sonsLen(src) - 1): dest.sons[i] = src.sons[i]
|
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)
|
result = newType(t.kind, owner)
|
||||||
assignType(result, t)
|
assignType(result, t)
|
||||||
if keepId:
|
if keepId:
|
||||||
result.id = t.id
|
result.id = t.id
|
||||||
else:
|
else:
|
||||||
when debugIds: registerId(result)
|
when debugIds: registerId(result)
|
||||||
result.sym = t.sym # backend-info should not be copied
|
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 = newSym(s.kind, s.name, s.owner, s.info)
|
||||||
#result.ast = nil # BUGFIX; was: s.ast which made problems
|
#result.ast = nil # BUGFIX; was: s.ast which made problems
|
||||||
result.typ = s.typ
|
result.typ = s.typ
|
||||||
if keepId:
|
if keepId:
|
||||||
result.id = s.id
|
result.id = s.id
|
||||||
else:
|
else:
|
||||||
result.id = getID()
|
result.id = getID()
|
||||||
when debugIds: registerId(result)
|
when debugIds: registerId(result)
|
||||||
result.flags = s.flags
|
result.flags = s.flags
|
||||||
|
|
@ -1273,19 +1270,19 @@ proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym =
|
||||||
result.annex = s.annex
|
result.annex = s.annex
|
||||||
# XXX once usedGenerics is used, ensure module aliases keep working!
|
# XXX once usedGenerics is used, ensure module aliases keep working!
|
||||||
assert s.usedGenerics == nil
|
assert s.usedGenerics == nil
|
||||||
|
|
||||||
proc initStrTable*(x: var TStrTable) =
|
proc initStrTable*(x: var TStrTable) =
|
||||||
x.counter = 0
|
x.counter = 0
|
||||||
newSeq(x.data, StartSize)
|
newSeq(x.data, StartSize)
|
||||||
|
|
||||||
proc newStrTable*: TStrTable =
|
proc newStrTable*: TStrTable =
|
||||||
initStrTable(result)
|
initStrTable(result)
|
||||||
|
|
||||||
proc initTable(x: var TTable) =
|
proc initTable(x: var TTable) =
|
||||||
x.counter = 0
|
x.counter = 0
|
||||||
newSeq(x.data, StartSize)
|
newSeq(x.data, StartSize)
|
||||||
|
|
||||||
proc initIdTable*(x: var TIdTable) =
|
proc initIdTable*(x: var TIdTable) =
|
||||||
x.counter = 0
|
x.counter = 0
|
||||||
newSeq(x.data, StartSize)
|
newSeq(x.data, StartSize)
|
||||||
|
|
||||||
|
|
@ -1295,15 +1292,15 @@ proc resetIdTable*(x: var TIdTable) =
|
||||||
setLen(x.data, 0)
|
setLen(x.data, 0)
|
||||||
setLen(x.data, StartSize)
|
setLen(x.data, StartSize)
|
||||||
|
|
||||||
proc initObjectSet*(x: var TObjectSet) =
|
proc initObjectSet*(x: var TObjectSet) =
|
||||||
x.counter = 0
|
x.counter = 0
|
||||||
newSeq(x.data, StartSize)
|
newSeq(x.data, StartSize)
|
||||||
|
|
||||||
proc initIdNodeTable*(x: var TIdNodeTable) =
|
proc initIdNodeTable*(x: var TIdNodeTable) =
|
||||||
x.counter = 0
|
x.counter = 0
|
||||||
newSeq(x.data, StartSize)
|
newSeq(x.data, StartSize)
|
||||||
|
|
||||||
proc initNodeTable*(x: var TNodeTable) =
|
proc initNodeTable*(x: var TNodeTable) =
|
||||||
x.counter = 0
|
x.counter = 0
|
||||||
newSeq(x.data, StartSize)
|
newSeq(x.data, StartSize)
|
||||||
|
|
||||||
|
|
@ -1327,11 +1324,11 @@ proc propagateToOwner*(owner, elem: PType) =
|
||||||
owner.flags.incl tfNotNil
|
owner.flags.incl tfNotNil
|
||||||
elif owner.kind notin HaveTheirOwnEmpty:
|
elif owner.kind notin HaveTheirOwnEmpty:
|
||||||
owner.flags.incl tfNeedsInit
|
owner.flags.incl tfNeedsInit
|
||||||
|
|
||||||
if tfNeedsInit in elem.flags:
|
if tfNeedsInit in elem.flags:
|
||||||
if owner.kind in HaveTheirOwnEmpty: discard
|
if owner.kind in HaveTheirOwnEmpty: discard
|
||||||
else: owner.flags.incl tfNeedsInit
|
else: owner.flags.incl tfNeedsInit
|
||||||
|
|
||||||
if elem.isMetaType:
|
if elem.isMetaType:
|
||||||
owner.flags.incl tfHasMeta
|
owner.flags.incl tfHasMeta
|
||||||
|
|
||||||
|
|
@ -1348,15 +1345,15 @@ proc addSonNilAllowed*(father, son: PNode) =
|
||||||
if isNil(father.sons): father.sons = @[]
|
if isNil(father.sons): father.sons = @[]
|
||||||
add(father.sons, son)
|
add(father.sons, son)
|
||||||
|
|
||||||
proc delSon*(father: PNode, idx: int) =
|
proc delSon*(father: PNode, idx: int) =
|
||||||
if isNil(father.sons): return
|
if isNil(father.sons): return
|
||||||
var length = sonsLen(father)
|
var length = sonsLen(father)
|
||||||
for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1]
|
for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1]
|
||||||
setLen(father.sons, length - 1)
|
setLen(father.sons, length - 1)
|
||||||
|
|
||||||
proc copyNode*(src: PNode): PNode =
|
proc copyNode*(src: PNode): PNode =
|
||||||
# does not copy its sons!
|
# does not copy its sons!
|
||||||
if src == nil:
|
if src == nil:
|
||||||
return nil
|
return nil
|
||||||
result = newNode(src.kind)
|
result = newNode(src.kind)
|
||||||
result.info = src.info
|
result.info = src.info
|
||||||
|
|
@ -1373,7 +1370,7 @@ proc copyNode*(src: PNode): PNode =
|
||||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc shallowCopy*(src: PNode): PNode =
|
proc shallowCopy*(src: PNode): PNode =
|
||||||
# does not copy its sons, but provides space for them:
|
# does not copy its sons, but provides space for them:
|
||||||
if src == nil: return nil
|
if src == nil: return nil
|
||||||
result = newNode(src.kind)
|
result = newNode(src.kind)
|
||||||
|
|
@ -1391,9 +1388,9 @@ proc shallowCopy*(src: PNode): PNode =
|
||||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||||
else: newSeq(result.sons, sonsLen(src))
|
else: newSeq(result.sons, sonsLen(src))
|
||||||
|
|
||||||
proc copyTree*(src: PNode): PNode =
|
proc copyTree*(src: PNode): PNode =
|
||||||
# copy a whole syntax tree; performs deep copying
|
# copy a whole syntax tree; performs deep copying
|
||||||
if src == nil:
|
if src == nil:
|
||||||
return nil
|
return nil
|
||||||
result = newNode(src.kind)
|
result = newNode(src.kind)
|
||||||
result.info = src.info
|
result.info = src.info
|
||||||
|
|
@ -1408,20 +1405,20 @@ proc copyTree*(src: PNode): PNode =
|
||||||
of nkSym: result.sym = src.sym
|
of nkSym: result.sym = src.sym
|
||||||
of nkIdent: result.ident = src.ident
|
of nkIdent: result.ident = src.ident
|
||||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||||
else:
|
else:
|
||||||
newSeq(result.sons, sonsLen(src))
|
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])
|
result.sons[i] = copyTree(src.sons[i])
|
||||||
|
|
||||||
proc hasSonWith*(n: PNode, kind: TNodeKind): bool =
|
proc hasSonWith*(n: PNode, kind: TNodeKind): bool =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if n.sons[i].kind == kind:
|
if n.sons[i].kind == kind:
|
||||||
return true
|
return true
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc hasNilSon*(n: PNode): bool =
|
proc hasNilSon*(n: PNode): bool =
|
||||||
for i in countup(0, safeLen(n) - 1):
|
for i in countup(0, safeLen(n) - 1):
|
||||||
if n.sons[i] == nil:
|
if n.sons[i] == nil:
|
||||||
return true
|
return true
|
||||||
elif hasNilSon(n.sons[i]):
|
elif hasNilSon(n.sons[i]):
|
||||||
return true
|
return true
|
||||||
|
|
@ -1435,47 +1432,47 @@ proc containsNode*(n: PNode, kinds: TNodeKinds): bool =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if n.kind in kinds or containsNode(n.sons[i], kinds): return true
|
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
|
case n.kind
|
||||||
of nkEmpty..nkNilLit: result = n.kind == kind
|
of nkEmpty..nkNilLit: result = n.kind == kind
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
|
if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
|
||||||
return true
|
return true
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc replaceSons(n: PNode, oldKind, newKind: TNodeKind) =
|
proc replaceSons(n: PNode, oldKind, newKind: TNodeKind) =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if n.sons[i].kind == oldKind: n.sons[i].kind = newKind
|
if n.sons[i].kind == oldKind: n.sons[i].kind = newKind
|
||||||
|
|
||||||
proc sonsNotNil(n: PNode): bool =
|
proc sonsNotNil(n: PNode): bool =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if n.sons[i] == nil:
|
if n.sons[i] == nil:
|
||||||
return false
|
return false
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc getInt*(a: PNode): BiggestInt =
|
proc getInt*(a: PNode): BiggestInt =
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkIntLit..nkUInt64Lit: result = a.intVal
|
of nkIntLit..nkUInt64Lit: result = a.intVal
|
||||||
else:
|
else:
|
||||||
internalError(a.info, "getInt")
|
internalError(a.info, "getInt")
|
||||||
result = 0
|
result = 0
|
||||||
|
|
||||||
proc getFloat*(a: PNode): BiggestFloat =
|
proc getFloat*(a: PNode): BiggestFloat =
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkFloatLit..nkFloat128Lit: result = a.floatVal
|
of nkFloatLit..nkFloat128Lit: result = a.floatVal
|
||||||
else:
|
else:
|
||||||
internalError(a.info, "getFloat")
|
internalError(a.info, "getFloat")
|
||||||
result = 0.0
|
result = 0.0
|
||||||
|
|
||||||
proc getStr*(a: PNode): string =
|
proc getStr*(a: PNode): string =
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkStrLit..nkTripleStrLit: result = a.strVal
|
of nkStrLit..nkTripleStrLit: result = a.strVal
|
||||||
else:
|
else:
|
||||||
internalError(a.info, "getStr")
|
internalError(a.info, "getStr")
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
proc getStrOrChar*(a: PNode): string =
|
proc getStrOrChar*(a: PNode): string =
|
||||||
case a.kind
|
case a.kind
|
||||||
of nkStrLit..nkTripleStrLit: result = a.strVal
|
of nkStrLit..nkTripleStrLit: result = a.strVal
|
||||||
of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal))
|
of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal))
|
||||||
|
|
@ -1483,7 +1480,7 @@ proc getStrOrChar*(a: PNode): string =
|
||||||
internalError(a.info, "getStrOrChar")
|
internalError(a.info, "getStrOrChar")
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
proc isGenericRoutine*(s: PSym): bool =
|
proc isGenericRoutine*(s: PSym): bool =
|
||||||
case s.kind
|
case s.kind
|
||||||
of skProcKinds:
|
of skProcKinds:
|
||||||
result = sfFromGeneric in s.flags or
|
result = sfFromGeneric in s.flags or
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
## Template evaluation engine. Now hygienic.
|
## Template evaluation engine. Now hygienic.
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer,
|
strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer,
|
||||||
rodread
|
rodread
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -49,7 +49,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||||
result.add copyNode(c, templ, actual)
|
result.add copyNode(c, templ, actual)
|
||||||
else:
|
else:
|
||||||
var res = copyNode(c, templ, actual)
|
var res = copyNode(c, templ, actual)
|
||||||
for i in countup(0, sonsLen(templ) - 1):
|
for i in countup(0, sonsLen(templ) - 1):
|
||||||
evalTemplateAux(templ.sons[i], actual, c, res)
|
evalTemplateAux(templ.sons[i], actual, c, res)
|
||||||
result.add res
|
result.add res
|
||||||
|
|
||||||
|
|
@ -86,9 +86,9 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym): PNode =
|
||||||
ctx.owner = tmpl
|
ctx.owner = tmpl
|
||||||
ctx.genSymOwner = genSymOwner
|
ctx.genSymOwner = genSymOwner
|
||||||
initIdTable(ctx.mapping)
|
initIdTable(ctx.mapping)
|
||||||
|
|
||||||
let body = tmpl.getBody
|
let body = tmpl.getBody
|
||||||
if isAtom(body):
|
if isAtom(body):
|
||||||
result = newNodeI(nkPar, body.info)
|
result = newNodeI(nkPar, body.info)
|
||||||
evalTemplateAux(body, args, ctx, result)
|
evalTemplateAux(body, args, ctx, result)
|
||||||
if result.len == 1: result = result.sons[0]
|
if result.len == 1: result = result.sons[0]
|
||||||
|
|
@ -102,5 +102,5 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym): PNode =
|
||||||
if ctx.instLines: result.info = n.info
|
if ctx.instLines: result.info = n.info
|
||||||
for i in countup(0, safeLen(body) - 1):
|
for i in countup(0, safeLen(body) - 1):
|
||||||
evalTemplateAux(body.sons[i], args, ctx, result)
|
evalTemplateAux(body.sons[i], args, ctx, result)
|
||||||
|
|
||||||
dec(evalTemplateCounter)
|
dec(evalTemplateCounter)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1232,7 +1232,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
elif f.kind == tyStatic:
|
elif f.kind == tyStatic:
|
||||||
return arg.typ.n
|
return arg.typ.n
|
||||||
else:
|
else:
|
||||||
return argOrig
|
return argSemantized # argOrig
|
||||||
|
|
||||||
if r != isNone and f.isInlineIterator:
|
if r != isNone and f.isInlineIterator:
|
||||||
var inlined = newTypeS(tyStatic, c)
|
var inlined = newTypeS(tyStatic, c)
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ export Port, SocketFlag
|
||||||
##
|
##
|
||||||
## Limitations/Bugs
|
## Limitations/Bugs
|
||||||
## ----------------
|
## ----------------
|
||||||
##
|
##
|
||||||
## * ``except`` statement (without `try`) does not work inside async procedures.
|
## * ``except`` statement (without `try`) does not work inside async procedures.
|
||||||
## * The effect system (``raises: []``) does not work with async procedures.
|
## * The effect system (``raises: []``) does not work with async procedures.
|
||||||
## * Can't await in a ``except`` body
|
## * Can't await in a ``except`` body
|
||||||
|
|
@ -379,7 +379,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
if p.handles.len == 0 and p.timers.len == 0:
|
if p.handles.len == 0 and p.timers.len == 0:
|
||||||
raise newException(ValueError,
|
raise newException(ValueError,
|
||||||
"No handles or timers registered in dispatcher.")
|
"No handles or timers registered in dispatcher.")
|
||||||
|
|
||||||
let llTimeout =
|
let llTimeout =
|
||||||
if timeout == -1: winlean.INFINITE
|
if timeout == -1: winlean.INFINITE
|
||||||
else: timeout.int32
|
else: timeout.int32
|
||||||
|
|
@ -436,12 +436,12 @@ when defined(windows) or defined(nimdoc):
|
||||||
if not initPointer(dummySock, getAcceptExSockAddrsPtr, WSAID_GETACCEPTEXSOCKADDRS):
|
if not initPointer(dummySock, getAcceptExSockAddrsPtr, WSAID_GETACCEPTEXSOCKADDRS):
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
proc connectEx(s: SocketHandle, name: ptr SockAddr, namelen: cint,
|
proc connectEx(s: SocketHandle, name: ptr SockAddr, namelen: cint,
|
||||||
lpSendBuffer: pointer, dwSendDataLength: Dword,
|
lpSendBuffer: pointer, dwSendDataLength: Dword,
|
||||||
lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool =
|
lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool =
|
||||||
if connectExPtr.isNil: raise newException(ValueError, "Need to initialise ConnectEx().")
|
if connectExPtr.isNil: raise newException(ValueError, "Need to initialise ConnectEx().")
|
||||||
let fun =
|
let fun =
|
||||||
cast[proc (s: SocketHandle, name: ptr SockAddr, namelen: cint,
|
cast[proc (s: SocketHandle, name: ptr SockAddr, namelen: cint,
|
||||||
lpSendBuffer: pointer, dwSendDataLength: Dword,
|
lpSendBuffer: pointer, dwSendDataLength: Dword,
|
||||||
lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool {.stdcall,gcsafe.}](connectExPtr)
|
lpdwBytesSent: PDword, lpOverlapped: POVERLAPPED): bool {.stdcall,gcsafe.}](connectExPtr)
|
||||||
|
|
||||||
|
|
@ -475,7 +475,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
dwRemoteAddressLength: Dword, LocalSockaddr: ptr ptr SockAddr,
|
dwRemoteAddressLength: Dword, LocalSockaddr: ptr ptr SockAddr,
|
||||||
LocalSockaddrLength: LPInt, RemoteSockaddr: ptr ptr SockAddr,
|
LocalSockaddrLength: LPInt, RemoteSockaddr: ptr ptr SockAddr,
|
||||||
RemoteSockaddrLength: LPInt) {.stdcall,gcsafe.}](getAcceptExSockAddrsPtr)
|
RemoteSockaddrLength: LPInt) {.stdcall,gcsafe.}](getAcceptExSockAddrsPtr)
|
||||||
|
|
||||||
fun(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
|
fun(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength,
|
||||||
dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength,
|
dwRemoteAddressLength, LocalSockaddr, LocalSockaddrLength,
|
||||||
RemoteSockaddr, RemoteSockaddrLength)
|
RemoteSockaddr, RemoteSockaddrLength)
|
||||||
|
|
@ -514,7 +514,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
else:
|
else:
|
||||||
retFuture.fail(newException(OSError, osErrorMsg(errcode)))
|
retFuture.fail(newException(OSError, osErrorMsg(errcode)))
|
||||||
)
|
)
|
||||||
|
|
||||||
var ret = connectEx(socket.SocketHandle, it.ai_addr,
|
var ret = connectEx(socket.SocketHandle, it.ai_addr,
|
||||||
sizeof(Sockaddr_in).cint, nil, 0, nil,
|
sizeof(Sockaddr_in).cint, nil, 0, nil,
|
||||||
cast[POVERLAPPED](ol))
|
cast[POVERLAPPED](ol))
|
||||||
|
|
@ -565,7 +565,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
var dataBuf: TWSABuf
|
var dataBuf: TWSABuf
|
||||||
dataBuf.buf = cast[cstring](alloc0(size))
|
dataBuf.buf = cast[cstring](alloc0(size))
|
||||||
dataBuf.len = size
|
dataBuf.len = size
|
||||||
|
|
||||||
var bytesReceived: Dword
|
var bytesReceived: Dword
|
||||||
var flagsio = flags.toOSFlags().Dword
|
var flagsio = flags.toOSFlags().Dword
|
||||||
var ol = PCustomOverlapped()
|
var ol = PCustomOverlapped()
|
||||||
|
|
@ -612,9 +612,9 @@ when defined(windows) or defined(nimdoc):
|
||||||
# the empty string (which signals a disconnection) when there is
|
# the empty string (which signals a disconnection) when there is
|
||||||
# nothing left to read.
|
# nothing left to read.
|
||||||
retFuture.complete("")
|
retFuture.complete("")
|
||||||
# TODO: "For message-oriented sockets, where a zero byte message is often
|
# TODO: "For message-oriented sockets, where a zero byte message is often
|
||||||
# allowable, a failure with an error code of WSAEDISCON is used to
|
# allowable, a failure with an error code of WSAEDISCON is used to
|
||||||
# indicate graceful closure."
|
# indicate graceful closure."
|
||||||
# ~ http://msdn.microsoft.com/en-us/library/ms741688%28v=vs.85%29.aspx
|
# ~ http://msdn.microsoft.com/en-us/library/ms741688%28v=vs.85%29.aspx
|
||||||
else:
|
else:
|
||||||
# Request to read completed immediately.
|
# Request to read completed immediately.
|
||||||
|
|
@ -748,7 +748,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
|
|
||||||
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
|
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524%28v=vs.85%29.aspx
|
||||||
let ret = acceptEx(socket.SocketHandle, clientSock, addr lpOutputBuf[0],
|
let ret = acceptEx(socket.SocketHandle, clientSock, addr lpOutputBuf[0],
|
||||||
dwReceiveDataLength,
|
dwReceiveDataLength,
|
||||||
dwLocalAddressLength,
|
dwLocalAddressLength,
|
||||||
dwRemoteAddressLength,
|
dwRemoteAddressLength,
|
||||||
addr dwBytesReceived, cast[POVERLAPPED](ol))
|
addr dwBytesReceived, cast[POVERLAPPED](ol))
|
||||||
|
|
@ -803,7 +803,7 @@ else:
|
||||||
else:
|
else:
|
||||||
from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK,
|
from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK,
|
||||||
MSG_NOSIGNAL
|
MSG_NOSIGNAL
|
||||||
|
|
||||||
type
|
type
|
||||||
TAsyncFD* = distinct cint
|
TAsyncFD* = distinct cint
|
||||||
TCallback = proc (fd: TAsyncFD): bool {.closure,gcsafe.}
|
TCallback = proc (fd: TAsyncFD): bool {.closure,gcsafe.}
|
||||||
|
|
@ -849,7 +849,7 @@ else:
|
||||||
result = newRawSocket(domain, typ, protocol).TAsyncFD
|
result = newRawSocket(domain, typ, protocol).TAsyncFD
|
||||||
result.SocketHandle.setBlocking(false)
|
result.SocketHandle.setBlocking(false)
|
||||||
register(result)
|
register(result)
|
||||||
|
|
||||||
proc closeSocket*(sock: TAsyncFD) =
|
proc closeSocket*(sock: TAsyncFD) =
|
||||||
let disp = getGlobalDispatcher()
|
let disp = getGlobalDispatcher()
|
||||||
sock.SocketHandle.close()
|
sock.SocketHandle.close()
|
||||||
|
|
@ -864,14 +864,14 @@ else:
|
||||||
raise newException(ValueError, "File descriptor not registered.")
|
raise newException(ValueError, "File descriptor not registered.")
|
||||||
p.selector[fd.SocketHandle].data.PData.readCBs.add(cb)
|
p.selector[fd.SocketHandle].data.PData.readCBs.add(cb)
|
||||||
update(fd, p.selector[fd.SocketHandle].events + {EvRead})
|
update(fd, p.selector[fd.SocketHandle].events + {EvRead})
|
||||||
|
|
||||||
proc addWrite*(fd: TAsyncFD, cb: TCallback) =
|
proc addWrite*(fd: TAsyncFD, cb: TCallback) =
|
||||||
let p = getGlobalDispatcher()
|
let p = getGlobalDispatcher()
|
||||||
if fd.SocketHandle notin p.selector:
|
if fd.SocketHandle notin p.selector:
|
||||||
raise newException(ValueError, "File descriptor not registered.")
|
raise newException(ValueError, "File descriptor not registered.")
|
||||||
p.selector[fd.SocketHandle].data.PData.writeCBs.add(cb)
|
p.selector[fd.SocketHandle].data.PData.writeCBs.add(cb)
|
||||||
update(fd, p.selector[fd.SocketHandle].events + {EvWrite})
|
update(fd, p.selector[fd.SocketHandle].events + {EvWrite})
|
||||||
|
|
||||||
proc poll*(timeout = 500) =
|
proc poll*(timeout = 500) =
|
||||||
let p = getGlobalDispatcher()
|
let p = getGlobalDispatcher()
|
||||||
for info in p.selector.select(timeout):
|
for info in p.selector.select(timeout):
|
||||||
|
|
@ -892,7 +892,7 @@ else:
|
||||||
if not cb(data.fd):
|
if not cb(data.fd):
|
||||||
# Callback wants to be called again.
|
# Callback wants to be called again.
|
||||||
data.readCBs.add(cb)
|
data.readCBs.add(cb)
|
||||||
|
|
||||||
if EvWrite in info.events:
|
if EvWrite in info.events:
|
||||||
let currentCBs = data.writeCBs
|
let currentCBs = data.writeCBs
|
||||||
data.writeCBs = @[]
|
data.writeCBs = @[]
|
||||||
|
|
@ -900,7 +900,7 @@ else:
|
||||||
if not cb(data.fd):
|
if not cb(data.fd):
|
||||||
# Callback wants to be called again.
|
# Callback wants to be called again.
|
||||||
data.writeCBs.add(cb)
|
data.writeCBs.add(cb)
|
||||||
|
|
||||||
if info.key in p.selector:
|
if info.key in p.selector:
|
||||||
var newEvents: set[Event]
|
var newEvents: set[Event]
|
||||||
if data.readCBs.len != 0: newEvents = {EvRead}
|
if data.readCBs.len != 0: newEvents = {EvRead}
|
||||||
|
|
@ -913,16 +913,16 @@ else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
processTimers(p)
|
processTimers(p)
|
||||||
|
|
||||||
proc connect*(socket: TAsyncFD, address: string, port: Port,
|
proc connect*(socket: TAsyncFD, address: string, port: Port,
|
||||||
af = AF_INET): Future[void] =
|
af = AF_INET): Future[void] =
|
||||||
var retFuture = newFuture[void]("connect")
|
var retFuture = newFuture[void]("connect")
|
||||||
|
|
||||||
proc cb(fd: TAsyncFD): bool =
|
proc cb(fd: TAsyncFD): bool =
|
||||||
# We have connected.
|
# We have connected.
|
||||||
retFuture.complete()
|
retFuture.complete()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
var aiList = getAddrInfo(address, port, af)
|
var aiList = getAddrInfo(address, port, af)
|
||||||
var success = false
|
var success = false
|
||||||
var lastError: OSErrorCode
|
var lastError: OSErrorCode
|
||||||
|
|
@ -952,7 +952,7 @@ else:
|
||||||
proc recv*(socket: TAsyncFD, size: int,
|
proc recv*(socket: TAsyncFD, size: int,
|
||||||
flags = {SocketFlag.SafeDisconn}): Future[string] =
|
flags = {SocketFlag.SafeDisconn}): Future[string] =
|
||||||
var retFuture = newFuture[string]("recv")
|
var retFuture = newFuture[string]("recv")
|
||||||
|
|
||||||
var readBuffer = newString(size)
|
var readBuffer = newString(size)
|
||||||
|
|
||||||
proc cb(sock: TAsyncFD): bool =
|
proc cb(sock: TAsyncFD): bool =
|
||||||
|
|
@ -983,9 +983,9 @@ else:
|
||||||
proc send*(socket: TAsyncFD, data: string,
|
proc send*(socket: TAsyncFD, data: string,
|
||||||
flags = {SocketFlag.SafeDisconn}): Future[void] =
|
flags = {SocketFlag.SafeDisconn}): Future[void] =
|
||||||
var retFuture = newFuture[void]("send")
|
var retFuture = newFuture[void]("send")
|
||||||
|
|
||||||
var written = 0
|
var written = 0
|
||||||
|
|
||||||
proc cb(sock: TAsyncFD): bool =
|
proc cb(sock: TAsyncFD): bool =
|
||||||
result = true
|
result = true
|
||||||
let netSize = data.len-written
|
let netSize = data.len-written
|
||||||
|
|
@ -1222,7 +1222,7 @@ proc processBody(node, retFutureSym: PNimrodNode,
|
||||||
of nnkTryStmt:
|
of nnkTryStmt:
|
||||||
# try: await x; except: ...
|
# try: await x; except: ...
|
||||||
result = newNimNode(nnkStmtList, node)
|
result = newNimNode(nnkStmtList, node)
|
||||||
template wrapInTry(n, tryBody: PNimrodNode) =
|
template wrapInTry(n, tryBody: expr) =
|
||||||
var temp = n
|
var temp = n
|
||||||
n[0] = tryBody
|
n[0] = tryBody
|
||||||
tryBody = temp
|
tryBody = temp
|
||||||
|
|
@ -1315,14 +1315,14 @@ macro async*(prc: stmt): stmt {.immediate.} =
|
||||||
if returnType.kind == nnkEmpty: newIdentNode("void")
|
if returnType.kind == nnkEmpty: newIdentNode("void")
|
||||||
else: returnType[1]
|
else: returnType[1]
|
||||||
outerProcBody.add(
|
outerProcBody.add(
|
||||||
newVarStmt(retFutureSym,
|
newVarStmt(retFutureSym,
|
||||||
newCall(
|
newCall(
|
||||||
newNimNode(nnkBracketExpr, prc[6]).add(
|
newNimNode(nnkBracketExpr, prc[6]).add(
|
||||||
newIdentNode(!"newFuture"), # TODO: Strange bug here? Remove the `!`.
|
newIdentNode(!"newFuture"), # TODO: Strange bug here? Remove the `!`.
|
||||||
subRetType),
|
subRetType),
|
||||||
newLit(prc[0].getName)))) # Get type from return type of this proc
|
newLit(prc[0].getName)))) # Get type from return type of this proc
|
||||||
|
|
||||||
# -> iterator nameIter(): FutureBase {.closure.} =
|
# -> iterator nameIter(): FutureBase {.closure.} =
|
||||||
# -> var result: T
|
# -> var result: T
|
||||||
# -> <proc_body>
|
# -> <proc_body>
|
||||||
# -> complete(retFuture, result)
|
# -> complete(retFuture, result)
|
||||||
|
|
@ -1337,7 +1337,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
|
||||||
else:
|
else:
|
||||||
# -> complete(retFuture)
|
# -> complete(retFuture)
|
||||||
procBody.add(newCall(newIdentNode("complete"), retFutureSym))
|
procBody.add(newCall(newIdentNode("complete"), retFutureSym))
|
||||||
|
|
||||||
var closureIterator = newProc(iteratorNameSym, [newIdentNode("FutureBase")],
|
var closureIterator = newProc(iteratorNameSym, [newIdentNode("FutureBase")],
|
||||||
procBody, nnkIteratorDef)
|
procBody, nnkIteratorDef)
|
||||||
closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure"))
|
closureIterator[4] = newNimNode(nnkPragma, prc[6]).add(newIdentNode("closure"))
|
||||||
|
|
@ -1351,7 +1351,7 @@ macro async*(prc: stmt): stmt {.immediate.} =
|
||||||
|
|
||||||
# -> return retFuture
|
# -> return retFuture
|
||||||
outerProcBody.add newNimNode(nnkReturnStmt, prc[6][prc[6].len-1]).add(retFutureSym)
|
outerProcBody.add newNimNode(nnkReturnStmt, prc[6][prc[6].len-1]).add(retFutureSym)
|
||||||
|
|
||||||
result = prc
|
result = prc
|
||||||
|
|
||||||
# Remove the 'async' pragma.
|
# Remove the 'async' pragma.
|
||||||
|
|
@ -1377,7 +1377,7 @@ proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
|
||||||
## If a full line is read ``\r\L`` is not
|
## If a full line is read ``\r\L`` is not
|
||||||
## added to ``line``, however if solely ``\r\L`` is read then ``line``
|
## added to ``line``, however if solely ``\r\L`` is read then ``line``
|
||||||
## will be set to it.
|
## will be set to it.
|
||||||
##
|
##
|
||||||
## If the socket is disconnected, ``line`` will be set to ``""``.
|
## If the socket is disconnected, ``line`` will be set to ``""``.
|
||||||
##
|
##
|
||||||
## If the socket is disconnected in the middle of a line (before ``\r\L``
|
## If the socket is disconnected in the middle of a line (before ``\r\L``
|
||||||
|
|
@ -1388,7 +1388,7 @@ proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
|
||||||
##
|
##
|
||||||
## **Note**: This procedure is mostly used for testing. You likely want to
|
## **Note**: This procedure is mostly used for testing. You likely want to
|
||||||
## use ``asyncnet.recvLine`` instead.
|
## use ``asyncnet.recvLine`` instead.
|
||||||
|
|
||||||
template addNLIfEmpty(): stmt =
|
template addNLIfEmpty(): stmt =
|
||||||
if result.len == 0:
|
if result.len == 0:
|
||||||
result.add("\c\L")
|
result.add("\c\L")
|
||||||
|
|
|
||||||
47
tests/template/texponential_eval.nim
Normal file
47
tests/template/texponential_eval.nim
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
# bug #1940
|
||||||
|
|
||||||
|
discard """
|
||||||
|
nimout: '''===
|
||||||
|
merge (A) with (B)
|
||||||
|
merge (A B) with (C)
|
||||||
|
merge (A B C) with (D)
|
||||||
|
merge (A B C D) with (E)
|
||||||
|
merge (A B C D E) with (F)
|
||||||
|
==='''
|
||||||
|
"""
|
||||||
|
|
||||||
|
type SqlStmt = tuple
|
||||||
|
sql: string
|
||||||
|
parts: int
|
||||||
|
|
||||||
|
proc sql(q: string): SqlStmt =
|
||||||
|
result.sql = q
|
||||||
|
result.parts = 1
|
||||||
|
|
||||||
|
template `&%%`(x, y: SqlStmt): SqlStmt =
|
||||||
|
const a = x
|
||||||
|
const b = y
|
||||||
|
|
||||||
|
static:
|
||||||
|
#echo "some merge"
|
||||||
|
echo "merge (", a.sql, ") with (", b.sql, ")"
|
||||||
|
|
||||||
|
|
||||||
|
const newSql = a.sql & " " & b.sql
|
||||||
|
const newParts = a.parts + b.parts
|
||||||
|
|
||||||
|
SqlStmt((sql: newSql, parts: newParts))
|
||||||
|
|
||||||
|
static:
|
||||||
|
echo "==="
|
||||||
|
|
||||||
|
let c =(sql("A") &%%
|
||||||
|
sql("B")) &%%
|
||||||
|
sql("C") &%%
|
||||||
|
sql("D") &%%
|
||||||
|
sql("E") &%%
|
||||||
|
sql("F")
|
||||||
|
echo c.sql
|
||||||
|
|
||||||
|
static:
|
||||||
|
echo "==="
|
||||||
Loading…
Add table
Add a link
Reference in a new issue