Merge branch 'master' of gh:/Araq/Nimrod into upstream
This commit is contained in:
commit
3f1e9b3a25
942 changed files with 13790 additions and 3241 deletions
3
.gitignore
vendored
Executable file → Normal file
3
.gitignore
vendored
Executable file → Normal file
|
|
@ -16,6 +16,7 @@ compiler/c2nim/nimcache
|
||||||
compiler/pas2nim/nimcache
|
compiler/pas2nim/nimcache
|
||||||
misc
|
misc
|
||||||
doc/*.html
|
doc/*.html
|
||||||
|
doc/*.pdf
|
||||||
doc/*.idx
|
doc/*.idx
|
||||||
/web/upload
|
/web/upload
|
||||||
koch
|
koch
|
||||||
|
|
@ -28,6 +29,8 @@ examples/cross_todo/nimrod_backend/backend
|
||||||
examples/cross_todo/nimrod_backend/testbackend
|
examples/cross_todo/nimrod_backend/testbackend
|
||||||
examples/cross_todo/nimrod_backend/todo.sqlite3
|
examples/cross_todo/nimrod_backend/todo.sqlite3
|
||||||
examples/cross_todo/nimrod_commandline/nimtodo
|
examples/cross_todo/nimrod_commandline/nimtodo
|
||||||
|
install.sh
|
||||||
|
deinstall.sh
|
||||||
|
|
||||||
# iOS specific wildcards.
|
# iOS specific wildcards.
|
||||||
*.mode1v3
|
*.mode1v3
|
||||||
|
|
|
||||||
0
build.bat
Executable file → Normal file
0
build.bat
Executable file → Normal file
49
compiler/ast.nim
Executable file → Normal file
49
compiler/ast.nim
Executable file → Normal file
|
|
@ -71,21 +71,25 @@ type
|
||||||
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)
|
||||||
|
nkPrefix, # a call like !a
|
||||||
|
nkPostfix, # something like a! (also used for visibility)
|
||||||
|
nkHiddenCallConv, # an implicit type conversion via a type converter
|
||||||
|
|
||||||
nkExprEqExpr, # a named parameter with equals: ''expr = expr''
|
nkExprEqExpr, # a named parameter with equals: ''expr = expr''
|
||||||
nkExprColonExpr, # a named parameter with colon: ''expr: expr''
|
nkExprColonExpr, # a named parameter with colon: ''expr: expr''
|
||||||
nkIdentDefs, # a definition like `a, b: typeDesc = expr`
|
nkIdentDefs, # a definition like `a, b: typeDesc = expr`
|
||||||
# either typeDesc or expr may be nil; used in
|
# either typeDesc or expr may be nil; used in
|
||||||
# formal parameters, var statements, etc.
|
# formal parameters, var statements, etc.
|
||||||
nkVarTuple, # a ``var (a, b) = expr`` construct
|
nkVarTuple, # a ``var (a, b) = expr`` construct
|
||||||
nkInfix, # a call like (a + b)
|
|
||||||
nkPrefix, # a call like !a
|
|
||||||
nkPostfix, # something like a! (also used for visibility)
|
|
||||||
nkPar, # syntactic (); may be a tuple constructor
|
nkPar, # syntactic (); may be a tuple constructor
|
||||||
|
nkObjConstr, # object constructor: T(a: 1, b: 2)
|
||||||
nkCurly, # syntactic {}
|
nkCurly, # syntactic {}
|
||||||
nkCurlyExpr, # an expression like a{i}
|
nkCurlyExpr, # an expression like a{i}
|
||||||
nkBracket, # syntactic []
|
nkBracket, # syntactic []
|
||||||
|
|
@ -109,7 +113,6 @@ type
|
||||||
nkHiddenStdConv, # an implicit standard type conversion
|
nkHiddenStdConv, # an implicit standard type conversion
|
||||||
nkHiddenSubConv, # an implicit type conversion from a subtype
|
nkHiddenSubConv, # an implicit type conversion from a subtype
|
||||||
# to a supertype
|
# to a supertype
|
||||||
nkHiddenCallConv, # an implicit type conversion via a type converter
|
|
||||||
nkConv, # a type conversion
|
nkConv, # a type conversion
|
||||||
nkCast, # a type cast
|
nkCast, # a type cast
|
||||||
nkStaticExpr, # a static expr
|
nkStaticExpr, # a static expr
|
||||||
|
|
@ -452,12 +455,12 @@ type
|
||||||
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,
|
||||||
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq,
|
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq,
|
||||||
mIsPartOf, mAstToStr, mRand,
|
mIsPartOf, mAstToStr, mRand,
|
||||||
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
|
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
|
||||||
mNewString, mNewStringOfCap,
|
mNewString, mNewStringOfCap,
|
||||||
mReset,
|
mReset,
|
||||||
mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
|
mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
|
||||||
|
|
@ -466,18 +469,18 @@ type
|
||||||
mUInt, mUInt8, mUInt16, mUInt32, mUInt64,
|
mUInt, mUInt8, mUInt16, mUInt32, mUInt64,
|
||||||
mFloat, mFloat32, mFloat64, mFloat128,
|
mFloat, mFloat32, mFloat64, mFloat128,
|
||||||
mBool, mChar, mString, mCstring,
|
mBool, mChar, mString, mCstring,
|
||||||
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
|
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
|
||||||
mVoidType, mPNimrodNode,
|
mVoidType, mPNimrodNode,
|
||||||
mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
|
mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
|
||||||
mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType,
|
mNimrodMinor, mNimrodPatch, mCpuEndian, mHostOS, mHostCPU, mAppType,
|
||||||
mNaN, mInf, mNegInf,
|
mNaN, mInf, mNegInf,
|
||||||
mCompileOption, mCompileOptionArg,
|
mCompileOption, mCompileOptionArg,
|
||||||
mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind,
|
mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, mNKind,
|
||||||
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
|
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
|
||||||
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
|
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
|
||||||
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr,
|
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr,
|
||||||
mNBindSym, mNCallSite,
|
mNBindSym, mLocals, mNCallSite,
|
||||||
mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError,
|
mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError,
|
||||||
mInstantiationInfo, mGetTypeInfo
|
mInstantiationInfo, mGetTypeInfo
|
||||||
|
|
||||||
# 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:
|
||||||
|
|
@ -520,7 +523,7 @@ type
|
||||||
TNodeSeq* = seq[PNode]
|
TNodeSeq* = seq[PNode]
|
||||||
PType* = ref TType
|
PType* = ref TType
|
||||||
PSym* = ref TSym
|
PSym* = ref TSym
|
||||||
TNode*{.final.} = object # on a 32bit machine, this takes 32 bytes
|
TNode*{.final, acyclic.} = object # on a 32bit machine, this takes 32 bytes
|
||||||
typ*: PType
|
typ*: PType
|
||||||
comment*: string
|
comment*: string
|
||||||
info*: TLineInfo
|
info*: TLineInfo
|
||||||
|
|
@ -591,6 +594,7 @@ type
|
||||||
TLib* = object of lists.TListEntry # also misused for headers!
|
TLib* = object of lists.TListEntry # also misused for headers!
|
||||||
kind*: TLibKind
|
kind*: TLibKind
|
||||||
generated*: bool # needed for the backends:
|
generated*: bool # needed for the backends:
|
||||||
|
isOverriden*: bool
|
||||||
name*: PRope
|
name*: PRope
|
||||||
path*: PNode # can be a string literal!
|
path*: PNode # can be a string literal!
|
||||||
|
|
||||||
|
|
@ -605,7 +609,7 @@ type
|
||||||
PInstantiation* = ref TInstantiation
|
PInstantiation* = ref TInstantiation
|
||||||
|
|
||||||
PLib* = ref TLib
|
PLib* = ref TLib
|
||||||
TSym* = object of TIdObj
|
TSym* {.acyclic.} = object of TIdObj
|
||||||
# proc and type instantiations are cached in the generic symbol
|
# proc and type instantiations are cached in the generic symbol
|
||||||
case kind*: TSymKind
|
case kind*: TSymKind
|
||||||
of skType:
|
of skType:
|
||||||
|
|
@ -653,7 +657,8 @@ type
|
||||||
constraint*: PNode # additional constraints like 'lit|result'
|
constraint*: PNode # additional constraints like 'lit|result'
|
||||||
|
|
||||||
TTypeSeq* = seq[PType]
|
TTypeSeq* = seq[PType]
|
||||||
TType* = object of TIdObj # types are identical iff they have the
|
TType* {.acyclic.} = object of TIdObj # \
|
||||||
|
# types are identical iff they have the
|
||||||
# same id; there may be multiple copies of a type
|
# same id; there may be multiple copies of a type
|
||||||
# in memory!
|
# in memory!
|
||||||
kind*: TTypeKind # kind of type
|
kind*: TTypeKind # kind of type
|
||||||
|
|
@ -759,7 +764,7 @@ const
|
||||||
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 5!
|
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 5!
|
||||||
|
|
||||||
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
|
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
|
||||||
nkCommand, nkCallStrLit}
|
nkCommand, nkCallStrLit, nkHiddenCallConv}
|
||||||
|
|
||||||
nkLambdaKinds* = {nkLambda, nkDo}
|
nkLambdaKinds* = {nkLambda, nkDo}
|
||||||
nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice}
|
nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice}
|
||||||
|
|
|
||||||
4
compiler/astalgo.nim
Executable file → Normal file
4
compiler/astalgo.nim
Executable file → Normal file
|
|
@ -156,6 +156,10 @@ proc skipConv*(n: PNode): PNode =
|
||||||
result = n.sons[1]
|
result = n.sons[1]
|
||||||
else: result = n
|
else: result = n
|
||||||
|
|
||||||
|
proc skipConvTakeType*(n: PNode): PNode =
|
||||||
|
result = n.skipConv
|
||||||
|
result.typ = n.typ
|
||||||
|
|
||||||
proc SameValue*(a, b: PNode): bool =
|
proc SameValue*(a, b: PNode): bool =
|
||||||
result = false
|
result = false
|
||||||
case a.kind
|
case a.kind
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ iterator chosen(packages: PStringTable): string =
|
||||||
|
|
||||||
proc addBabelPath(p: string, info: TLineInfo) =
|
proc addBabelPath(p: string, info: TLineInfo) =
|
||||||
if not contains(options.searchPaths, p):
|
if not contains(options.searchPaths, p):
|
||||||
Message(info, hintPath, p)
|
if gVerbosity >= 1: Message(info, hintPath, p)
|
||||||
lists.PrependStr(options.lazyPaths, p)
|
lists.PrependStr(options.lazyPaths, p)
|
||||||
|
|
||||||
proc addPathWithNimFiles(p: string, info: TLineInfo) =
|
proc addPathWithNimFiles(p: string, info: TLineInfo) =
|
||||||
|
|
@ -83,7 +83,7 @@ proc addPathRec(dir: string, info: TLineInfo) =
|
||||||
if k == pcDir and p[pos] != '.':
|
if k == pcDir and p[pos] != '.':
|
||||||
addPackage(packages, p)
|
addPackage(packages, p)
|
||||||
for p in packages.chosen:
|
for p in packages.chosen:
|
||||||
addPathWithNimFiles(p, info)
|
addBabelPath(p, info)
|
||||||
|
|
||||||
proc babelPath*(path: string, info: TLineInfo) =
|
proc babelPath*(path: string, info: TLineInfo) =
|
||||||
addPathRec(path, info)
|
addPathRec(path, info)
|
||||||
|
|
|
||||||
0
compiler/bitsets.nim
Executable file → Normal file
0
compiler/bitsets.nim
Executable file → Normal file
4
compiler/c2nim/c2nim.nim
Executable file → Normal file
4
compiler/c2nim/c2nim.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# c2nim - C to Nimrod source converter
|
# c2nim - C to Nimrod source converter
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -15,7 +15,7 @@ const
|
||||||
Version = NimrodVersion
|
Version = NimrodVersion
|
||||||
Usage = """
|
Usage = """
|
||||||
c2nim - C to Nimrod source converter
|
c2nim - C to Nimrod source converter
|
||||||
(c) 2012 Andreas Rumpf
|
(c) 2013 Andreas Rumpf
|
||||||
Usage: c2nim [options] inputfile [options]
|
Usage: c2nim [options] inputfile [options]
|
||||||
Options:
|
Options:
|
||||||
-o, --out:FILE set output filename
|
-o, --out:FILE set output filename
|
||||||
|
|
|
||||||
0
compiler/c2nim/clex.nim
Executable file → Normal file
0
compiler/c2nim/clex.nim
Executable file → Normal file
11
compiler/c2nim/cparse.nim
Executable file → Normal file
11
compiler/c2nim/cparse.nim
Executable file → Normal file
|
|
@ -955,15 +955,22 @@ proc enumSpecifier(p: var TParser): PNode =
|
||||||
result = newNodeP(nkConstSection, p)
|
result = newNodeP(nkConstSection, p)
|
||||||
getTok(p, result)
|
getTok(p, result)
|
||||||
var i = 0
|
var i = 0
|
||||||
|
var hasUnknown = false
|
||||||
while true:
|
while true:
|
||||||
var name = skipIdentExport(p)
|
var name = skipIdentExport(p)
|
||||||
var val: PNode
|
var val: PNode
|
||||||
if p.tok.xkind == pxAsgn:
|
if p.tok.xkind == pxAsgn:
|
||||||
getTok(p, name)
|
getTok(p, name)
|
||||||
val = constantExpression(p)
|
val = constantExpression(p)
|
||||||
if val.kind == nkIntLit: i = int(val.intVal)+1
|
if val.kind == nkIntLit:
|
||||||
else: parMessage(p, errXExpected, "int literal")
|
i = int(val.intVal)+1
|
||||||
|
hasUnknown = false
|
||||||
|
else:
|
||||||
|
hasUnknown = true
|
||||||
else:
|
else:
|
||||||
|
if hasUnknown:
|
||||||
|
parMessage(p, warnUser, "computed const value may be wrong: " &
|
||||||
|
name.renderTree)
|
||||||
val = newIntNodeP(nkIntLit, i, p)
|
val = newIntNodeP(nkIntLit, i, p)
|
||||||
inc(i)
|
inc(i)
|
||||||
var c = createConst(name, ast.emptyNode, val, p)
|
var c = createConst(name, ast.emptyNode, val, p)
|
||||||
|
|
|
||||||
0
compiler/c2nim/cpp.nim
Executable file → Normal file
0
compiler/c2nim/cpp.nim
Executable file → Normal file
0
compiler/c2nim/nimrod.cfg
Executable file → Normal file
0
compiler/c2nim/nimrod.cfg
Executable file → Normal file
14
compiler/c2nim/tests/systest.c
Executable file → Normal file
14
compiler/c2nim/tests/systest.c
Executable file → Normal file
|
|
@ -9,6 +9,20 @@ extern "C" {
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/* 8bit, color or not */
|
||||||
|
CV_LOAD_IMAGE_UNCHANGED =-1,
|
||||||
|
/* 8bit, gray */
|
||||||
|
CV_LOAD_IMAGE_GRAYSCALE =0,
|
||||||
|
/* ?, color */
|
||||||
|
CV_LOAD_IMAGE_COLOR =1,
|
||||||
|
/* any depth, ? */
|
||||||
|
CV_LOAD_IMAGE_ANYDEPTH =2,
|
||||||
|
/* ?, any color */
|
||||||
|
CV_LOAD_IMAGE_ANYCOLOR =4
|
||||||
|
};
|
||||||
|
|
||||||
typedef void (*callback_t) (int rc);
|
typedef void (*callback_t) (int rc);
|
||||||
typedef const char* (*callback2)(int rc, long L, const char* buffer);
|
typedef const char* (*callback2)(int rc, long L, const char* buffer);
|
||||||
|
|
||||||
|
|
|
||||||
0
compiler/c2nim/tests/systest2.c
Executable file → Normal file
0
compiler/c2nim/tests/systest2.c
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
|
||||||
269
compiler/ccgexprs.nim
Executable file → Normal file
269
compiler/ccgexprs.nim
Executable file → Normal file
|
|
@ -195,6 +195,46 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
addrLoc(dest), rdLoc(src))
|
addrLoc(dest), rdLoc(src))
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||||
|
|
||||||
|
proc asgnComplexity(n: PNode): int =
|
||||||
|
if n != nil:
|
||||||
|
case n.kind
|
||||||
|
of nkSym: result = 1
|
||||||
|
of nkRecCase:
|
||||||
|
# 'case objects' are too difficult to inline their assignment operation:
|
||||||
|
result = 100
|
||||||
|
of nkRecList:
|
||||||
|
for t in items(n):
|
||||||
|
result += asgnComplexity(t)
|
||||||
|
else: nil
|
||||||
|
|
||||||
|
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
|
||||||
|
|
||||||
|
proc optAsgnLoc(a: TLoc, t: PType, field: PRope): TLoc =
|
||||||
|
result.k = locField
|
||||||
|
result.s = a.s
|
||||||
|
result.t = t
|
||||||
|
result.r = rdLoc(a).con(".").con(field)
|
||||||
|
result.heapRoot = a.heapRoot
|
||||||
|
|
||||||
|
proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
|
for i in 0 .. <dest.t.len:
|
||||||
|
let t = dest.t.sons[i]
|
||||||
|
let field = ropef("Field$1", i.toRope)
|
||||||
|
genAssignment(p, optAsgnLoc(dest, t, field),
|
||||||
|
optAsgnLoc(src, t, field), flags)
|
||||||
|
|
||||||
|
proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
|
||||||
|
t: PNode) =
|
||||||
|
if t == nil: return
|
||||||
|
case t.kind
|
||||||
|
of nkSym:
|
||||||
|
let field = t.sym
|
||||||
|
genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r),
|
||||||
|
optAsgnLoc(src, field.typ, field.loc.r), flags)
|
||||||
|
of nkRecList:
|
||||||
|
for child in items(t): genOptAsgnObject(p, dest, src, flags, child)
|
||||||
|
else: nil
|
||||||
|
|
||||||
proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# Consider:
|
# Consider:
|
||||||
# type TMyFastString {.shallow.} = string
|
# type TMyFastString {.shallow.} = string
|
||||||
|
|
@ -251,10 +291,29 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
||||||
addrLoc(dest), rdLoc(src))
|
addrLoc(dest), rdLoc(src))
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||||
of tyTuple, tyObject, tyProc:
|
of tyProc:
|
||||||
|
if needsComplexAssignment(dest.t):
|
||||||
|
# optimize closure assignment:
|
||||||
|
let a = optAsgnLoc(dest, dest.t, "ClEnv".toRope)
|
||||||
|
let b = optAsgnLoc(src, dest.t, "ClEnv".toRope)
|
||||||
|
genRefAssign(p, a, b, flags)
|
||||||
|
linefmt(p, cpsStmts, "$1.ClPrc = $2.ClPrc;$n", rdLoc(dest), rdLoc(src))
|
||||||
|
else:
|
||||||
|
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||||
|
of tyTuple:
|
||||||
|
if needsComplexAssignment(dest.t):
|
||||||
|
if dest.t.len <= 4: genOptAsgnTuple(p, dest, src, flags)
|
||||||
|
else: genGenericAsgn(p, dest, src, flags)
|
||||||
|
else:
|
||||||
|
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||||
|
of tyObject:
|
||||||
# XXX: check for subtyping?
|
# XXX: check for subtyping?
|
||||||
if needsComplexAssignment(dest.t):
|
if needsComplexAssignment(dest.t):
|
||||||
genGenericAsgn(p, dest, src, flags)
|
if asgnComplexity(dest.t.n) <= 4:
|
||||||
|
discard getTypeDesc(p.module, dest.t)
|
||||||
|
genOptAsgnObject(p, dest, src, flags, dest.t.n)
|
||||||
|
else:
|
||||||
|
genGenericAsgn(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
|
|
@ -574,6 +633,28 @@ proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
|
||||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||||
result = a.t
|
result = a.t
|
||||||
|
|
||||||
|
proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
var
|
||||||
|
a: TLoc
|
||||||
|
i: int
|
||||||
|
initLocExpr(p, e.sons[0], a)
|
||||||
|
d.inheritLocation(a)
|
||||||
|
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||||
|
var ty = a.t
|
||||||
|
var r = rdLoc(a)
|
||||||
|
case e.sons[1].kind
|
||||||
|
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
|
||||||
|
else: internalError(e.info, "genTupleElem")
|
||||||
|
when false:
|
||||||
|
if ty.n != nil:
|
||||||
|
var field = ty.n.sons[i].sym
|
||||||
|
if field == nil: InternalError(e.info, "genTupleElem")
|
||||||
|
if field.loc.r == nil: InternalError(e.info, "genTupleElem")
|
||||||
|
appf(r, ".$1", [field.loc.r])
|
||||||
|
else:
|
||||||
|
appf(r, ".Field$1", [toRope(i)])
|
||||||
|
putIntoDest(p, d, ty.sons[i], r)
|
||||||
|
|
||||||
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
var ty = genRecordFieldAux(p, e, d, a)
|
var ty = genRecordFieldAux(p, e, d, a)
|
||||||
|
|
@ -598,38 +679,42 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
appf(r, ".$1", [field.loc.r])
|
appf(r, ".$1", [field.loc.r])
|
||||||
putIntoDest(p, d, field.typ, r)
|
putIntoDest(p, d, field.typ, r)
|
||||||
|
|
||||||
proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
|
||||||
var
|
|
||||||
a: TLoc
|
|
||||||
i: int
|
|
||||||
initLocExpr(p, e.sons[0], a)
|
|
||||||
d.inheritLocation(a)
|
|
||||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
|
||||||
var ty = a.t
|
|
||||||
var r = rdLoc(a)
|
|
||||||
case e.sons[1].kind
|
|
||||||
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
|
|
||||||
else: internalError(e.info, "genTupleElem")
|
|
||||||
when false:
|
|
||||||
if ty.n != nil:
|
|
||||||
var field = ty.n.sons[i].sym
|
|
||||||
if field == nil: InternalError(e.info, "genTupleElem")
|
|
||||||
if field.loc.r == nil: InternalError(e.info, "genTupleElem")
|
|
||||||
appf(r, ".$1", [field.loc.r])
|
|
||||||
else:
|
|
||||||
appf(r, ".Field$1", [toRope(i)])
|
|
||||||
putIntoDest(p, d, ty.sons[i], r)
|
|
||||||
|
|
||||||
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
|
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
|
||||||
|
|
||||||
|
proc genFieldCheck(p: BProc, e: PNode, obj: PRope, field: PSym) =
|
||||||
|
var test, u, v: TLoc
|
||||||
|
for i in countup(1, sonsLen(e) - 1):
|
||||||
|
var it = e.sons[i]
|
||||||
|
assert(it.kind in nkCallKinds)
|
||||||
|
assert(it.sons[0].kind == nkSym)
|
||||||
|
let op = it.sons[0].sym
|
||||||
|
if op.magic == mNot: it = it.sons[1]
|
||||||
|
assert(it.sons[2].kind == nkSym)
|
||||||
|
initLoc(test, locNone, it.typ, OnStack)
|
||||||
|
InitLocExpr(p, it.sons[1], u)
|
||||||
|
initLoc(v, locExpr, it.sons[2].typ, OnUnknown)
|
||||||
|
v.r = ropef("$1.$2", [obj, it.sons[2].sym.loc.r])
|
||||||
|
genInExprAux(p, it, u, v, test)
|
||||||
|
let id = NodeTableTestOrSet(p.module.dataCache,
|
||||||
|
newStrNode(nkStrLit, field.name.s), gBackendId)
|
||||||
|
let strLit = if id == gBackendId: getStrLit(p.module, field.name.s)
|
||||||
|
else: con("TMP", toRope(id))
|
||||||
|
if op.magic == mNot:
|
||||||
|
linefmt(p, cpsStmts,
|
||||||
|
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||||
|
rdLoc(test), strLit)
|
||||||
|
else:
|
||||||
|
linefmt(p, cpsStmts,
|
||||||
|
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
||||||
|
rdLoc(test), strLit)
|
||||||
|
|
||||||
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var
|
|
||||||
a, u, v, test: TLoc
|
|
||||||
f, field, op: PSym
|
|
||||||
ty: PType
|
|
||||||
r, strLit: PRope
|
|
||||||
id: int
|
|
||||||
it: PNode
|
|
||||||
if optFieldCheck in p.options:
|
if optFieldCheck in p.options:
|
||||||
|
var
|
||||||
|
a: TLoc
|
||||||
|
f, field: PSym
|
||||||
|
ty: PType
|
||||||
|
r: PRope
|
||||||
ty = genRecordFieldAux(p, e.sons[0], d, a)
|
ty = genRecordFieldAux(p, e.sons[0], d, a)
|
||||||
r = rdLoc(a)
|
r = rdLoc(a)
|
||||||
f = e.sons[0].sons[1].sym
|
f = e.sons[0].sons[1].sym
|
||||||
|
|
@ -643,30 +728,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if field == nil: InternalError(e.info, "genCheckedRecordField")
|
if field == nil: InternalError(e.info, "genCheckedRecordField")
|
||||||
if field.loc.r == nil:
|
if field.loc.r == nil:
|
||||||
InternalError(e.info, "genCheckedRecordField") # generate the checks:
|
InternalError(e.info, "genCheckedRecordField") # generate the checks:
|
||||||
for i in countup(1, sonsLen(e) - 1):
|
genFieldCheck(p, e, r, field)
|
||||||
it = e.sons[i]
|
|
||||||
assert(it.kind in nkCallKinds)
|
|
||||||
assert(it.sons[0].kind == nkSym)
|
|
||||||
op = it.sons[0].sym
|
|
||||||
if op.magic == mNot: it = it.sons[1]
|
|
||||||
assert(it.sons[2].kind == nkSym)
|
|
||||||
initLoc(test, locNone, it.typ, OnStack)
|
|
||||||
InitLocExpr(p, it.sons[1], u)
|
|
||||||
initLoc(v, locExpr, it.sons[2].typ, OnUnknown)
|
|
||||||
v.r = ropef("$1.$2", [r, it.sons[2].sym.loc.r])
|
|
||||||
genInExprAux(p, it, u, v, test)
|
|
||||||
id = NodeTableTestOrSet(p.module.dataCache,
|
|
||||||
newStrNode(nkStrLit, field.name.s), gBackendId)
|
|
||||||
if id == gBackendId: strLit = getStrLit(p.module, field.name.s)
|
|
||||||
else: strLit = con("TMP", toRope(id))
|
|
||||||
if op.magic == mNot:
|
|
||||||
linefmt(p, cpsStmts,
|
|
||||||
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
|
||||||
rdLoc(test), strLit)
|
|
||||||
else:
|
|
||||||
linefmt(p, cpsStmts,
|
|
||||||
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
|
|
||||||
rdLoc(test), strLit)
|
|
||||||
app(r, rfmt(nil, ".$1", field.loc.r))
|
app(r, rfmt(nil, ".$1", field.loc.r))
|
||||||
putIntoDest(p, d, field.typ, r)
|
putIntoDest(p, d, field.typ, r)
|
||||||
else:
|
else:
|
||||||
|
|
@ -913,10 +975,9 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
|
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
|
||||||
# seq->data[seq->len-1] = x;
|
# seq->data[seq->len-1] = x;
|
||||||
let seqAppendPattern = if gCmd != cmdCompileToCpp:
|
let seqAppendPattern = if gCmd != cmdCompileToCpp:
|
||||||
"$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n"
|
"$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n"
|
||||||
else:
|
else:
|
||||||
"$1 = ($2) #incrSeq($1, sizeof($3));$n"
|
"$1 = ($2) #incrSeq($1, sizeof($3));$n"
|
||||||
|
|
||||||
var a, b, dest: TLoc
|
var a, b, dest: TLoc
|
||||||
InitLocExpr(p, e.sons[1], a)
|
InitLocExpr(p, e.sons[1], a)
|
||||||
InitLocExpr(p, e.sons[2], b)
|
InitLocExpr(p, e.sons[2], b)
|
||||||
|
|
@ -935,20 +996,12 @@ proc genReset(p: BProc, n: PNode) =
|
||||||
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
|
||||||
addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange)))
|
addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange)))
|
||||||
|
|
||||||
proc genNew(p: BProc, e: PNode) =
|
proc rawGenNew(p: BProc, a: TLoc, sizeExpr: PRope) =
|
||||||
var
|
var sizeExpr = sizeExpr
|
||||||
a, b: TLoc
|
let refType = skipTypes(a.t, abstractVarRange)
|
||||||
reftype, bt: PType
|
var b: TLoc
|
||||||
sizeExpr: PRope
|
|
||||||
refType = skipTypes(e.sons[1].typ, abstractVarRange)
|
|
||||||
InitLocExpr(p, e.sons[1], a)
|
|
||||||
initLoc(b, locExpr, a.t, OnHeap)
|
initLoc(b, locExpr, a.t, OnHeap)
|
||||||
# 'genNew' also handles 'unsafeNew':
|
if sizeExpr.isNil:
|
||||||
if e.len == 3:
|
|
||||||
var se: TLoc
|
|
||||||
InitLocExpr(p, e.sons[2], se)
|
|
||||||
sizeExpr = se.rdLoc
|
|
||||||
else:
|
|
||||||
sizeExpr = ropef("sizeof($1)",
|
sizeExpr = ropef("sizeof($1)",
|
||||||
getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange)))
|
getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange)))
|
||||||
let args = [getTypeDesc(p.module, reftype),
|
let args = [getTypeDesc(p.module, reftype),
|
||||||
|
|
@ -965,9 +1018,20 @@ proc genNew(p: BProc, e: PNode) =
|
||||||
else:
|
else:
|
||||||
b.r = ropecg(p.module, "($1) #newObj($2, $3)", args)
|
b.r = ropecg(p.module, "($1) #newObj($2, $3)", args)
|
||||||
genAssignment(p, a, b, {needToKeepAlive}) # set the object type:
|
genAssignment(p, a, b, {needToKeepAlive}) # set the object type:
|
||||||
bt = skipTypes(refType.sons[0], abstractRange)
|
let bt = skipTypes(refType.sons[0], abstractRange)
|
||||||
genObjectInit(p, cpsStmts, bt, a, false)
|
genObjectInit(p, cpsStmts, bt, a, false)
|
||||||
|
|
||||||
|
proc genNew(p: BProc, e: PNode) =
|
||||||
|
var a: TLoc
|
||||||
|
InitLocExpr(p, e.sons[1], a)
|
||||||
|
# 'genNew' also handles 'unsafeNew':
|
||||||
|
if e.len == 3:
|
||||||
|
var se: TLoc
|
||||||
|
InitLocExpr(p, e.sons[2], se)
|
||||||
|
rawGenNew(p, a, se.rdLoc)
|
||||||
|
else:
|
||||||
|
rawGenNew(p, a, nil)
|
||||||
|
|
||||||
proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
|
proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
|
||||||
let seqtype = skipTypes(dest.t, abstractVarRange)
|
let seqtype = skipTypes(dest.t, abstractVarRange)
|
||||||
let args = [getTypeDesc(p.module, seqtype),
|
let args = [getTypeDesc(p.module, seqtype),
|
||||||
|
|
@ -975,7 +1039,10 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
|
||||||
var call: TLoc
|
var call: TLoc
|
||||||
initLoc(call, locExpr, dest.t, OnHeap)
|
initLoc(call, locExpr, dest.t, OnHeap)
|
||||||
if dest.s == OnHeap and usesNativeGC():
|
if dest.s == OnHeap and usesNativeGC():
|
||||||
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
|
if canFormAcycle(dest.t):
|
||||||
|
linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", dest.rdLoc)
|
||||||
|
else:
|
||||||
|
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
|
||||||
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
|
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
|
||||||
linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
|
linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
|
||||||
else:
|
else:
|
||||||
|
|
@ -988,6 +1055,44 @@ proc genNewSeq(p: BProc, e: PNode) =
|
||||||
InitLocExpr(p, e.sons[2], b)
|
InitLocExpr(p, e.sons[2], b)
|
||||||
genNewSeqAux(p, a, b.rdLoc)
|
genNewSeqAux(p, a, b.rdLoc)
|
||||||
|
|
||||||
|
proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
var tmp: TLoc
|
||||||
|
var t = e.typ.skipTypes(abstractInst)
|
||||||
|
getTemp(p, t, tmp)
|
||||||
|
let isRef = t.kind == tyRef
|
||||||
|
var r = rdLoc(tmp)
|
||||||
|
if isRef:
|
||||||
|
rawGenNew(p, tmp, nil)
|
||||||
|
t = t.sons[0].skipTypes(abstractInst)
|
||||||
|
r = ropef("(*$1)", r)
|
||||||
|
# XXX object initialization? but not necessary for temps, is it?
|
||||||
|
discard getTypeDesc(p.module, t)
|
||||||
|
for i in 1 .. <e.len:
|
||||||
|
let it = e.sons[i]
|
||||||
|
var tmp2: TLoc
|
||||||
|
tmp2.r = r
|
||||||
|
var field: PSym = nil
|
||||||
|
var ty = t
|
||||||
|
while ty != nil:
|
||||||
|
field = lookupInRecord(ty.n, it.sons[0].sym.name)
|
||||||
|
if field != nil: break
|
||||||
|
if gCmd != cmdCompileToCpp: app(tmp2.r, ".Sup")
|
||||||
|
ty = GetUniqueType(ty.sons[0])
|
||||||
|
if field == nil or field.loc.r == nil: InternalError(e.info, "genObjConstr")
|
||||||
|
if it.len == 3 and optFieldCheck in p.options:
|
||||||
|
genFieldCheck(p, it.sons[2], r, field)
|
||||||
|
app(tmp2.r, ".")
|
||||||
|
app(tmp2.r, field.loc.r)
|
||||||
|
tmp2.k = locTemp
|
||||||
|
tmp2.t = field.loc.t
|
||||||
|
tmp2.s = onHeap
|
||||||
|
tmp2.heapRoot = tmp.r
|
||||||
|
expr(p, it.sons[1], tmp2)
|
||||||
|
if d.k == locNone:
|
||||||
|
d = tmp
|
||||||
|
else:
|
||||||
|
genAssignment(p, d, tmp, {})
|
||||||
|
|
||||||
proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
|
proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
|
||||||
var arr: TLoc
|
var arr: TLoc
|
||||||
if d.k == locNone:
|
if d.k == locNone:
|
||||||
|
|
@ -995,7 +1100,7 @@ proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
|
||||||
# generate call to newSeq before adding the elements per hand:
|
# generate call to newSeq before adding the elements per hand:
|
||||||
genNewSeqAux(p, d, intLiteral(sonsLen(t)))
|
genNewSeqAux(p, d, intLiteral(sonsLen(t)))
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
initLoc(arr, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap)
|
initLoc(arr, locExpr, elemType(skipTypes(t.typ, typedescInst)), OnHeap)
|
||||||
arr.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i))
|
arr.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i))
|
||||||
arr.s = OnHeap # we know that sequences are on the heap
|
arr.s = OnHeap # we know that sequences are on the heap
|
||||||
expr(p, t.sons[i], arr)
|
expr(p, t.sons[i], arr)
|
||||||
|
|
@ -1226,8 +1331,14 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var a, b, x, y: TLoc
|
var a, b, x, y: TLoc
|
||||||
if (e.sons[1].Kind == nkCurly) and fewCmps(e.sons[1]):
|
if (e.sons[1].Kind == nkCurly) and fewCmps(e.sons[1]):
|
||||||
# a set constructor but not a constant set:
|
# a set constructor but not a constant set:
|
||||||
# do not emit the set, but generate a bunch of comparisons
|
# do not emit the set, but generate a bunch of comparisons; and if we do
|
||||||
initLocExpr(p, e.sons[2], a)
|
# so, we skip the unnecessary range check: This is a semantical extension
|
||||||
|
# that code now relies on. :-/ XXX
|
||||||
|
let ea = if e.sons[2].kind in {nkChckRange, nkChckRange64}:
|
||||||
|
e.sons[2].sons[0]
|
||||||
|
else:
|
||||||
|
e.sons[2]
|
||||||
|
initLocExpr(p, ea, a)
|
||||||
initLoc(b, locExpr, e.typ, OnUnknown)
|
initLoc(b, locExpr, e.typ, OnUnknown)
|
||||||
b.r = toRope("(")
|
b.r = toRope("(")
|
||||||
var length = sonsLen(e.sons[1])
|
var length = sonsLen(e.sons[1])
|
||||||
|
|
@ -1467,8 +1578,9 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
of mNewFinalize: genNewFinalize(p, e)
|
of mNewFinalize: genNewFinalize(p, e)
|
||||||
of mNewSeq: genNewSeq(p, e)
|
of mNewSeq: genNewSeq(p, e)
|
||||||
of mSizeOf:
|
of mSizeOf:
|
||||||
|
let t = e.sons[1].typ.skipTypes({tyTypeDesc})
|
||||||
putIntoDest(p, d, e.typ, ropef("((NI)sizeof($1))",
|
putIntoDest(p, d, e.typ, ropef("((NI)sizeof($1))",
|
||||||
[getTypeDesc(p.module, e.sons[1].typ)]))
|
[getTypeDesc(p.module, t)]))
|
||||||
of mChr: genCast(p, e, d)
|
of mChr: genCast(p, e, d)
|
||||||
of mOrd: genOrd(p, e, d)
|
of mOrd: genOrd(p, e, d)
|
||||||
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
|
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
|
||||||
|
|
@ -1755,6 +1867,7 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
exprComplexConst(p, e, d)
|
exprComplexConst(p, e, d)
|
||||||
else:
|
else:
|
||||||
genTupleConstr(p, e, d)
|
genTupleConstr(p, e, d)
|
||||||
|
of nkObjConstr: genObjConstr(p, e, d)
|
||||||
of nkCast: genCast(p, e, d)
|
of nkCast: genCast(p, e, d)
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, e, d)
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, e, d)
|
||||||
of nkHiddenAddr, nkAddr: genAddr(p, e, d)
|
of nkHiddenAddr, nkAddr: genAddr(p, e, d)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
## is needed for incremental compilation.
|
## is needed for incremental compilation.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, ropes, options, strutils, lexbase, msgs, cgendata, rodutils,
|
ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils,
|
||||||
intsets, platform, llstream
|
intsets, platform, llstream
|
||||||
|
|
||||||
# Careful! Section marks need to contain a tabulator so that they cannot
|
# Careful! Section marks need to contain a tabulator so that they cannot
|
||||||
|
|
@ -45,11 +45,8 @@ const
|
||||||
]
|
]
|
||||||
NimMergeEndMark = "/*\tNIM_merge_END:*/"
|
NimMergeEndMark = "/*\tNIM_merge_END:*/"
|
||||||
|
|
||||||
template mergeSectionsEnabled: expr =
|
|
||||||
{optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
|
|
||||||
|
|
||||||
proc genSectionStart*(fs: TCFileSection): PRope =
|
proc genSectionStart*(fs: TCFileSection): PRope =
|
||||||
if mergeSectionsEnabled:
|
if compilationCachePresent:
|
||||||
result = toRope(tnl)
|
result = toRope(tnl)
|
||||||
app(result, "/*\t")
|
app(result, "/*\t")
|
||||||
app(result, CFileSectionNames[fs])
|
app(result, CFileSectionNames[fs])
|
||||||
|
|
@ -57,11 +54,11 @@ proc genSectionStart*(fs: TCFileSection): PRope =
|
||||||
app(result, tnl)
|
app(result, tnl)
|
||||||
|
|
||||||
proc genSectionEnd*(fs: TCFileSection): PRope =
|
proc genSectionEnd*(fs: TCFileSection): PRope =
|
||||||
if mergeSectionsEnabled:
|
if compilationCachePresent:
|
||||||
result = toRope(NimMergeEndMark & tnl)
|
result = toRope(NimMergeEndMark & tnl)
|
||||||
|
|
||||||
proc genSectionStart*(ps: TCProcSection): PRope =
|
proc genSectionStart*(ps: TCProcSection): PRope =
|
||||||
if mergeSectionsEnabled:
|
if compilationCachePresent:
|
||||||
result = toRope(tnl)
|
result = toRope(tnl)
|
||||||
app(result, "/*\t")
|
app(result, "/*\t")
|
||||||
app(result, CProcSectionNames[ps])
|
app(result, CProcSectionNames[ps])
|
||||||
|
|
@ -69,7 +66,7 @@ proc genSectionStart*(ps: TCProcSection): PRope =
|
||||||
app(result, tnl)
|
app(result, tnl)
|
||||||
|
|
||||||
proc genSectionEnd*(ps: TCProcSection): PRope =
|
proc genSectionEnd*(ps: TCProcSection): PRope =
|
||||||
if mergeSectionsEnabled:
|
if compilationCachePresent:
|
||||||
result = toRope(NimMergeEndMark & tnl)
|
result = toRope(NimMergeEndMark & tnl)
|
||||||
|
|
||||||
proc writeTypeCache(a: TIdTable, s: var string) =
|
proc writeTypeCache(a: TIdTable, s: var string) =
|
||||||
|
|
@ -122,8 +119,8 @@ proc skipWhite(L: var TBaseLexer) =
|
||||||
var pos = L.bufpos
|
var pos = L.bufpos
|
||||||
while true:
|
while true:
|
||||||
case ^pos
|
case ^pos
|
||||||
of CR: pos = lexbase.HandleCR(L, pos)
|
of CR: pos = nimlexbase.HandleCR(L, pos)
|
||||||
of LF: pos = lexbase.HandleLF(L, pos)
|
of LF: pos = nimlexbase.HandleLF(L, pos)
|
||||||
of ' ': inc pos
|
of ' ': inc pos
|
||||||
else: break
|
else: break
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
@ -132,8 +129,8 @@ proc skipUntilCmd(L: var TBaseLexer) =
|
||||||
var pos = L.bufpos
|
var pos = L.bufpos
|
||||||
while true:
|
while true:
|
||||||
case ^pos
|
case ^pos
|
||||||
of CR: pos = lexbase.HandleCR(L, pos)
|
of CR: pos = nimlexbase.HandleCR(L, pos)
|
||||||
of LF: pos = lexbase.HandleLF(L, pos)
|
of LF: pos = nimlexbase.HandleLF(L, pos)
|
||||||
of '\0': break
|
of '\0': break
|
||||||
of '/':
|
of '/':
|
||||||
if ^(pos+1) == '*' and ^(pos+2) == '\t':
|
if ^(pos+1) == '*' and ^(pos+2) == '\t':
|
||||||
|
|
@ -156,11 +153,11 @@ when false:
|
||||||
while true:
|
while true:
|
||||||
case buf[pos]
|
case buf[pos]
|
||||||
of CR:
|
of CR:
|
||||||
pos = lexbase.HandleCR(L, pos)
|
pos = nimlexbase.HandleCR(L, pos)
|
||||||
buf = L.buf
|
buf = L.buf
|
||||||
result.data.add(tnl)
|
result.data.add(tnl)
|
||||||
of LF:
|
of LF:
|
||||||
pos = lexbase.HandleLF(L, pos)
|
pos = nimlexbase.HandleLF(L, pos)
|
||||||
buf = L.buf
|
buf = L.buf
|
||||||
result.data.add(tnl)
|
result.data.add(tnl)
|
||||||
of '\0':
|
of '\0':
|
||||||
|
|
@ -182,11 +179,11 @@ proc readVerbatimSection(L: var TBaseLexer): PRope =
|
||||||
while true:
|
while true:
|
||||||
case buf[pos]
|
case buf[pos]
|
||||||
of CR:
|
of CR:
|
||||||
pos = lexbase.HandleCR(L, pos)
|
pos = nimlexbase.HandleCR(L, pos)
|
||||||
buf = L.buf
|
buf = L.buf
|
||||||
r.add(tnl)
|
r.add(tnl)
|
||||||
of LF:
|
of LF:
|
||||||
pos = lexbase.HandleLF(L, pos)
|
pos = nimlexbase.HandleLF(L, pos)
|
||||||
buf = L.buf
|
buf = L.buf
|
||||||
r.add(tnl)
|
r.add(tnl)
|
||||||
of '\0':
|
of '\0':
|
||||||
|
|
|
||||||
41
compiler/ccgstmts.nim
Executable file → Normal file
41
compiler/ccgstmts.nim
Executable file → Normal file
|
|
@ -16,7 +16,8 @@ const
|
||||||
# above X strings a hash-switch for strings is generated
|
# above X strings a hash-switch for strings is generated
|
||||||
|
|
||||||
proc registerGcRoot(p: BProc, v: PSym) =
|
proc registerGcRoot(p: BProc, v: PSym) =
|
||||||
if gSelectedGc == gcMarkAndSweep and containsGarbageCollectedRef(v.loc.t):
|
if gSelectedGc in {gcMarkAndSweep, gcGenerational} and
|
||||||
|
containsGarbageCollectedRef(v.loc.t):
|
||||||
# we register a specialized marked proc here; this has the advantage
|
# we register a specialized marked proc here; this has the advantage
|
||||||
# that it works out of the box for thread local storage then :-)
|
# that it works out of the box for thread local storage then :-)
|
||||||
let prc = genTraverseProcForGlobal(p.module, v)
|
let prc = genTraverseProcForGlobal(p.module, v)
|
||||||
|
|
@ -44,7 +45,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||||
if t.kind == tyTuple:
|
if t.kind == tyTuple:
|
||||||
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
|
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
|
||||||
else:
|
else:
|
||||||
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genVarTuple")
|
if t.n.sons[i].kind != nkSym: InternalError(n.info, "genVarTuple")
|
||||||
field.r = ropef("$1.$2",
|
field.r = ropef("$1.$2",
|
||||||
[rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
|
[rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
|
||||||
putLocIntoDest(p, v.loc, field)
|
putLocIntoDest(p, v.loc, field)
|
||||||
|
|
@ -63,19 +64,23 @@ proc startBlock(p: BProc, start: TFormatStr = "{$n",
|
||||||
result = len(p.blocks)
|
result = len(p.blocks)
|
||||||
setlen(p.blocks, result + 1)
|
setlen(p.blocks, result + 1)
|
||||||
p.blocks[result].id = p.labels
|
p.blocks[result].id = p.labels
|
||||||
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len
|
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
|
||||||
|
|
||||||
proc assignLabel(b: var TBlock): PRope {.inline.} =
|
proc assignLabel(b: var TBlock): PRope {.inline.} =
|
||||||
b.label = con("LA", b.id.toRope)
|
b.label = con("LA", b.id.toRope)
|
||||||
result = b.label
|
result = b.label
|
||||||
|
|
||||||
proc blockBody(b: var TBlock): PRope {.inline.} =
|
proc blockBody(b: var TBlock): PRope =
|
||||||
return b.sections[cpsLocals].con(b.sections[cpsInit]).con(b.sections[cpsStmts])
|
result = b.sections[cpsLocals]
|
||||||
|
if b.frameLen > 0:
|
||||||
|
result.appf("F.len+=$1;$n", b.frameLen.toRope)
|
||||||
|
result.app(b.sections[cpsInit])
|
||||||
|
result.app(b.sections[cpsStmts])
|
||||||
|
|
||||||
proc endBlock(p: BProc, blockEnd: PRope) =
|
proc endBlock(p: BProc, blockEnd: PRope) =
|
||||||
let topBlock = p.blocks.len - 1
|
let topBlock = p.blocks.len-1
|
||||||
# the block is merged into the parent block
|
# the block is merged into the parent block
|
||||||
app(p.blocks[topBlock - 1].sections[cpsStmts], p.blocks[topBlock].blockBody)
|
app(p.blocks[topBlock-1].sections[cpsStmts], p.blocks[topBlock].blockBody)
|
||||||
setlen(p.blocks, topBlock)
|
setlen(p.blocks, topBlock)
|
||||||
# this is done after the block is popped so $n is
|
# this is done after the block is popped so $n is
|
||||||
# properly indented when pretty printing is enabled
|
# properly indented when pretty printing is enabled
|
||||||
|
|
@ -83,10 +88,13 @@ proc endBlock(p: BProc, blockEnd: PRope) =
|
||||||
|
|
||||||
proc endBlock(p: BProc) =
|
proc endBlock(p: BProc) =
|
||||||
let topBlock = p.blocks.len - 1
|
let topBlock = p.blocks.len - 1
|
||||||
let blockEnd = if p.blocks[topBlock].label != nil:
|
var blockEnd = if p.blocks[topBlock].label != nil:
|
||||||
rfmt(nil, "} $1: ;$n", p.blocks[topBlock].label)
|
rfmt(nil, "} $1: ;$n", p.blocks[topBlock].label)
|
||||||
else:
|
else:
|
||||||
~"}$n"
|
~"}$n"
|
||||||
|
let frameLen = p.blocks[topBlock].frameLen
|
||||||
|
if frameLen > 0:
|
||||||
|
blockEnd.appf("F.len-=$1;$n", frameLen.toRope)
|
||||||
endBlock(p, blockEnd)
|
endBlock(p, blockEnd)
|
||||||
|
|
||||||
proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} =
|
proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} =
|
||||||
|
|
@ -773,7 +781,7 @@ var
|
||||||
|
|
||||||
proc genBreakPoint(p: BProc, t: PNode) =
|
proc genBreakPoint(p: BProc, t: PNode) =
|
||||||
var name: string
|
var name: string
|
||||||
if optEndb in p.Options:
|
if optEndb in p.Options:
|
||||||
if t.kind == nkExprColonExpr:
|
if t.kind == nkExprColonExpr:
|
||||||
assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit})
|
assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit})
|
||||||
name = normalize(t.sons[1].strVal)
|
name = normalize(t.sons[1].strVal)
|
||||||
|
|
@ -783,7 +791,7 @@ proc genBreakPoint(p: BProc, t: PNode) =
|
||||||
genLineDir(p, t) # BUGFIX
|
genLineDir(p, t) # BUGFIX
|
||||||
appcg(p.module, gBreakpoints,
|
appcg(p.module, gBreakpoints,
|
||||||
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
|
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
|
||||||
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
|
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
|
||||||
makeCString(name)])
|
makeCString(name)])
|
||||||
|
|
||||||
proc genWatchpoint(p: BProc, n: PNode) =
|
proc genWatchpoint(p: BProc, n: PNode) =
|
||||||
|
|
@ -795,16 +803,13 @@ proc genWatchpoint(p: BProc, n: PNode) =
|
||||||
[a.addrLoc, makeCString(renderTree(n.sons[1])),
|
[a.addrLoc, makeCString(renderTree(n.sons[1])),
|
||||||
genTypeInfo(p.module, typ)])
|
genTypeInfo(p.module, typ)])
|
||||||
|
|
||||||
proc genPragma(p: BProc, n: PNode) =
|
proc genPragma(p: BProc, n: PNode) =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
case whichPragma(it)
|
case whichPragma(it)
|
||||||
of wEmit:
|
of wEmit: genEmit(p, it)
|
||||||
genEmit(p, it)
|
of wBreakpoint: genBreakPoint(p, it)
|
||||||
of wBreakpoint:
|
of wWatchpoint: genWatchpoint(p, it)
|
||||||
genBreakPoint(p, it)
|
|
||||||
of wWatchpoint:
|
|
||||||
genWatchpoint(p, it)
|
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
proc FieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
||||||
|
|
|
||||||
0
compiler/ccgthreadvars.nim
Executable file → Normal file
0
compiler/ccgthreadvars.nim
Executable file → Normal file
|
|
@ -59,7 +59,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
|
||||||
if typ == nil: return
|
if typ == nil: return
|
||||||
var p = c.p
|
var p = c.p
|
||||||
case typ.kind
|
case typ.kind
|
||||||
of tyGenericInst, tyGenericBody:
|
of tyGenericInst, tyGenericBody, tyTypeDesc:
|
||||||
genTraverseProc(c, accessor, lastSon(typ))
|
genTraverseProc(c, accessor, lastSon(typ))
|
||||||
of tyArrayConstr, tyArray:
|
of tyArrayConstr, tyArray:
|
||||||
let arraySize = lengthOrd(typ.sons[0])
|
let arraySize = lengthOrd(typ.sons[0])
|
||||||
|
|
@ -111,10 +111,11 @@ proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
|
||||||
lineF(p, cpsInit, "a = ($1)p;$n", t)
|
lineF(p, cpsInit, "a = ($1)p;$n", t)
|
||||||
|
|
||||||
c.p = p
|
c.p = p
|
||||||
|
assert typ.kind != tyTypedesc
|
||||||
if typ.kind == tySequence:
|
if typ.kind == tySequence:
|
||||||
genTraverseProcSeq(c, "a".toRope, typ)
|
genTraverseProcSeq(c, "a".toRope, typ)
|
||||||
else:
|
else:
|
||||||
if skipTypes(typ.sons[0], abstractInst).kind in {tyArrayConstr, tyArray}:
|
if skipTypes(typ.sons[0], typedescInst).kind in {tyArrayConstr, tyArray}:
|
||||||
# C's arrays are broken beyond repair:
|
# C's arrays are broken beyond repair:
|
||||||
genTraverseProc(c, "a".toRope, typ.sons[0])
|
genTraverseProc(c, "a".toRope, typ.sons[0])
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
22
compiler/ccgtypes.nim
Executable file → Normal file
22
compiler/ccgtypes.nim
Executable file → Normal file
|
|
@ -193,8 +193,8 @@ proc mapType(typ: PType): TCTypeKind =
|
||||||
of 8: result = ctInt64
|
of 8: result = ctInt64
|
||||||
else: internalError("mapType")
|
else: internalError("mapType")
|
||||||
of tyRange: result = mapType(typ.sons[0])
|
of tyRange: result = mapType(typ.sons[0])
|
||||||
of tyPtr, tyVar, tyRef:
|
of tyPtr, tyVar, tyRef:
|
||||||
var base = skipTypes(typ.sons[0], abstractInst)
|
var base = skipTypes(typ.sons[0], typedescInst)
|
||||||
case base.kind
|
case base.kind
|
||||||
of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctArray
|
of tyOpenArray, tyArrayConstr, tyArray, tyVarargs: result = ctArray
|
||||||
else: result = ctPtr
|
else: result = ctPtr
|
||||||
|
|
@ -208,7 +208,7 @@ proc mapType(typ: PType): TCTypeKind =
|
||||||
else: InternalError("mapType")
|
else: InternalError("mapType")
|
||||||
|
|
||||||
proc mapReturnType(typ: PType): TCTypeKind =
|
proc mapReturnType(typ: PType): TCTypeKind =
|
||||||
if skipTypes(typ, abstractInst).kind == tyArray: result = ctPtr
|
if skipTypes(typ, typedescInst).kind == tyArray: result = ctPtr
|
||||||
else: result = mapType(typ)
|
else: result = mapType(typ)
|
||||||
|
|
||||||
proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope
|
proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope
|
||||||
|
|
@ -224,10 +224,10 @@ proc isInvalidReturnType(rettype: PType): bool =
|
||||||
else:
|
else:
|
||||||
case mapType(rettype)
|
case mapType(rettype)
|
||||||
of ctArray:
|
of ctArray:
|
||||||
result = not (skipTypes(rettype, abstractInst).kind in
|
result = not (skipTypes(rettype, typedescInst).kind in
|
||||||
{tyVar, tyRef, tyPtr})
|
{tyVar, tyRef, tyPtr})
|
||||||
of ctStruct:
|
of ctStruct:
|
||||||
result = needsComplexAssignment(skipTypes(rettype, abstractInst))
|
result = needsComplexAssignment(skipTypes(rettype, typedescInst))
|
||||||
else: result = false
|
else: result = false
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -253,7 +253,7 @@ proc getGlobalTempName(): PRope =
|
||||||
result = rfmt(nil, "TMP$1", toRope(backendId()))
|
result = rfmt(nil, "TMP$1", toRope(backendId()))
|
||||||
|
|
||||||
proc ccgIntroducedPtr(s: PSym): bool =
|
proc ccgIntroducedPtr(s: PSym): bool =
|
||||||
var pt = skipTypes(s.typ, abstractInst)
|
var pt = skipTypes(s.typ, typedescInst)
|
||||||
assert skResult != s.kind
|
assert skResult != s.kind
|
||||||
if tfByRef in pt.flags: return true
|
if tfByRef in pt.flags: return true
|
||||||
elif tfByCopy in pt.flags: return false
|
elif tfByCopy in pt.flags: return false
|
||||||
|
|
@ -280,13 +280,13 @@ proc fillResult(param: PSym) =
|
||||||
proc getParamTypeDesc(m: BModule, t: PType, check: var TIntSet): PRope =
|
proc getParamTypeDesc(m: BModule, t: PType, check: var TIntSet): PRope =
|
||||||
when false:
|
when false:
|
||||||
if t.Kind in {tyRef, tyPtr, tyVar}:
|
if t.Kind in {tyRef, tyPtr, tyVar}:
|
||||||
var b = skipTypes(t.sons[0], abstractInst)
|
var b = skipTypes(t.sons[0], typedescInst)
|
||||||
if b.kind == tySet and mapSetType(b) == ctArray:
|
if b.kind == tySet and mapSetType(b) == ctArray:
|
||||||
return getTypeDescAux(m, b, check)
|
return getTypeDescAux(m, b, check)
|
||||||
result = getTypeDescAux(m, t, check)
|
result = getTypeDescAux(m, t, check)
|
||||||
|
|
||||||
proc paramStorageLoc(param: PSym): TStorageLoc =
|
proc paramStorageLoc(param: PSym): TStorageLoc =
|
||||||
if param.typ.skipTypes({tyVar}).kind notin {tyArray, tyOpenArray}:
|
if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {tyArray, tyOpenArray}:
|
||||||
result = OnStack
|
result = OnStack
|
||||||
else:
|
else:
|
||||||
result = OnUnknown
|
result = OnUnknown
|
||||||
|
|
@ -572,7 +572,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
|
||||||
assert(CacheGetType(m.typeCache, t) == nil)
|
assert(CacheGetType(m.typeCache, t) == nil)
|
||||||
IdTablePut(m.typeCache, t, con(result, "*"))
|
IdTablePut(m.typeCache, t, con(result, "*"))
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
if skipTypes(t.sons[0], abstractInst).kind != tyEmpty:
|
if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
|
||||||
const
|
const
|
||||||
cppSeq = "struct $2 : #TGenericSeq {$n"
|
cppSeq = "struct $2 : #TGenericSeq {$n"
|
||||||
cSeq = "struct $2 {$n" &
|
cSeq = "struct $2 {$n" &
|
||||||
|
|
@ -744,7 +744,7 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope =
|
||||||
if objType.sym == nil:
|
if objType.sym == nil:
|
||||||
InternalError(d.info, "anonymous obj with discriminator")
|
InternalError(d.info, "anonymous obj with discriminator")
|
||||||
result = ropef("NimDT_$1_$2", [
|
result = ropef("NimDT_$1_$2", [
|
||||||
toRope(objType.sym.name.s), toRope(d.name.s)])
|
toRope(objType.sym.name.s.mangle), toRope(d.name.s.mangle)])
|
||||||
|
|
||||||
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope =
|
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope =
|
||||||
discard cgsym(m, "TNimNode")
|
discard cgsym(m, "TNimNode")
|
||||||
|
|
@ -915,7 +915,7 @@ include ccgtrav
|
||||||
proc genTypeInfo(m: BModule, typ: PType): PRope =
|
proc genTypeInfo(m: BModule, typ: PType): PRope =
|
||||||
var t = getUniqueType(typ)
|
var t = getUniqueType(typ)
|
||||||
result = ropef("NTI$1", [toRope(t.id)])
|
result = ropef("NTI$1", [toRope(t.id)])
|
||||||
let owner = typ.skipTypes(abstractPtrs).owner.getModule
|
let owner = typ.skipTypes(typedescPtrs).owner.getModule
|
||||||
if owner != m.module:
|
if owner != m.module:
|
||||||
# make sure the type info is created in the owner module
|
# make sure the type info is created in the owner module
|
||||||
discard genTypeInfo(owner.bmod, typ)
|
discard genTypeInfo(owner.bmod, typ)
|
||||||
|
|
|
||||||
4
compiler/ccgutils.nim
Executable file → Normal file
4
compiler/ccgutils.nim
Executable file → Normal file
|
|
@ -80,13 +80,13 @@ proc GetUniqueType*(key: PType): PType =
|
||||||
# no canonicalization for integral types, so that e.g. ``pid_t`` is
|
# no canonicalization for integral types, so that e.g. ``pid_t`` is
|
||||||
# produced instead of ``NI``.
|
# produced instead of ``NI``.
|
||||||
result = key
|
result = key
|
||||||
of tyEmpty, tyNil, tyExpr, tyStmt, tyTypeDesc, tyPointer, tyString,
|
of tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString,
|
||||||
tyCString, tyNone, tyBigNum:
|
tyCString, tyNone, tyBigNum:
|
||||||
result = gCanonicalTypes[k]
|
result = gCanonicalTypes[k]
|
||||||
if result == nil:
|
if result == nil:
|
||||||
gCanonicalTypes[k] = key
|
gCanonicalTypes[k] = key
|
||||||
result = key
|
result = key
|
||||||
of tyGenericParam, tyTypeClass:
|
of tyGenericParam, tyTypeClass, tyTypeDesc:
|
||||||
InternalError("GetUniqueType")
|
InternalError("GetUniqueType")
|
||||||
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
|
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
|
||||||
result = GetUniqueType(lastSon(key))
|
result = GetUniqueType(lastSon(key))
|
||||||
|
|
|
||||||
41
compiler/cgen.nim
Executable file → Normal file
41
compiler/cgen.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -269,18 +269,18 @@ proc genCLineDir(r: var PRope, filename: string, line: int) =
|
||||||
proc genCLineDir(r: var PRope, info: TLineInfo) =
|
proc genCLineDir(r: var PRope, info: TLineInfo) =
|
||||||
genCLineDir(r, info.toFullPath, info.safeLineNm)
|
genCLineDir(r, info.toFullPath, info.safeLineNm)
|
||||||
|
|
||||||
proc genLineDir(p: BProc, t: PNode) =
|
proc genLineDir(p: BProc, t: PNode) =
|
||||||
var line = t.info.safeLineNm
|
var line = t.info.safeLineNm
|
||||||
if optEmbedOrigSrc in gGlobalOptions:
|
if optEmbedOrigSrc in gGlobalOptions:
|
||||||
app(p.s(cpsStmts), con(~"//", t.info.sourceLine, rnl))
|
app(p.s(cpsStmts), con(~"//", t.info.sourceLine, rnl))
|
||||||
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
|
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
|
||||||
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
|
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
|
||||||
(p.prc == nil or sfPure notin p.prc.flags):
|
(p.prc == nil or sfPure notin p.prc.flags):
|
||||||
linefmt(p, cpsStmts, "#endb($1);$n", toRope(line))
|
linefmt(p, cpsStmts, "#endb($1, $2);$n",
|
||||||
|
line.toRope, makeCString(toFilename(t.info)))
|
||||||
elif ({optLineTrace, optStackTrace} * p.Options ==
|
elif ({optLineTrace, optStackTrace} * p.Options ==
|
||||||
{optLineTrace, optStackTrace}) and
|
{optLineTrace, optStackTrace}) and
|
||||||
(p.prc == nil or sfPure notin p.prc.flags):
|
(p.prc == nil or sfPure notin p.prc.flags):
|
||||||
|
|
||||||
linefmt(p, cpsStmts, "nimln($1, $2);$n",
|
linefmt(p, cpsStmts, "nimln($1, $2);$n",
|
||||||
line.toRope, t.info.quotedFilename)
|
line.toRope, t.info.quotedFilename)
|
||||||
|
|
||||||
|
|
@ -470,12 +470,13 @@ proc localDebugInfo(p: BProc, s: PSym) =
|
||||||
# XXX work around a bug: No type information for open arrays possible:
|
# XXX work around a bug: No type information for open arrays possible:
|
||||||
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
|
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
|
||||||
var a = con("&", s.loc.r)
|
var a = con("&", s.loc.r)
|
||||||
if (s.kind == skParam) and ccgIntroducedPtr(s): a = s.loc.r
|
if s.kind == skParam and ccgIntroducedPtr(s): a = s.loc.r
|
||||||
lineF(p, cpsInit,
|
lineF(p, cpsInit,
|
||||||
"F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n",
|
"F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n",
|
||||||
[toRope(p.frameLen), makeCString(normalize(s.name.s)), a,
|
[p.maxFrameLen.toRope, makeCString(normalize(s.name.s)), a,
|
||||||
genTypeInfo(p.module, s.loc.t)])
|
genTypeInfo(p.module, s.loc.t)])
|
||||||
inc(p.frameLen)
|
inc(p.maxFrameLen)
|
||||||
|
inc p.blocks[p.blocks.len-1].frameLen
|
||||||
|
|
||||||
proc assignLocalVar(p: BProc, s: PSym) =
|
proc assignLocalVar(p: BProc, s: PSym) =
|
||||||
#assert(s.loc.k == locNone) // not yet assigned
|
#assert(s.loc.k == locNone) // not yet assigned
|
||||||
|
|
@ -488,7 +489,7 @@ proc assignLocalVar(p: BProc, s: PSym) =
|
||||||
if sfRegister in s.flags: app(decl, " register")
|
if sfRegister in s.flags: app(decl, " register")
|
||||||
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
|
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
|
||||||
# app(decl, " GC_GUARD")
|
# app(decl, " GC_GUARD")
|
||||||
if (sfVolatile in s.flags) or (p.nestedTryStmts.len > 0):
|
if sfVolatile in s.flags or p.nestedTryStmts.len > 0:
|
||||||
app(decl, " volatile")
|
app(decl, " volatile")
|
||||||
appf(decl, " $1;$n", [s.loc.r])
|
appf(decl, " $1;$n", [s.loc.r])
|
||||||
line(p, cpsLocals, decl)
|
line(p, cpsLocals, decl)
|
||||||
|
|
@ -574,6 +575,8 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||||
if lib.path.kind in {nkStrLit..nkTripleStrLit}:
|
if lib.path.kind in {nkStrLit..nkTripleStrLit}:
|
||||||
var s: TStringSeq = @[]
|
var s: TStringSeq = @[]
|
||||||
libCandidates(lib.path.strVal, s)
|
libCandidates(lib.path.strVal, s)
|
||||||
|
if gVerbosity >= 2:
|
||||||
|
MsgWriteln("Dependency: " & lib.path.strVal)
|
||||||
var loadlib: PRope = nil
|
var loadlib: PRope = nil
|
||||||
for i in countup(0, high(s)):
|
for i in countup(0, high(s)):
|
||||||
inc(m.labels)
|
inc(m.labels)
|
||||||
|
|
@ -693,10 +696,11 @@ proc retIsNotVoid(s: PSym): bool =
|
||||||
|
|
||||||
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
||||||
discard cgsym(p.module, "pushFrame")
|
discard cgsym(p.module, "pushFrame")
|
||||||
if p.frameLen > 0:
|
if p.maxFrameLen > 0:
|
||||||
discard cgsym(p.module, "TVarSlot")
|
discard cgsym(p.module, "TVarSlot")
|
||||||
result = rfmt(nil, "\tnimfrs($1, $2, $3)$N",
|
result = rfmt(nil, "\tnimfrs($1, $2, $3, $4)$N",
|
||||||
procname, filename, p.frameLen.toRope)
|
procname, filename, p.maxFrameLen.toRope,
|
||||||
|
p.blocks[0].frameLen.toRope)
|
||||||
else:
|
else:
|
||||||
result = rfmt(nil, "\tnimfr($1, $2)$N", procname, filename)
|
result = rfmt(nil, "\tnimfr($1, $2)$N", procname, filename)
|
||||||
|
|
||||||
|
|
@ -890,6 +894,12 @@ proc getFileHeader(cfilenoext: string): PRope =
|
||||||
result = getCopyright(cfilenoext)
|
result = getCopyright(cfilenoext)
|
||||||
addIntTypes(result)
|
addIntTypes(result)
|
||||||
|
|
||||||
|
proc genFilenames(m: BModule): PRope =
|
||||||
|
discard cgsym(m, "dbgRegisterFilename")
|
||||||
|
result = nil
|
||||||
|
for i in 0.. <fileInfos.len:
|
||||||
|
result.appf("dbgRegisterFilename($1);$n", fileInfos[i].projPath.makeCString)
|
||||||
|
|
||||||
proc genMainProc(m: BModule) =
|
proc genMainProc(m: BModule) =
|
||||||
const
|
const
|
||||||
CommonMainBody =
|
CommonMainBody =
|
||||||
|
|
@ -948,6 +958,8 @@ proc genMainProc(m: BModule) =
|
||||||
nimMain = PosixNimMain
|
nimMain = PosixNimMain
|
||||||
otherMain = PosixCMain
|
otherMain = PosixCMain
|
||||||
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
|
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
|
||||||
|
if optEndb in gOptions:
|
||||||
|
gBreakpoints.app(m.genFilenames)
|
||||||
|
|
||||||
let initStackBottomCall = if emulatedThreadVars() or
|
let initStackBottomCall = if emulatedThreadVars() or
|
||||||
platform.targetOS == osStandalone: "".toRope
|
platform.targetOS == osStandalone: "".toRope
|
||||||
|
|
@ -1244,7 +1256,7 @@ proc updateCachedModule(m: BModule) =
|
||||||
let cfile = getCFile(m)
|
let cfile = getCFile(m)
|
||||||
let cfilenoext = changeFileExt(cfile, "")
|
let cfilenoext = changeFileExt(cfile, "")
|
||||||
|
|
||||||
if mergeRequired(m):
|
if mergeRequired(m) and sfMainModule notin m.module.flags:
|
||||||
mergeFiles(cfile, m)
|
mergeFiles(cfile, m)
|
||||||
genInitCode(m)
|
genInitCode(m)
|
||||||
finishTypeDescriptions(m)
|
finishTypeDescriptions(m)
|
||||||
|
|
@ -1254,8 +1266,7 @@ proc updateCachedModule(m: BModule) =
|
||||||
|
|
||||||
addFileToLink(cfilenoext)
|
addFileToLink(cfilenoext)
|
||||||
|
|
||||||
proc cgenCaasUpdate* =
|
proc updateCachedModules* =
|
||||||
# XXX(zah): clean-up the fromCache mess
|
|
||||||
for m in cgenModules():
|
for m in cgenModules():
|
||||||
if m.fromCache: m.updateCachedModule
|
if m.fromCache: m.updateCachedModule
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,10 @@ type
|
||||||
id*: int # the ID of the label; positive means that it
|
id*: int # the ID of the label; positive means that it
|
||||||
label*: PRope # generated text for the label
|
label*: PRope # generated text for the label
|
||||||
# nil if label is not used
|
# nil if label is not used
|
||||||
nestedTryStmts*: int # how many try statements is it nested into
|
|
||||||
sections*: TCProcSections # the code beloging
|
sections*: TCProcSections # the code beloging
|
||||||
isLoop*: bool # whether block is a loop
|
isLoop*: bool # whether block is a loop
|
||||||
|
nestedTryStmts*: int16 # how many try statements is it nested into
|
||||||
|
frameLen*: int16
|
||||||
|
|
||||||
TCProc{.final.} = object # represents C proc that is currently generated
|
TCProc{.final.} = object # represents C proc that is currently generated
|
||||||
prc*: PSym # the Nimrod proc that this C proc belongs to
|
prc*: PSym # the Nimrod proc that this C proc belongs to
|
||||||
|
|
@ -74,9 +75,7 @@ type
|
||||||
options*: TOptions # options that should be used for code
|
options*: TOptions # options that should be used for code
|
||||||
# generation; this is the same as prc.options
|
# generation; this is the same as prc.options
|
||||||
# unless prc == nil
|
# unless prc == nil
|
||||||
frameLen*: int # current length of frame descriptor
|
maxFrameLen*: int # max length of frame descriptor
|
||||||
sendClosure*: PType # closure record type that we pass
|
|
||||||
receiveClosure*: PType # closure record type that we get
|
|
||||||
module*: BModule # used to prevent excessive parameter passing
|
module*: BModule # used to prevent excessive parameter passing
|
||||||
withinLoop*: int # > 0 if we are within a loop
|
withinLoop*: int # > 0 if we are within a loop
|
||||||
gcFrameId*: natural # for the GC stack marking
|
gcFrameId*: natural # for the GC stack marking
|
||||||
|
|
|
||||||
4
compiler/cgmeth.nim
Executable file → Normal file
4
compiler/cgmeth.nim
Executable file → Normal file
|
|
@ -108,8 +108,8 @@ proc methodDef*(s: PSym, fromCache: bool) =
|
||||||
|
|
||||||
proc relevantCol(methods: TSymSeq, col: int): bool =
|
proc relevantCol(methods: TSymSeq, col: int): bool =
|
||||||
# returns true iff the position is relevant
|
# returns true iff the position is relevant
|
||||||
var t = methods[0].typ.sons[col]
|
var t = methods[0].typ.sons[col].skipTypes(skipPtrs)
|
||||||
if skipTypes(t, skipPtrs).kind == tyObject:
|
if t.kind == tyObject:
|
||||||
for i in countup(1, high(methods)):
|
for i in countup(1, high(methods)):
|
||||||
let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs)
|
let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs)
|
||||||
if not SameType(t2, t):
|
if not SameType(t2, t):
|
||||||
|
|
|
||||||
0
compiler/charsets.nim
Executable file → Normal file
0
compiler/charsets.nim
Executable file → Normal file
37
compiler/commands.nim
Executable file → Normal file
37
compiler/commands.nim
Executable file → Normal file
|
|
@ -65,8 +65,13 @@ proc writeCommandLineUsage() =
|
||||||
MsgWriteln(getCommandLineDesc())
|
MsgWriteln(getCommandLineDesc())
|
||||||
helpWritten = true
|
helpWritten = true
|
||||||
|
|
||||||
|
proc addPrefix(switch: string): string =
|
||||||
|
if len(switch) == 1: result = "-" & switch
|
||||||
|
else: result = "--" & switch
|
||||||
|
|
||||||
proc InvalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) =
|
proc InvalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) =
|
||||||
LocalError(info, errInvalidCmdLineOption, switch)
|
if switch == " ": LocalError(info, errInvalidCmdLineOption, "-")
|
||||||
|
else: LocalError(info, errInvalidCmdLineOption, addPrefix(switch))
|
||||||
|
|
||||||
proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass,
|
proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass,
|
||||||
info: TLineInfo) =
|
info: TLineInfo) =
|
||||||
|
|
@ -98,10 +103,10 @@ proc ProcessOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdlinePass,
|
||||||
else: LocalError(info, errOnOrOffExpectedButXFound, arg)
|
else: LocalError(info, errOnOrOffExpectedButXFound, arg)
|
||||||
|
|
||||||
proc ExpectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
proc ExpectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||||
if arg == "": LocalError(info, errCmdLineArgExpected, switch)
|
if arg == "": LocalError(info, errCmdLineArgExpected, addPrefix(switch))
|
||||||
|
|
||||||
proc ExpectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
proc ExpectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||||
if arg != "": LocalError(info, errCmdLineNoArgExpected, switch)
|
if arg != "": LocalError(info, errCmdLineNoArgExpected, addPrefix(switch))
|
||||||
|
|
||||||
proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
|
proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
|
||||||
info: TLineInfo) =
|
info: TLineInfo) =
|
||||||
|
|
@ -143,6 +148,7 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
|
||||||
of "refc": result = gSelectedGC == gcRefc
|
of "refc": result = gSelectedGC == gcRefc
|
||||||
of "v2": result = gSelectedGC == gcV2
|
of "v2": result = gSelectedGC == gcV2
|
||||||
of "markandsweep": result = gSelectedGC == gcMarkAndSweep
|
of "markandsweep": result = gSelectedGC == gcMarkAndSweep
|
||||||
|
of "generational": result = gSelectedGC == gcGenerational
|
||||||
of "none": result = gSelectedGC == gcNone
|
of "none": result = gSelectedGC == gcNone
|
||||||
else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
|
else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
|
||||||
of "opt":
|
of "opt":
|
||||||
|
|
@ -190,8 +196,13 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
|
||||||
of "patterns": result = contains(gOptions, optPatterns)
|
of "patterns": result = contains(gOptions, optPatterns)
|
||||||
else: InvalidCmdLineOption(passCmd1, switch, info)
|
else: InvalidCmdLineOption(passCmd1, switch, info)
|
||||||
|
|
||||||
proc processPath(path: string): string =
|
proc processPath(path: string, notRelativeToProj = false): string =
|
||||||
result = UnixToNativePath(path % ["nimrod", getPrefixDir(), "lib", libpath,
|
let p = if notRelativeToProj or os.isAbsolute(path) or
|
||||||
|
'$' in path or path[0] == '.':
|
||||||
|
path
|
||||||
|
else:
|
||||||
|
options.gProjectPath / path
|
||||||
|
result = UnixToNativePath(p % ["nimrod", getPrefixDir(), "lib", libpath,
|
||||||
"home", removeTrailingDirSep(os.getHomeDir()),
|
"home", removeTrailingDirSep(os.getHomeDir()),
|
||||||
"projectname", options.gProjectName,
|
"projectname", options.gProjectName,
|
||||||
"projectpath", options.gProjectPath])
|
"projectpath", options.gProjectPath])
|
||||||
|
|
@ -206,6 +217,11 @@ proc track(arg: string, info: TLineInfo) =
|
||||||
LocalError(info, errInvalidNumber, a[2])
|
LocalError(info, errInvalidNumber, a[2])
|
||||||
msgs.addCheckpoint(newLineInfo(a[0], line, column))
|
msgs.addCheckpoint(newLineInfo(a[0], line, column))
|
||||||
|
|
||||||
|
proc dynlibOverride(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||||
|
if pass in {passCmd2, passPP}:
|
||||||
|
expectArg(switch, arg, pass, info)
|
||||||
|
options.inclDynlibOverride(arg)
|
||||||
|
|
||||||
proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||||
var
|
var
|
||||||
theOS: TSystemOS
|
theOS: TSystemOS
|
||||||
|
|
@ -218,7 +234,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||||
of "babelpath":
|
of "babelpath":
|
||||||
if pass in {passCmd2, passPP}:
|
if pass in {passCmd2, passPP}:
|
||||||
expectArg(switch, arg, pass, info)
|
expectArg(switch, arg, pass, info)
|
||||||
let path = processPath(arg)
|
let path = processPath(arg, notRelativeToProj=true)
|
||||||
babelpath(path, info)
|
babelpath(path, info)
|
||||||
of "excludepath":
|
of "excludepath":
|
||||||
expectArg(switch, arg, pass, info)
|
expectArg(switch, arg, pass, info)
|
||||||
|
|
@ -280,6 +296,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||||
of "markandsweep":
|
of "markandsweep":
|
||||||
gSelectedGC = gcMarkAndSweep
|
gSelectedGC = gcMarkAndSweep
|
||||||
defineSymbol("gcmarkandsweep")
|
defineSymbol("gcmarkandsweep")
|
||||||
|
of "generational":
|
||||||
|
gSelectedGC = gcGenerational
|
||||||
|
defineSymbol("gcgenerational")
|
||||||
of "none":
|
of "none":
|
||||||
gSelectedGC = gcNone
|
gSelectedGC = gcNone
|
||||||
defineSymbol("nogc")
|
defineSymbol("nogc")
|
||||||
|
|
@ -437,9 +456,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||||
of "genscript":
|
of "genscript":
|
||||||
expectNoArg(switch, arg, pass, info)
|
expectNoArg(switch, arg, pass, info)
|
||||||
incl(gGlobalOptions, optGenScript)
|
incl(gGlobalOptions, optGenScript)
|
||||||
of "lib":
|
of "lib":
|
||||||
expectArg(switch, arg, pass, info)
|
expectArg(switch, arg, pass, info)
|
||||||
libpath = processPath(arg)
|
libpath = processPath(arg, notRelativeToProj=true)
|
||||||
of "putenv":
|
of "putenv":
|
||||||
expectArg(switch, arg, pass, info)
|
expectArg(switch, arg, pass, info)
|
||||||
splitSwitch(arg, key, val, pass, info)
|
splitSwitch(arg, key, val, pass, info)
|
||||||
|
|
@ -471,6 +490,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||||
of "listfullpaths":
|
of "listfullpaths":
|
||||||
expectNoArg(switch, arg, pass, info)
|
expectNoArg(switch, arg, pass, info)
|
||||||
gListFullPaths = true
|
gListFullPaths = true
|
||||||
|
of "dynliboverride":
|
||||||
|
dynlibOverride(switch, arg, pass, info)
|
||||||
else:
|
else:
|
||||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
|
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
|
||||||
else: InvalidCmdLineOption(pass, switch, info)
|
else: InvalidCmdLineOption(pass, switch, info)
|
||||||
|
|
|
||||||
10
compiler/condsyms.nim
Executable file → Normal file
10
compiler/condsyms.nim
Executable file → Normal file
|
|
@ -10,7 +10,7 @@
|
||||||
# This module handles the conditional symbols.
|
# This module handles the conditional symbols.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, msgs, hashes, platform, strutils, idents
|
ast, astalgo, hashes, platform, strutils, idents
|
||||||
|
|
||||||
var gSymbols*: TStrTable
|
var gSymbols*: TStrTable
|
||||||
|
|
||||||
|
|
@ -35,14 +35,12 @@ proc isDefined*(symbol: PIdent): bool =
|
||||||
proc isDefined*(symbol: string): bool =
|
proc isDefined*(symbol: string): bool =
|
||||||
result = isDefined(getIdent(symbol))
|
result = isDefined(getIdent(symbol))
|
||||||
|
|
||||||
proc ListSymbols*() =
|
iterator definedSymbolNames*: string =
|
||||||
var it: TTabIter
|
var it: TTabIter
|
||||||
var s = InitTabIter(it, gSymbols)
|
var s = InitTabIter(it, gSymbols)
|
||||||
OutWriteln("-- List of currently defined symbols --")
|
while s != nil:
|
||||||
while s != nil:
|
if s.position == 1: yield s.name.s
|
||||||
if s.position == 1: OutWriteln(s.name.s)
|
|
||||||
s = nextIter(it, gSymbols)
|
s = nextIter(it, gSymbols)
|
||||||
OutWriteln("-- End of list --")
|
|
||||||
|
|
||||||
proc countDefinedSymbols*(): int =
|
proc countDefinedSymbols*(): int =
|
||||||
var it: TTabIter
|
var it: TTabIter
|
||||||
|
|
|
||||||
0
compiler/crc.nim
Executable file → Normal file
0
compiler/crc.nim
Executable file → Normal file
0
compiler/depends.nim
Executable file → Normal file
0
compiler/depends.nim
Executable file → Normal file
0
compiler/docgen.nim
Executable file → Normal file
0
compiler/docgen.nim
Executable file → Normal file
|
|
@ -142,10 +142,10 @@ proc getField(n: PNode; position: int): PSym =
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc packObject(x: PNode, typ: PType, res: pointer) =
|
proc packObject(x: PNode, typ: PType, res: pointer) =
|
||||||
InternalAssert x.kind == nkPar
|
InternalAssert x.kind in {nkObjConstr, nkPar}
|
||||||
# compute the field's offsets:
|
# compute the field's offsets:
|
||||||
discard typ.getSize
|
discard typ.getSize
|
||||||
for i in countup(0, sonsLen(x) - 1):
|
for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
|
||||||
var it = x.sons[i]
|
var it = x.sons[i]
|
||||||
if it.kind == nkExprColonExpr:
|
if it.kind == nkExprColonExpr:
|
||||||
internalAssert it.sons[0].kind == nkSym
|
internalAssert it.sons[0].kind == nkSym
|
||||||
|
|
@ -257,11 +257,11 @@ proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
|
||||||
unpackObjectAdd(x, typ.n, result)
|
unpackObjectAdd(x, typ.n, result)
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
if result.kind != nkPar:
|
if result.kind notin {nkObjConstr, nkPar}:
|
||||||
GlobalError(n.info, "cannot map value from FFI")
|
GlobalError(n.info, "cannot map value from FFI")
|
||||||
if typ.n.isNil:
|
if typ.n.isNil:
|
||||||
GlobalError(n.info, "cannot unpack unnamed tuple")
|
GlobalError(n.info, "cannot unpack unnamed tuple")
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(ord(n.kind == nkObjConstr), sonsLen(n) - 1):
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
if it.kind == nkExprColonExpr:
|
if it.kind == nkExprColonExpr:
|
||||||
internalAssert it.sons[0].kind == nkSym
|
internalAssert it.sons[0].kind == nkSym
|
||||||
|
|
|
||||||
133
compiler/evals.nim
Executable file → Normal file
133
compiler/evals.nim
Executable file → Normal file
|
|
@ -249,7 +249,7 @@ proc getNullValueAux(obj: PNode, result: PNode) =
|
||||||
else: InternalError(result.info, "getNullValueAux")
|
else: InternalError(result.info, "getNullValueAux")
|
||||||
|
|
||||||
proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
var t = skipTypes(typ, abstractRange)
|
var t = skipTypes(typ, abstractRange-{tyTypeDesc})
|
||||||
result = emptyNode
|
result = emptyNode
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyBool, tyEnum, tyChar, tyInt..tyInt64:
|
of tyBool, tyEnum, tyChar, tyInt..tyInt64:
|
||||||
|
|
@ -273,9 +273,10 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
result = newNodeIT(nkBracket, info, t)
|
result = newNodeIT(nkBracket, info, t)
|
||||||
for i in countup(0, int(lengthOrd(t)) - 1):
|
for i in countup(0, int(lengthOrd(t)) - 1):
|
||||||
addSon(result, getNullValue(elemType(t), info))
|
addSon(result, getNullValue(elemType(t), info))
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
|
# XXX nkExprColonExpr is out of fashion ...
|
||||||
result = newNodeIT(nkPar, info, t)
|
result = newNodeIT(nkPar, info, t)
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
var p = newNodeIT(nkExprColonExpr, info, t.sons[i])
|
var p = newNodeIT(nkExprColonExpr, info, t.sons[i])
|
||||||
var field = if t.n != nil: t.n.sons[i].sym else: newSym(
|
var field = if t.n != nil: t.n.sons[i].sym else: newSym(
|
||||||
skField, getIdent(":tmp" & $i), t.owner, info)
|
skField, getIdent(":tmp" & $i), t.owner, info)
|
||||||
|
|
@ -293,10 +294,12 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
|
||||||
if a.kind != nkIdentDefs: return raiseCannotEval(c, n.info)
|
if a.kind != nkIdentDefs: return raiseCannotEval(c, n.info)
|
||||||
# XXX var (x, y) = z support?
|
# XXX var (x, y) = z support?
|
||||||
#assert(a.sons[0].kind == nkSym) can happen for transformed vars
|
#assert(a.sons[0].kind == nkSym) can happen for transformed vars
|
||||||
if a.sons[2].kind != nkEmpty:
|
if a.sons[2].kind != nkEmpty:
|
||||||
result = evalAux(c, a.sons[2], {})
|
result = evalAux(c, a.sons[2], {})
|
||||||
if isSpecial(result): return
|
if result.kind in {nkType..nkNilLit}:
|
||||||
else:
|
result = result.copyNode
|
||||||
|
if isSpecial(result): return
|
||||||
|
else:
|
||||||
result = getNullValue(a.sons[0].typ, a.sons[0].info)
|
result = getNullValue(a.sons[0].typ, a.sons[0].info)
|
||||||
if a.sons[0].kind == nkSym:
|
if a.sons[0].kind == nkSym:
|
||||||
var v = a.sons[0].sym
|
var v = a.sons[0].sym
|
||||||
|
|
@ -444,29 +447,35 @@ proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||||
stackTrace(c, n, errIndexOutOfBounds)
|
stackTrace(c, n, errIndexOutOfBounds)
|
||||||
else: stackTrace(c, n, errNilAccess)
|
else: stackTrace(c, n, errNilAccess)
|
||||||
|
|
||||||
proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||||
# a real field access; proc calls have already been transformed
|
# a real field access; proc calls have already been transformed
|
||||||
# XXX: field checks!
|
# XXX: field checks!
|
||||||
result = evalAux(c, n.sons[0], flags)
|
result = evalAux(c, n.sons[0], flags)
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
var x = result
|
var x = result
|
||||||
if x.kind != nkPar: return raiseCannotEval(c, n.info)
|
if x.kind != nkPar: return raiseCannotEval(c, n.info)
|
||||||
|
# this is performance critical:
|
||||||
var field = n.sons[1].sym
|
var field = n.sons[1].sym
|
||||||
for i in countup(0, sonsLen(x) - 1):
|
result = x.sons[field.position]
|
||||||
var it = x.sons[i]
|
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||||
if it.kind != nkExprColonExpr:
|
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||||
# lookup per index:
|
when false:
|
||||||
result = x.sons[field.position]
|
var field = n.sons[1].sym
|
||||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
for i in countup(0, sonsLen(x) - 1):
|
||||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
var it = x.sons[i]
|
||||||
return
|
if it.kind != nkExprColonExpr:
|
||||||
#InternalError(it.info, "evalFieldAccess")
|
# lookup per index:
|
||||||
if it.sons[0].sym.name.id == field.name.id:
|
result = x.sons[field.position]
|
||||||
result = x.sons[i].sons[1]
|
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||||
return
|
return
|
||||||
stackTrace(c, n, errFieldXNotFound, field.name.s)
|
#InternalError(it.info, "evalFieldAccess")
|
||||||
result = emptyNode
|
if it.sons[0].sym.name.id == field.name.id:
|
||||||
|
result = x.sons[i].sons[1]
|
||||||
|
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||||
|
return
|
||||||
|
stackTrace(c, n, errFieldXNotFound, field.name.s)
|
||||||
|
result = emptyNode
|
||||||
|
|
||||||
proc evalAsgn(c: PEvalContext, n: PNode): PNode =
|
proc evalAsgn(c: PEvalContext, n: PNode): PNode =
|
||||||
var a = n.sons[0]
|
var a = n.sons[0]
|
||||||
|
|
@ -896,13 +905,13 @@ proc evalParseExpr(c: PEvalContext, n: PNode): PNode =
|
||||||
if sonsLen(ast) != 1:
|
if sonsLen(ast) != 1:
|
||||||
GlobalError(code.info, errExprExpected, "multiple statements")
|
GlobalError(code.info, errExprExpected, "multiple statements")
|
||||||
result = ast.sons[0]
|
result = ast.sons[0]
|
||||||
result.typ = newType(tyExpr, c.module)
|
#result.typ = newType(tyExpr, c.module)
|
||||||
|
|
||||||
proc evalParseStmt(c: PEvalContext, n: PNode): PNode =
|
proc evalParseStmt(c: PEvalContext, n: PNode): PNode =
|
||||||
var code = evalAux(c, n.sons[1], {})
|
var code = evalAux(c, n.sons[1], {})
|
||||||
result = parseString(code.getStrValue, code.info.toFilename,
|
result = parseString(code.getStrValue, code.info.toFilename,
|
||||||
code.stringStartingLine)
|
code.stringStartingLine)
|
||||||
result.typ = newType(tyStmt, c.module)
|
#result.typ = newType(tyStmt, c.module)
|
||||||
|
|
||||||
proc evalTypeTrait*(n: PNode, context: PSym): PNode =
|
proc evalTypeTrait*(n: PNode, context: PSym): PNode =
|
||||||
## XXX: This should be pretty much guaranteed to be true
|
## XXX: This should be pretty much guaranteed to be true
|
||||||
|
|
@ -993,10 +1002,10 @@ proc evalExpandToAst(c: PEvalContext, original: PNode): PNode =
|
||||||
|
|
||||||
case expandedSym.kind
|
case expandedSym.kind
|
||||||
of skTemplate:
|
of skTemplate:
|
||||||
let genSymOwner = if c.tos != nil and c.tos.prc != nil:
|
let genSymOwner = if c.tos != nil and c.tos.prc != nil:
|
||||||
c.tos.prc
|
c.tos.prc
|
||||||
else:
|
else:
|
||||||
c.module
|
c.module
|
||||||
result = evalTemplate(macroCall, expandedSym, genSymOwner)
|
result = evalTemplate(macroCall, expandedSym, genSymOwner)
|
||||||
of skMacro:
|
of skMacro:
|
||||||
# At this point macroCall.sons[0] is nkSym node.
|
# At this point macroCall.sons[0] is nkSym node.
|
||||||
|
|
@ -1090,7 +1099,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||||
result = evalAux(c, n.sons[2], {efLValue})
|
result = evalAux(c, n.sons[2], {efLValue})
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
addSon(a, result)
|
addSon(a, result)
|
||||||
result = emptyNode
|
result = a
|
||||||
of mNAddMultiple:
|
of mNAddMultiple:
|
||||||
result = evalAux(c, n.sons[1], {efLValue})
|
result = evalAux(c, n.sons[1], {efLValue})
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
|
|
@ -1098,7 +1107,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||||
result = evalAux(c, n.sons[2], {efLValue})
|
result = evalAux(c, n.sons[2], {efLValue})
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
for i in countup(0, sonsLen(result) - 1): addSon(a, result.sons[i])
|
for i in countup(0, sonsLen(result) - 1): addSon(a, result.sons[i])
|
||||||
result = emptyNode
|
result = a
|
||||||
of mNDel:
|
of mNDel:
|
||||||
result = evalAux(c, n.sons[1], {efLValue})
|
result = evalAux(c, n.sons[1], {efLValue})
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
|
|
@ -1336,19 +1345,27 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||||
cc = result
|
cc = result
|
||||||
if isEmpty(a) or isEmpty(b) or isEmpty(cc): result = emptyNode
|
if isEmpty(a) or isEmpty(b) or isEmpty(cc): result = emptyNode
|
||||||
else: result = evalOp(m, n, a, b, cc)
|
else: result = evalOp(m, n, a, b, cc)
|
||||||
|
|
||||||
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||||
result = emptyNode
|
result = emptyNode
|
||||||
dec(gNestedEvals)
|
dec(gNestedEvals)
|
||||||
if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations)
|
if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations)
|
||||||
case n.kind # atoms:
|
case n.kind
|
||||||
of nkEmpty: result = n
|
|
||||||
of nkSym: result = evalSym(c, n, flags)
|
of nkSym: result = evalSym(c, n, flags)
|
||||||
of nkType..nkNilLit: result = copyNode(n) # end of atoms
|
of nkType..nkNilLit:
|
||||||
of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit, nkInfix,
|
# nkStrLit is VERY common in the traces, so we should avoid
|
||||||
nkPrefix, nkPostfix:
|
# the 'copyNode' here.
|
||||||
|
result = n #.copyNode
|
||||||
|
of nkAsgn, nkFastAsgn: result = evalAsgn(c, n)
|
||||||
|
of nkCommand..nkHiddenCallConv:
|
||||||
result = evalMagicOrCall(c, n)
|
result = evalMagicOrCall(c, n)
|
||||||
of nkCurly, nkBracket, nkRange:
|
of nkDotExpr: result = evalFieldAccess(c, n, flags)
|
||||||
|
of nkBracketExpr:
|
||||||
|
result = evalArrayAccess(c, n, flags)
|
||||||
|
of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n, flags)
|
||||||
|
of nkAddr, nkHiddenAddr: result = evalAddr(c, n, flags)
|
||||||
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n)
|
||||||
|
of nkCurly, nkBracket, nkRange:
|
||||||
# flags need to be passed here for mNAddMultiple :-(
|
# flags need to be passed here for mNAddMultiple :-(
|
||||||
# XXX this is not correct in every case!
|
# XXX this is not correct in every case!
|
||||||
var a = copyNode(n)
|
var a = copyNode(n)
|
||||||
|
|
@ -1370,12 +1387,23 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
a.sons[i] = result
|
a.sons[i] = result
|
||||||
result = a
|
result = a
|
||||||
of nkBracketExpr: result = evalArrayAccess(c, n, flags)
|
of nkObjConstr:
|
||||||
of nkDotExpr: result = evalFieldAccess(c, n, flags)
|
let t = skipTypes(n.typ, abstractInst)
|
||||||
of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n, flags)
|
var a: PNode
|
||||||
of nkAddr, nkHiddenAddr: result = evalAddr(c, n, flags)
|
if t.kind == tyRef:
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n)
|
result = newNodeIT(nkRefTy, n.info, t)
|
||||||
of nkAsgn, nkFastAsgn: result = evalAsgn(c, n)
|
a = getNullValue(t.sons[0], n.info)
|
||||||
|
addSon(result, a)
|
||||||
|
else:
|
||||||
|
a = getNullValue(t, n.info)
|
||||||
|
result = a
|
||||||
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
let it = n.sons[i]
|
||||||
|
if it.kind == nkExprColonExpr:
|
||||||
|
let value = evalAux(c, it.sons[1], flags)
|
||||||
|
if isSpecial(value): return value
|
||||||
|
a.sons[it.sons[0].sym.position] = value
|
||||||
|
else: return raiseCannotEval(c, n.info)
|
||||||
of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
|
of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
|
||||||
of nkWhileStmt: result = evalWhile(c, n)
|
of nkWhileStmt: result = evalWhile(c, n)
|
||||||
of nkCaseStmt: result = evalCase(c, n)
|
of nkCaseStmt: result = evalCase(c, n)
|
||||||
|
|
@ -1414,6 +1442,9 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||||
result = raiseCannotEval(c, n.info)
|
result = raiseCannotEval(c, n.info)
|
||||||
of nkRefTy:
|
of nkRefTy:
|
||||||
result = evalAux(c, n.sons[0], flags)
|
result = evalAux(c, n.sons[0], flags)
|
||||||
|
of nkEmpty:
|
||||||
|
# nkEmpty occurs once in each trace that I looked at
|
||||||
|
result = n
|
||||||
else: InternalError(n.info, "evalAux: " & $n.kind)
|
else: InternalError(n.info, "evalAux: " & $n.kind)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
InternalError(n.info, "evalAux: returned nil " & $n.kind)
|
InternalError(n.info, "evalAux: returned nil " & $n.kind)
|
||||||
|
|
@ -1464,11 +1495,13 @@ proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
|
||||||
c.callsite = nOrig
|
c.callsite = nOrig
|
||||||
var s = newStackFrame()
|
var s = newStackFrame()
|
||||||
s.call = n
|
s.call = n
|
||||||
setlen(s.params, n.len)
|
var L = n.safeLen
|
||||||
|
if L == 0: L = 1
|
||||||
|
setlen(s.params, L)
|
||||||
# return value:
|
# return value:
|
||||||
s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
|
s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
|
||||||
# setup parameters:
|
# setup parameters:
|
||||||
for i in 1 .. < n.len: s.params[i] = setupMacroParam(n.sons[i])
|
for i in 1 .. < L: s.params[i] = setupMacroParam(n.sons[i])
|
||||||
pushStackFrame(c, s)
|
pushStackFrame(c, s)
|
||||||
discard eval(c, sym.getBody)
|
discard eval(c, sym.getBody)
|
||||||
result = s.params[0]
|
result = s.params[0]
|
||||||
|
|
@ -1483,7 +1516,13 @@ proc myOpen(module: PSym): PPassContext =
|
||||||
pushStackFrame(c, newStackFrame())
|
pushStackFrame(c, newStackFrame())
|
||||||
result = c
|
result = c
|
||||||
|
|
||||||
proc myProcess(c: PPassContext, n: PNode): PNode =
|
var oldErrorCount: int
|
||||||
|
|
||||||
|
proc myProcess(c: PPassContext, n: PNode): PNode =
|
||||||
|
# don't eval errornous code:
|
||||||
|
if oldErrorCount != msgs.gErrorCounter:
|
||||||
|
oldErrorCount = msgs.gErrorCounter
|
||||||
|
return n
|
||||||
result = eval(PEvalContext(c), n)
|
result = eval(PEvalContext(c), n)
|
||||||
|
|
||||||
const evalPass* = makePass(myOpen, nil, myProcess, myProcess)
|
const evalPass* = makePass(myOpen, nil, myProcess, myProcess)
|
||||||
|
|
|
||||||
66
compiler/extccomp.nim
Executable file → Normal file
66
compiler/extccomp.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -391,35 +391,8 @@ proc resetCompilationLists* =
|
||||||
initLinkedList(externalToCompile)
|
initLinkedList(externalToCompile)
|
||||||
initLinkedList(toLink)
|
initLinkedList(toLink)
|
||||||
|
|
||||||
proc footprint(filename: string): TCrc32 =
|
|
||||||
result = crcFromFile(filename) ><
|
|
||||||
platform.OS[targetOS].name ><
|
|
||||||
platform.CPU[targetCPU].name ><
|
|
||||||
extccomp.CC[extccomp.ccompiler].name
|
|
||||||
|
|
||||||
proc externalFileChanged(filename: string): bool =
|
|
||||||
var crcFile = toGeneratedFile(filename, "crc")
|
|
||||||
var currentCrc = int(footprint(filename))
|
|
||||||
var f: TFile
|
|
||||||
if open(f, crcFile, fmRead):
|
|
||||||
var line = newStringOfCap(40)
|
|
||||||
if not f.readLine(line): line = "0"
|
|
||||||
close(f)
|
|
||||||
var oldCrc = parseInt(line)
|
|
||||||
result = oldCrc != currentCrc
|
|
||||||
else:
|
|
||||||
result = true
|
|
||||||
if result:
|
|
||||||
if open(f, crcFile, fmWrite):
|
|
||||||
f.writeln($currentCrc)
|
|
||||||
close(f)
|
|
||||||
|
|
||||||
proc addExternalFileToCompile*(filename: string) =
|
|
||||||
if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
|
|
||||||
appendStr(externalToCompile, filename)
|
|
||||||
|
|
||||||
proc addFileToLink*(filename: string) =
|
proc addFileToLink*(filename: string) =
|
||||||
prependStr(toLink, filename)
|
prependStr(toLink, filename)
|
||||||
# BUGFIX: was ``appendStr``
|
# BUGFIX: was ``appendStr``
|
||||||
|
|
||||||
proc execExternalProgram*(cmd: string) =
|
proc execExternalProgram*(cmd: string) =
|
||||||
|
|
@ -536,6 +509,34 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
|
||||||
"nimrod", quoteIfContainsWhite(getPrefixDir()),
|
"nimrod", quoteIfContainsWhite(getPrefixDir()),
|
||||||
"lib", quoteIfContainsWhite(libpath)])
|
"lib", quoteIfContainsWhite(libpath)])
|
||||||
|
|
||||||
|
proc footprint(filename: string): TCrc32 =
|
||||||
|
result = crcFromFile(filename) ><
|
||||||
|
platform.OS[targetOS].name ><
|
||||||
|
platform.CPU[targetCPU].name ><
|
||||||
|
extccomp.CC[extccomp.ccompiler].name ><
|
||||||
|
getCompileCFileCmd(filename, true)
|
||||||
|
|
||||||
|
proc externalFileChanged(filename: string): bool =
|
||||||
|
var crcFile = toGeneratedFile(filename, "crc")
|
||||||
|
var currentCrc = int(footprint(filename))
|
||||||
|
var f: TFile
|
||||||
|
if open(f, crcFile, fmRead):
|
||||||
|
var line = newStringOfCap(40)
|
||||||
|
if not f.readLine(line): line = "0"
|
||||||
|
close(f)
|
||||||
|
var oldCrc = parseInt(line)
|
||||||
|
result = oldCrc != currentCrc
|
||||||
|
else:
|
||||||
|
result = true
|
||||||
|
if result:
|
||||||
|
if open(f, crcFile, fmWrite):
|
||||||
|
f.writeln($currentCrc)
|
||||||
|
close(f)
|
||||||
|
|
||||||
|
proc addExternalFileToCompile*(filename: string) =
|
||||||
|
if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
|
||||||
|
appendStr(externalToCompile, filename)
|
||||||
|
|
||||||
proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
|
proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
|
||||||
isExternal: bool) =
|
isExternal: bool) =
|
||||||
var it = PStrEntry(list.head)
|
var it = PStrEntry(list.head)
|
||||||
|
|
@ -572,7 +573,12 @@ proc CallCCompiler*(projectfile: string) =
|
||||||
else:
|
else:
|
||||||
res = execProcesses(cmds, {poUseShell, poParentStreams},
|
res = execProcesses(cmds, {poUseShell, poParentStreams},
|
||||||
gNumberOfProcessors)
|
gNumberOfProcessors)
|
||||||
if res != 0: rawMessage(errExecutionOfProgramFailed, [])
|
if res != 0:
|
||||||
|
if gNumberOfProcessors <= 1:
|
||||||
|
rawMessage(errExecutionOfProgramFailed, [])
|
||||||
|
else:
|
||||||
|
rawMessage(errGenerated, " execution of an external program failed; " &
|
||||||
|
"rerun with --parallelBuild:1 to see the error message")
|
||||||
if optNoLinking notin gGlobalOptions:
|
if optNoLinking notin gGlobalOptions:
|
||||||
# call the linker:
|
# call the linker:
|
||||||
var it = PStrEntry(toLink.head)
|
var it = PStrEntry(toLink.head)
|
||||||
|
|
|
||||||
8
compiler/filter_tmpl.nim
Executable file → Normal file
8
compiler/filter_tmpl.nim
Executable file → Normal file
|
|
@ -98,7 +98,13 @@ proc parseLine(p: var TTmplParser) =
|
||||||
of wElif, wOf, wElse, wExcept, wFinally:
|
of wElif, wOf, wElse, wExcept, wFinally:
|
||||||
LLStreamWrite(p.outp, repeatChar(p.indent - 2))
|
LLStreamWrite(p.outp, repeatChar(p.indent - 2))
|
||||||
LLStreamWrite(p.outp, substr(p.x, d))
|
LLStreamWrite(p.outp, substr(p.x, d))
|
||||||
else:
|
of wLet, wVar, wConst, wType:
|
||||||
|
LLStreamWrite(p.outp, repeatChar(p.indent))
|
||||||
|
LLStreamWrite(p.outp, substr(p.x, d))
|
||||||
|
if not p.x.contains({':', '='}):
|
||||||
|
# no inline element --> treat as block:
|
||||||
|
inc(p.indent, 2)
|
||||||
|
else:
|
||||||
LLStreamWrite(p.outp, repeatChar(p.indent))
|
LLStreamWrite(p.outp, repeatChar(p.indent))
|
||||||
LLStreamWrite(p.outp, substr(p.x, d))
|
LLStreamWrite(p.outp, substr(p.x, d))
|
||||||
p.state = psDirective
|
p.state = psDirective
|
||||||
|
|
|
||||||
0
compiler/filters.nim
Executable file → Normal file
0
compiler/filters.nim
Executable file → Normal file
0
compiler/idents.nim
Executable file → Normal file
0
compiler/idents.nim
Executable file → Normal file
0
compiler/importer.nim
Executable file → Normal file
0
compiler/importer.nim
Executable file → Normal file
100
compiler/ecmasgen.nim → compiler/jsgen.nim
Executable file → Normal file
100
compiler/ecmasgen.nim → compiler/jsgen.nim
Executable file → Normal file
|
|
@ -20,22 +20,22 @@ import
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
type
|
type
|
||||||
TEcmasGen = object of TPassContext
|
TJSGen = object of TPassContext
|
||||||
module: PSym
|
module: PSym
|
||||||
|
|
||||||
BModule = ref TEcmasGen
|
BModule = ref TJSGen
|
||||||
TEcmasTypeKind = enum # necessary JS "types"
|
TJSTypeKind = enum # necessary JS "types"
|
||||||
etyNone, # no type
|
etyNone, # no type
|
||||||
etyNull, # null type
|
etyNull, # null type
|
||||||
etyProc, # proc type
|
etyProc, # proc type
|
||||||
etyBool, # bool type
|
etyBool, # bool type
|
||||||
etyInt, # Ecmascript's int
|
etyInt, # JavaScript's int
|
||||||
etyFloat, # Ecmascript's float
|
etyFloat, # JavaScript's float
|
||||||
etyString, # Ecmascript's string
|
etyString, # JavaScript's string
|
||||||
etyObject, # Ecmascript's reference to an object
|
etyObject, # JavaScript's reference to an object
|
||||||
etyBaseIndex # base + index needed
|
etyBaseIndex # base + index needed
|
||||||
TCompRes{.final.} = object
|
TCompRes{.final.} = object
|
||||||
kind: TEcmasTypeKind
|
kind: TJSTypeKind
|
||||||
com: PRope # computation part
|
com: PRope # computation part
|
||||||
# address if this is a (address, index)-tuple
|
# address if this is a (address, index)-tuple
|
||||||
res: PRope # result part; index if this is an
|
res: PRope # result part; index if this is an
|
||||||
|
|
@ -44,7 +44,6 @@ type
|
||||||
TBlock{.final.} = object
|
TBlock{.final.} = object
|
||||||
id: int # the ID of the label; positive means that it
|
id: int # the ID of the label; positive means that it
|
||||||
# has been used (i.e. the label should be emitted)
|
# has been used (i.e. the label should be emitted)
|
||||||
nestedTryStmts: int # how many try statements is it nested into
|
|
||||||
isLoop: bool # whether it's a 'block' or 'while'
|
isLoop: bool # whether it's a 'block' or 'while'
|
||||||
|
|
||||||
TGlobals{.final.} = object
|
TGlobals{.final.} = object
|
||||||
|
|
@ -57,12 +56,11 @@ type
|
||||||
TProc{.final.} = object
|
TProc{.final.} = object
|
||||||
procDef: PNode
|
procDef: PNode
|
||||||
prc: PSym
|
prc: PSym
|
||||||
data: PRope
|
locals: PRope
|
||||||
options: TOptions
|
options: TOptions
|
||||||
module: BModule
|
module: BModule
|
||||||
g: PGlobals
|
g: PGlobals
|
||||||
BeforeRetNeeded: bool
|
BeforeRetNeeded: bool
|
||||||
nestedTryStmts: int
|
|
||||||
unique: int
|
unique: int
|
||||||
blocks: seq[TBlock]
|
blocks: seq[TBlock]
|
||||||
|
|
||||||
|
|
@ -91,7 +89,7 @@ const
|
||||||
MappedToObject = {tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray,
|
MappedToObject = {tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray,
|
||||||
tySet, tyVar, tyRef, tyPtr, tyBigNum, tyVarargs}
|
tySet, tyVar, tyRef, tyPtr, tyBigNum, tyVarargs}
|
||||||
|
|
||||||
proc mapType(typ: PType): TEcmasTypeKind =
|
proc mapType(typ: PType): TJSTypeKind =
|
||||||
var t = skipTypes(typ, abstractInst)
|
var t = skipTypes(typ, abstractInst)
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyVar, tyRef, tyPtr:
|
of tyVar, tyRef, tyPtr:
|
||||||
|
|
@ -485,10 +483,6 @@ proc genLineDir(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
((p.prc == nil) or not (sfPure in p.prc.flags)):
|
((p.prc == nil) or not (sfPure in p.prc.flags)):
|
||||||
appf(r.com, "F.line = $1;$n", [toRope(line)])
|
appf(r.com, "F.line = $1;$n", [toRope(line)])
|
||||||
|
|
||||||
proc finishTryStmt(p: var TProc, r: var TCompRes, howMany: int) =
|
|
||||||
for i in countup(1, howMany):
|
|
||||||
app(r.com, "excHandler = excHandler.prev;" & tnl)
|
|
||||||
|
|
||||||
proc genWhileStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genWhileStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var
|
var
|
||||||
cond, stmt: TCompRes
|
cond, stmt: TCompRes
|
||||||
|
|
@ -498,7 +492,6 @@ proc genWhileStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
length = len(p.blocks)
|
length = len(p.blocks)
|
||||||
setlen(p.blocks, length + 1)
|
setlen(p.blocks, length + 1)
|
||||||
p.blocks[length].id = - p.unique
|
p.blocks[length].id = - p.unique
|
||||||
p.blocks[length].nestedTryStmts = p.nestedTryStmts
|
|
||||||
p.blocks[length].isLoop = true
|
p.blocks[length].isLoop = true
|
||||||
labl = p.unique
|
labl = p.unique
|
||||||
gen(p, n.sons[0], cond)
|
gen(p, n.sons[0], cond)
|
||||||
|
|
@ -543,7 +536,6 @@ proc genTryStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
if optStackTrace in p.Options: app(r.com, "framePtr = F;" & tnl)
|
if optStackTrace in p.Options: app(r.com, "framePtr = F;" & tnl)
|
||||||
app(r.com, "try {" & tnl)
|
app(r.com, "try {" & tnl)
|
||||||
length = sonsLen(n)
|
length = sonsLen(n)
|
||||||
inc(p.nestedTryStmts)
|
|
||||||
genStmt(p, n.sons[0], a)
|
genStmt(p, n.sons[0], a)
|
||||||
app(r.com, mergeStmt(a))
|
app(r.com, mergeStmt(a))
|
||||||
i = 1
|
i = 1
|
||||||
|
|
@ -571,8 +563,6 @@ proc genTryStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
appf(epart, "$1}$n", [mergeStmt(a)])
|
appf(epart, "$1}$n", [mergeStmt(a)])
|
||||||
inc(i)
|
inc(i)
|
||||||
if epart != nil: appf(r.com, "} catch (EXC) {$n$1", [epart])
|
if epart != nil: appf(r.com, "} catch (EXC) {$n$1", [epart])
|
||||||
finishTryStmt(p, r, p.nestedTryStmts)
|
|
||||||
dec(p.nestedTryStmts)
|
|
||||||
app(r.com, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl)
|
app(r.com, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl)
|
||||||
if (i < length) and (n.sons[i].kind == nkFinally):
|
if (i < length) and (n.sons[i].kind == nkFinally):
|
||||||
genStmt(p, n.sons[i].sons[0], a)
|
genStmt(p, n.sons[i].sons[0], a)
|
||||||
|
|
@ -605,8 +595,8 @@ proc genCaseStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
if cond.com != nil: appf(r.com, "$1;$n", [cond.com])
|
if cond.com != nil: appf(r.com, "$1;$n", [cond.com])
|
||||||
stringSwitch = skipTypes(n.sons[0].typ, abstractVar).kind == tyString
|
stringSwitch = skipTypes(n.sons[0].typ, abstractVar).kind == tyString
|
||||||
if stringSwitch:
|
if stringSwitch:
|
||||||
useMagic(p, "toEcmaStr")
|
useMagic(p, "toJSStr")
|
||||||
appf(r.com, "switch (toEcmaStr($1)) {$n", [cond.res])
|
appf(r.com, "switch (toJSStr($1)) {$n", [cond.res])
|
||||||
else:
|
else:
|
||||||
appf(r.com, "switch ($1) {$n", [cond.res])
|
appf(r.com, "switch ($1) {$n", [cond.res])
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
|
@ -619,17 +609,17 @@ proc genCaseStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
v = copyNode(e.sons[0])
|
v = copyNode(e.sons[0])
|
||||||
while (v.intVal <= e.sons[1].intVal):
|
while (v.intVal <= e.sons[1].intVal):
|
||||||
gen(p, v, cond)
|
gen(p, v, cond)
|
||||||
if cond.com != nil: internalError(v.info, "ecmasgen.genCaseStmt")
|
if cond.com != nil: internalError(v.info, "jsgen.genCaseStmt")
|
||||||
appf(r.com, "case $1: ", [cond.res])
|
appf(r.com, "case $1: ", [cond.res])
|
||||||
Inc(v.intVal)
|
Inc(v.intVal)
|
||||||
else:
|
else:
|
||||||
gen(p, e, cond)
|
gen(p, e, cond)
|
||||||
if cond.com != nil: internalError(e.info, "ecmasgen.genCaseStmt")
|
if cond.com != nil: internalError(e.info, "jsgen.genCaseStmt")
|
||||||
if stringSwitch:
|
if stringSwitch:
|
||||||
case e.kind
|
case e.kind
|
||||||
of nkStrLit..nkTripleStrLit: appf(r.com, "case $1: ",
|
of nkStrLit..nkTripleStrLit: appf(r.com, "case $1: ",
|
||||||
[makeJSString(e.strVal)])
|
[makeJSString(e.strVal)])
|
||||||
else: InternalError(e.info, "ecmasgen.genCaseStmt: 2")
|
else: InternalError(e.info, "jsgen.genCaseStmt: 2")
|
||||||
else:
|
else:
|
||||||
appf(r.com, "case $1: ", [cond.res])
|
appf(r.com, "case $1: ", [cond.res])
|
||||||
genStmt(p, lastSon(it), stmt)
|
genStmt(p, lastSon(it), stmt)
|
||||||
|
|
@ -637,7 +627,7 @@ proc genCaseStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
of nkElse:
|
of nkElse:
|
||||||
genStmt(p, it.sons[0], stmt)
|
genStmt(p, it.sons[0], stmt)
|
||||||
appf(r.com, "default: $n$1break;$n", [mergeStmt(stmt)])
|
appf(r.com, "default: $n$1break;$n", [mergeStmt(stmt)])
|
||||||
else: internalError(it.info, "ecmasgen.genCaseStmt")
|
else: internalError(it.info, "jsgen.genCaseStmt")
|
||||||
appf(r.com, "}$n", [])
|
appf(r.com, "}$n", [])
|
||||||
|
|
||||||
proc genStmtListExpr(p: var TProc, n: PNode, r: var TCompRes)
|
proc genStmtListExpr(p: var TProc, n: PNode, r: var TCompRes)
|
||||||
|
|
@ -655,7 +645,6 @@ proc genBlock(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
sym.loc.a = idx
|
sym.loc.a = idx
|
||||||
setlen(p.blocks, idx + 1)
|
setlen(p.blocks, idx + 1)
|
||||||
p.blocks[idx].id = - p.unique # negative because it isn't used yet
|
p.blocks[idx].id = - p.unique # negative because it isn't used yet
|
||||||
p.blocks[idx].nestedTryStmts = p.nestedTryStmts
|
|
||||||
labl = p.unique
|
labl = p.unique
|
||||||
if n.kind == nkBlockExpr: genStmtListExpr(p, n.sons[1], r)
|
if n.kind == nkBlockExpr: genStmtListExpr(p, n.sons[1], r)
|
||||||
else: genStmt(p, n.sons[1], r)
|
else: genStmt(p, n.sons[1], r)
|
||||||
|
|
@ -682,7 +671,6 @@ proc genBreakStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
if idx < 0 or not p.blocks[idx].isLoop:
|
if idx < 0 or not p.blocks[idx].isLoop:
|
||||||
InternalError(n.info, "no loop to break")
|
InternalError(n.info, "no loop to break")
|
||||||
p.blocks[idx].id = abs(p.blocks[idx].id) # label is used
|
p.blocks[idx].id = abs(p.blocks[idx].id) # label is used
|
||||||
finishTryStmt(p, r, p.nestedTryStmts - p.blocks[idx].nestedTryStmts)
|
|
||||||
appf(r.com, "break L$1;$n", [toRope(p.blocks[idx].id)])
|
appf(r.com, "break L$1;$n", [toRope(p.blocks[idx].id)])
|
||||||
|
|
||||||
proc genAsmStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genAsmStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
|
@ -692,7 +680,7 @@ proc genAsmStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
case n.sons[i].Kind
|
case n.sons[i].Kind
|
||||||
of nkStrLit..nkTripleStrLit: app(r.com, n.sons[i].strVal)
|
of nkStrLit..nkTripleStrLit: app(r.com, n.sons[i].strVal)
|
||||||
of nkSym: app(r.com, mangleName(n.sons[i].sym))
|
of nkSym: app(r.com, mangleName(n.sons[i].sym))
|
||||||
else: InternalError(n.sons[i].info, "ecmasgen: genAsmStmt()")
|
else: InternalError(n.sons[i].info, "jsgen: genAsmStmt()")
|
||||||
|
|
||||||
proc genIfStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genIfStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var
|
var
|
||||||
|
|
@ -758,7 +746,7 @@ proc generateHeader(p: var TProc, typ: PType): PRope =
|
||||||
|
|
||||||
const
|
const
|
||||||
nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
|
nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
|
||||||
nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkStringToCString,
|
nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkObjConstr, nkStringToCString,
|
||||||
nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix,
|
nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix,
|
||||||
nkCommand, nkHiddenCallConv, nkCallStrLit}
|
nkCommand, nkHiddenCallConv, nkCallStrLit}
|
||||||
|
|
||||||
|
|
@ -967,7 +955,8 @@ proc genSym(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
||||||
var r2: TCompRes
|
var r2: TCompRes
|
||||||
genProc(p, s, r2)
|
genProc(p, s, r2)
|
||||||
app(p.g.code, mergeStmt(r2))
|
app(p.locals, mergeStmt(r2))
|
||||||
|
#app(r.com, mergeStmt(r2))
|
||||||
else:
|
else:
|
||||||
if s.loc.r == nil:
|
if s.loc.r == nil:
|
||||||
InternalError(n.info, "symbol has no generated name: " & s.name.s)
|
InternalError(n.info, "symbol has no generated name: " & s.name.s)
|
||||||
|
|
@ -1152,6 +1141,8 @@ proc genConstant(p: var TProc, c: PSym, r: var TCompRes) =
|
||||||
if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id):
|
if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id):
|
||||||
genLineDir(p, c.ast, r)
|
genLineDir(p, c.ast, r)
|
||||||
genVarInit(p, c, c.ast, r)
|
genVarInit(p, c, c.ast, r)
|
||||||
|
app(p.g.code, r.com)
|
||||||
|
r.com = nil
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
proc genConstStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genConstStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
|
@ -1276,7 +1267,7 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
binaryStmt(p, n, r, "", "$1 += $2")
|
binaryStmt(p, n, r, "", "$1 += $2")
|
||||||
else:
|
else:
|
||||||
binaryStmt(p, n, r, "", "$1 = ($1.slice(0,-1)).concat($2)")
|
binaryStmt(p, n, r, "", "$1 = ($1.slice(0,-1)).concat($2)")
|
||||||
# XXX: make a copy of $2, because of ECMAScript's sucking semantics
|
# XXX: make a copy of $2, because of Javascript's sucking semantics
|
||||||
of mAppendSeqElem: binaryStmt(p, n, r, "", "$1.push($2)")
|
of mAppendSeqElem: binaryStmt(p, n, r, "", "$1.push($2)")
|
||||||
of mConStrStr: genConStrStr(p, n, r)
|
of mConStrStr: genConStrStr(p, n, r)
|
||||||
of mEqStr: binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)")
|
of mEqStr: binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)")
|
||||||
|
|
@ -1367,6 +1358,21 @@ proc genTupleConstr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
appf(r.res, "Field$1: $2", [i.toRope, a.res])
|
appf(r.res, "Field$1: $2", [i.toRope, a.res])
|
||||||
r.res.app("}")
|
r.res.app("}")
|
||||||
|
|
||||||
|
proc genObjConstr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
|
# XXX inheritance?
|
||||||
|
var a: TCompRes
|
||||||
|
r.res = toRope("{")
|
||||||
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
if i > 0: app(r.res, ", ")
|
||||||
|
var it = n.sons[i]
|
||||||
|
InternalAssert it.kind == nkExprColonExpr
|
||||||
|
gen(p, it.sons[1], a)
|
||||||
|
r.com = mergeExpr(r.com, a.com)
|
||||||
|
var f = it.sons[0].sym
|
||||||
|
if f.loc.r == nil: f.loc.r = mangleName(f)
|
||||||
|
appf(r.res, "$1: $2", [f.loc.r, a.res])
|
||||||
|
r.res.app("}")
|
||||||
|
|
||||||
proc genConv(p: var TProc, n: PNode, r: var TCompRes) =
|
proc genConv(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
var dest = skipTypes(n.typ, abstractVarRange)
|
var dest = skipTypes(n.typ, abstractVarRange)
|
||||||
var src = skipTypes(n.sons[1].typ, abstractVarRange)
|
var src = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||||
|
|
@ -1395,8 +1401,8 @@ proc convStrToCStr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
else:
|
else:
|
||||||
gen(p, n.sons[0], r)
|
gen(p, n.sons[0], r)
|
||||||
if r.res == nil: InternalError(n.info, "convStrToCStr")
|
if r.res == nil: InternalError(n.info, "convStrToCStr")
|
||||||
useMagic(p, "toEcmaStr")
|
useMagic(p, "toJSStr")
|
||||||
r.res = ropef("toEcmaStr($1)", [r.res])
|
r.res = ropef("toJSStr($1)", [r.res])
|
||||||
|
|
||||||
proc convCStrToStr(p: var TProc, n: PNode, r: var TCompRes) =
|
proc convCStrToStr(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
# we do an optimization here as this is likely to slow down
|
# we do an optimization here as this is likely to slow down
|
||||||
|
|
@ -1418,7 +1424,6 @@ proc genReturnStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
if a.com != nil: appf(r.com, "$1;$n", mergeStmt(a))
|
if a.com != nil: appf(r.com, "$1;$n", mergeStmt(a))
|
||||||
else:
|
else:
|
||||||
genLineDir(p, n, r)
|
genLineDir(p, n, r)
|
||||||
finishTryStmt(p, r, p.nestedTryStmts)
|
|
||||||
app(r.com, "break BeforeRet;" & tnl)
|
app(r.com, "break BeforeRet;" & tnl)
|
||||||
|
|
||||||
proc genProcBody(p: var TProc, prc: PSym, r: TCompRes): PRope =
|
proc genProcBody(p: var TProc, prc: PSym, r: TCompRes): PRope =
|
||||||
|
|
@ -1451,16 +1456,17 @@ proc genProc(oldProc: var TProc, prc: PSym, r: var TCompRes) =
|
||||||
resultAsgn = nil
|
resultAsgn = nil
|
||||||
name = mangleName(prc)
|
name = mangleName(prc)
|
||||||
header = generateHeader(p, prc.typ)
|
header = generateHeader(p, prc.typ)
|
||||||
if (prc.typ.sons[0] != nil) and sfPure notin prc.flags:
|
if prc.typ.sons[0] != nil and sfPure notin prc.flags:
|
||||||
resultSym = prc.ast.sons[resultPos].sym
|
resultSym = prc.ast.sons[resultPos].sym
|
||||||
resultAsgn = ropef("var $1 = $2;$n", [mangleName(resultSym),
|
resultAsgn = ropef("var $# = $#;$n", [mangleName(resultSym),
|
||||||
createVar(p, resultSym.typ, isIndirect(resultSym))])
|
createVar(p, resultSym.typ, isIndirect(resultSym))])
|
||||||
gen(p, prc.ast.sons[resultPos], a)
|
gen(p, prc.ast.sons[resultPos], a)
|
||||||
if a.com != nil: appf(returnStmt, "$1;$n", [a.com])
|
if a.com != nil: appf(returnStmt, "$1;$n", [a.com])
|
||||||
returnStmt = ropef("return $1;$n", [a.res])
|
returnStmt = ropef("return $#;$n", [a.res])
|
||||||
genStmt(p, prc.getBody, r)
|
genStmt(p, prc.getBody, r)
|
||||||
r.com = ropef("function $1($2) {$n$3$4$5}$n",
|
r.com = ropef("function $#($#) {$n$#$#$#$#}$n",
|
||||||
[name, header, resultAsgn, genProcBody(p, prc, r), returnStmt])
|
[name, header, p.locals, resultAsgn,
|
||||||
|
genProcBody(p, prc, r), returnStmt])
|
||||||
r.res = nil
|
r.res = nil
|
||||||
#if gVerbosity >= 3:
|
#if gVerbosity >= 3:
|
||||||
# echo "END generated code for: " & prc.name.s
|
# echo "END generated code for: " & prc.name.s
|
||||||
|
|
@ -1512,9 +1518,10 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: nil
|
nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: nil
|
||||||
of nkProcDef, nkMethodDef, nkConverterDef:
|
of nkProcDef, nkMethodDef, nkConverterDef:
|
||||||
var s = n.sons[namePos].sym
|
var s = n.sons[namePos].sym
|
||||||
if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}:
|
if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}:
|
||||||
var r2: TCompRes
|
#var r2: TCompRes
|
||||||
genSym(p, n.sons[namePos], r2)
|
genSym(p, n.sons[namePos], r)
|
||||||
|
r.res = nil
|
||||||
of nkGotoState, nkState:
|
of nkGotoState, nkState:
|
||||||
internalError(n.info, "first class iterators not implemented")
|
internalError(n.info, "first class iterators not implemented")
|
||||||
else:
|
else:
|
||||||
|
|
@ -1566,6 +1573,7 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
of nkCurly: genSetConstr(p, n, r)
|
of nkCurly: genSetConstr(p, n, r)
|
||||||
of nkBracket: genArrayConstr(p, n, r)
|
of nkBracket: genArrayConstr(p, n, r)
|
||||||
of nkPar: genTupleConstr(p, n, r)
|
of nkPar: genTupleConstr(p, n, r)
|
||||||
|
of nkObjConstr: genObjConstr(p, n, r)
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
||||||
of nkAddr, nkHiddenAddr: genAddr(p, n, r)
|
of nkAddr, nkHiddenAddr: genAddr(p, n, r)
|
||||||
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
||||||
|
|
@ -1626,7 +1634,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
|
||||||
if m.module == nil: InternalError(n.info, "myProcess")
|
if m.module == nil: InternalError(n.info, "myProcess")
|
||||||
initProc(p, globals, m, nil, m.module.options)
|
initProc(p, globals, m, nil, m.module.options)
|
||||||
genModule(p, n, r)
|
genModule(p, n, r)
|
||||||
app(p.g.code, p.data)
|
app(p.g.code, p.locals)
|
||||||
app(p.g.code, mergeStmt(r))
|
app(p.g.code, mergeStmt(r))
|
||||||
|
|
||||||
proc myClose(b: PPassContext, n: PNode): PNode =
|
proc myClose(b: PPassContext, n: PNode): PNode =
|
||||||
|
|
@ -1660,10 +1668,10 @@ proc myClose(b: PPassContext, n: PNode): PNode =
|
||||||
discard writeRopeIfNotEqual(con(genHeader(), code), outfile)
|
discard writeRopeIfNotEqual(con(genHeader(), code), outfile)
|
||||||
|
|
||||||
proc myOpenCached(s: PSym, rd: PRodReader): PPassContext =
|
proc myOpenCached(s: PSym, rd: PRodReader): PPassContext =
|
||||||
InternalError("symbol files are not possible with the Ecmas code generator")
|
InternalError("symbol files are not possible with the JS code generator")
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
proc myOpen(s: PSym): PPassContext =
|
proc myOpen(s: PSym): PPassContext =
|
||||||
result = newModule(s)
|
result = newModule(s)
|
||||||
|
|
||||||
const ecmasgenPass* = makePass(myOpen, myOpenCached, myProcess, myClose)
|
const JSgenPass* = makePass(myOpen, myOpenCached, myProcess, myClose)
|
||||||
|
|
@ -322,7 +322,7 @@ proc generateThunk(prc: PNode, dest: PType): PNode =
|
||||||
|
|
||||||
# we cannot generate a proper thunk here for GC-safety reasons (see internal
|
# we cannot generate a proper thunk here for GC-safety reasons (see internal
|
||||||
# documentation):
|
# documentation):
|
||||||
if gCmd == cmdCompileToEcmaScript: return prc
|
if gCmd == cmdCompileToJS: return prc
|
||||||
result = newNodeIT(nkClosure, prc.info, dest)
|
result = newNodeIT(nkClosure, prc.info, dest)
|
||||||
var conv = newNodeIT(nkHiddenStdConv, prc.info, dest)
|
var conv = newNodeIT(nkHiddenStdConv, prc.info, dest)
|
||||||
conv.add(emptyNode)
|
conv.add(emptyNode)
|
||||||
|
|
@ -391,7 +391,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
|
||||||
gatherVars(o, inner, body)
|
gatherVars(o, inner, body)
|
||||||
# dummy closure param needed?
|
# dummy closure param needed?
|
||||||
if inner.closureParam == nil and n.sym.typ.callConv == ccClosure:
|
if inner.closureParam == nil and n.sym.typ.callConv == ccClosure:
|
||||||
assert tfCapturesEnv notin n.sym.typ.flags
|
#assert tfCapturesEnv notin n.sym.typ.flags
|
||||||
dummyClosureParam(o, inner)
|
dummyClosureParam(o, inner)
|
||||||
# only transform if it really needs a closure:
|
# only transform if it really needs a closure:
|
||||||
if inner.closureParam != nil:
|
if inner.closureParam != nil:
|
||||||
|
|
@ -443,10 +443,15 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
searchForInnerProcs(o, n.sons[i])
|
searchForInnerProcs(o, n.sons[i])
|
||||||
|
|
||||||
proc newAsgnStmt(le, ri: PNode): PNode =
|
proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
|
||||||
result = newNodeI(nkFastAsgn, ri.info)
|
# Bugfix: unfortunately we cannot use 'nkFastAsgn' here as that would
|
||||||
result.add(le)
|
# mean to be able to capture string literals which have no GC header.
|
||||||
result.add(ri)
|
# However this can only happen if the capture happens through a parameter,
|
||||||
|
# which is however the only case when we generate an assignment in the first
|
||||||
|
# place.
|
||||||
|
result = newNodeI(nkAsgn, info, 2)
|
||||||
|
result.sons[0] = le
|
||||||
|
result.sons[1] = ri
|
||||||
|
|
||||||
proc addVar*(father, v: PNode) =
|
proc addVar*(father, v: PNode) =
|
||||||
var vpart = newNodeI(nkIdentDefs, v.info)
|
var vpart = newNodeI(nkIdentDefs, v.info)
|
||||||
|
|
@ -481,13 +486,13 @@ proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode =
|
||||||
if local.kind == skParam:
|
if local.kind == skParam:
|
||||||
# maybe later: (sfByCopy in local.flags)
|
# maybe later: (sfByCopy in local.flags)
|
||||||
# add ``env.param = param``
|
# add ``env.param = param``
|
||||||
result.add(newAsgnStmt(fieldAccess, newSymNode(local)))
|
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
|
||||||
IdNodeTablePut(o.localsToAccess, local, fieldAccess)
|
IdNodeTablePut(o.localsToAccess, local, fieldAccess)
|
||||||
# add support for 'up' references:
|
# add support for 'up' references:
|
||||||
for e, field in items(scope.deps):
|
for e, field in items(scope.deps):
|
||||||
# add ``env.up = env2``
|
# add ``env.up = env2``
|
||||||
result.add(newAsgnStmt(indirectAccess(env, field, env.info),
|
result.add(newAsgnStmt(indirectAccess(env, field, env.info),
|
||||||
newSymNode(getClosureVar(o, e))))
|
newSymNode(getClosureVar(o, e)), env.info))
|
||||||
|
|
||||||
proc transformOuterProc(o: POuterContext, n: PNode): PNode =
|
proc transformOuterProc(o: POuterContext, n: PNode): PNode =
|
||||||
if n == nil: return nil
|
if n == nil: return nil
|
||||||
|
|
@ -543,7 +548,7 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
|
||||||
if x != nil: n.sons[i] = x
|
if x != nil: n.sons[i] = x
|
||||||
|
|
||||||
proc liftLambdas*(fn: PSym, body: PNode): PNode =
|
proc liftLambdas*(fn: PSym, body: PNode): PNode =
|
||||||
if body.kind == nkEmpty or gCmd == cmdCompileToEcmaScript:
|
if body.kind == nkEmpty or gCmd == cmdCompileToJS:
|
||||||
# ignore forward declaration:
|
# ignore forward declaration:
|
||||||
result = body
|
result = body
|
||||||
else:
|
else:
|
||||||
|
|
@ -566,7 +571,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
|
||||||
result = ex
|
result = ex
|
||||||
|
|
||||||
proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
|
proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
|
||||||
if body.kind == nkEmpty or gCmd == cmdCompileToEcmaScript:
|
if body.kind == nkEmpty or gCmd == cmdCompileToJS:
|
||||||
result = body
|
result = body
|
||||||
else:
|
else:
|
||||||
var o = newOuterContext(module)
|
var o = newOuterContext(module)
|
||||||
|
|
|
||||||
19
compiler/lexer.nim
Executable file → Normal file
19
compiler/lexer.nim
Executable file → Normal file
|
|
@ -16,7 +16,7 @@
|
||||||
# DOS or Macintosh text files, even when it is not the native format.
|
# DOS or Macintosh text files, even when it is not the native format.
|
||||||
|
|
||||||
import
|
import
|
||||||
hashes, options, msgs, strutils, platform, idents, lexbase, llstream,
|
hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream,
|
||||||
wordrecg
|
wordrecg
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -530,10 +530,10 @@ proc HandleCRLF(L: var TLexer, pos: int): int =
|
||||||
case L.buf[pos]
|
case L.buf[pos]
|
||||||
of CR:
|
of CR:
|
||||||
registerLine()
|
registerLine()
|
||||||
result = lexbase.HandleCR(L, pos)
|
result = nimlexbase.HandleCR(L, pos)
|
||||||
of LF:
|
of LF:
|
||||||
registerLine()
|
registerLine()
|
||||||
result = lexbase.HandleLF(L, pos)
|
result = nimlexbase.HandleLF(L, pos)
|
||||||
else: result = pos
|
else: result = pos
|
||||||
|
|
||||||
proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
||||||
|
|
@ -559,7 +559,7 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
||||||
pos = HandleCRLF(L, pos)
|
pos = HandleCRLF(L, pos)
|
||||||
buf = L.buf
|
buf = L.buf
|
||||||
add(tok.literal, tnl)
|
add(tok.literal, tnl)
|
||||||
of lexbase.EndOfFile:
|
of nimlexbase.EndOfFile:
|
||||||
var line2 = L.linenumber
|
var line2 = L.linenumber
|
||||||
L.LineNumber = line
|
L.LineNumber = line
|
||||||
lexMessagePos(L, errClosingTripleQuoteExpected, L.lineStart)
|
lexMessagePos(L, errClosingTripleQuoteExpected, L.lineStart)
|
||||||
|
|
@ -581,7 +581,7 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
|
||||||
else:
|
else:
|
||||||
inc(pos) # skip '"'
|
inc(pos) # skip '"'
|
||||||
break
|
break
|
||||||
elif c in {CR, LF, lexbase.EndOfFile}:
|
elif c in {CR, LF, nimlexbase.EndOfFile}:
|
||||||
lexMessage(L, errClosingQuoteExpected)
|
lexMessage(L, errClosingQuoteExpected)
|
||||||
break
|
break
|
||||||
elif (c == '\\') and not rawMode:
|
elif (c == '\\') and not rawMode:
|
||||||
|
|
@ -675,10 +675,12 @@ proc scanComment(L: var TLexer, tok: var TToken) =
|
||||||
# a comment ends if the next line does not start with the # on the same
|
# a comment ends if the next line does not start with the # on the same
|
||||||
# column after only whitespace
|
# column after only whitespace
|
||||||
tok.tokType = tkComment
|
tok.tokType = tkComment
|
||||||
|
# iNumber contains the number of '\n' in the token
|
||||||
|
tok.iNumber = 0
|
||||||
var col = getColNumber(L, pos)
|
var col = getColNumber(L, pos)
|
||||||
while true:
|
while true:
|
||||||
var lastBackslash = -1
|
var lastBackslash = -1
|
||||||
while buf[pos] notin {CR, LF, lexbase.EndOfFile}:
|
while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}:
|
||||||
if buf[pos] == '\\': lastBackslash = pos+1
|
if buf[pos] == '\\': lastBackslash = pos+1
|
||||||
add(tok.literal, buf[pos])
|
add(tok.literal, buf[pos])
|
||||||
inc(pos)
|
inc(pos)
|
||||||
|
|
@ -686,7 +688,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
|
||||||
# a backslash is a continuation character if only followed by spaces
|
# a backslash is a continuation character if only followed by spaces
|
||||||
# plus a newline:
|
# plus a newline:
|
||||||
while buf[lastBackslash] == ' ': inc(lastBackslash)
|
while buf[lastBackslash] == ' ': inc(lastBackslash)
|
||||||
if buf[lastBackslash] notin {CR, LF, lexbase.EndOfFile}:
|
if buf[lastBackslash] notin {CR, LF, nimlexbase.EndOfFile}:
|
||||||
# false positive:
|
# false positive:
|
||||||
lastBackslash = -1
|
lastBackslash = -1
|
||||||
|
|
||||||
|
|
@ -699,6 +701,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
|
||||||
if buf[pos] == '#' and (col == indent or lastBackslash > 0):
|
if buf[pos] == '#' and (col == indent or lastBackslash > 0):
|
||||||
tok.literal.add "\n"
|
tok.literal.add "\n"
|
||||||
col = indent
|
col = indent
|
||||||
|
inc tok.iNumber
|
||||||
else:
|
else:
|
||||||
if buf[pos] > ' ':
|
if buf[pos] > ' ':
|
||||||
L.indentAhead = indent
|
L.indentAhead = indent
|
||||||
|
|
@ -838,7 +841,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) =
|
||||||
else:
|
else:
|
||||||
if c in OpChars:
|
if c in OpChars:
|
||||||
getOperator(L, tok)
|
getOperator(L, tok)
|
||||||
elif c == lexbase.EndOfFile:
|
elif c == nimlexbase.EndOfFile:
|
||||||
tok.toktype = tkEof
|
tok.toktype = tkEof
|
||||||
else:
|
else:
|
||||||
tok.literal = c & ""
|
tok.literal = c & ""
|
||||||
|
|
|
||||||
0
compiler/lists.nim
Executable file → Normal file
0
compiler/lists.nim
Executable file → Normal file
0
compiler/llstream.nim
Executable file → Normal file
0
compiler/llstream.nim
Executable file → Normal file
0
compiler/lookups.nim
Executable file → Normal file
0
compiler/lookups.nim
Executable file → Normal file
5
compiler/magicsys.nim
Executable file → Normal file
5
compiler/magicsys.nim
Executable file → Normal file
|
|
@ -38,7 +38,10 @@ proc newSysType(kind: TTypeKind, size: int): PType =
|
||||||
|
|
||||||
proc getSysSym(name: string): PSym =
|
proc getSysSym(name: string): PSym =
|
||||||
result = StrTableGet(systemModule.tab, getIdent(name))
|
result = StrTableGet(systemModule.tab, getIdent(name))
|
||||||
if result == nil: rawMessage(errSystemNeeds, name)
|
if result == nil:
|
||||||
|
rawMessage(errSystemNeeds, name)
|
||||||
|
result = newSym(skError, getIdent(name), systemModule, systemModule.info)
|
||||||
|
result.typ = newType(tyError, systemModule)
|
||||||
if result.kind == skStub: loadStub(result)
|
if result.kind == skStub: loadStub(result)
|
||||||
|
|
||||||
proc sysTypeFromName*(name: string): PType =
|
proc sysTypeFromName*(name: string): PType =
|
||||||
|
|
|
||||||
68
compiler/main.nim
Executable file → Normal file
68
compiler/main.nim
Executable file → Normal file
|
|
@ -14,7 +14,7 @@ import
|
||||||
llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs,
|
llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs,
|
||||||
os, lists, condsyms, rodread, rodwrite, ropes, trees, times,
|
os, lists, condsyms, rodread, rodwrite, ropes, trees, times,
|
||||||
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
|
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
|
||||||
cgen, ecmasgen, cgendata,
|
cgen, jsgen, cgendata, json, nversion,
|
||||||
platform, nimconf, importer, passaux, depends, evals, types, idgen,
|
platform, nimconf, importer, passaux, depends, evals, types, idgen,
|
||||||
tables, docgen2, service, magicsys, parser, crc, ccgutils
|
tables, docgen2, service, magicsys, parser, crc, ccgutils
|
||||||
|
|
||||||
|
|
@ -155,7 +155,8 @@ proc compileModule(fileIdx: int32, flags: TSymFlags): PSym =
|
||||||
growCache gMemCacheData, fileIdx
|
growCache gMemCacheData, fileIdx
|
||||||
gMemCacheData[fileIdx].needsRecompile = Probing
|
gMemCacheData[fileIdx].needsRecompile = Probing
|
||||||
result = newModule(fileIdx)
|
result = newModule(fileIdx)
|
||||||
var rd = handleSymbolFile(result)
|
#var rd = handleSymbolFile(result)
|
||||||
|
var rd: PRodReader
|
||||||
result.flags = result.flags + flags
|
result.flags = result.flags + flags
|
||||||
if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
|
if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
|
||||||
rd = handleSymbolFile(result)
|
rd = handleSymbolFile(result)
|
||||||
|
|
@ -251,8 +252,8 @@ proc CommandCompileToC =
|
||||||
|
|
||||||
compileProject()
|
compileProject()
|
||||||
|
|
||||||
if optCaasEnabled in gGlobalOptions:
|
if compilationCachePresent:
|
||||||
cgenCaasUpdate()
|
updateCachedModules()
|
||||||
|
|
||||||
if gCmd != cmdRun:
|
if gCmd != cmdRun:
|
||||||
extccomp.CallCCompiler(changeFileExt(gProjectFull, ""))
|
extccomp.CallCCompiler(changeFileExt(gProjectFull, ""))
|
||||||
|
|
@ -301,18 +302,19 @@ when has_LLVM_Backend:
|
||||||
#registerPass(cleanupPass())
|
#registerPass(cleanupPass())
|
||||||
compileProject()
|
compileProject()
|
||||||
|
|
||||||
proc CommandCompileToEcmaScript =
|
proc CommandCompileToJS =
|
||||||
#incl(gGlobalOptions, optSafeCode)
|
#incl(gGlobalOptions, optSafeCode)
|
||||||
setTarget(osEcmaScript, cpuEcmaScript)
|
setTarget(osJS, cpuJS)
|
||||||
#initDefines()
|
#initDefines()
|
||||||
DefineSymbol("nimrod") # 'nimrod' is always defined
|
DefineSymbol("nimrod") # 'nimrod' is always defined
|
||||||
DefineSymbol("ecmascript")
|
DefineSymbol("ecmascript") # For backward compatibility
|
||||||
|
DefineSymbol("js")
|
||||||
semanticPasses()
|
semanticPasses()
|
||||||
registerPass(ecmasgenPass)
|
registerPass(jsgenPass)
|
||||||
compileProject()
|
compileProject()
|
||||||
|
|
||||||
proc InteractivePasses =
|
proc InteractivePasses =
|
||||||
incl(gGlobalOptions, optSafeCode)
|
#incl(gGlobalOptions, optSafeCode)
|
||||||
#setTarget(osNimrodVM, cpuNimrodVM)
|
#setTarget(osNimrodVM, cpuNimrodVM)
|
||||||
initDefines()
|
initDefines()
|
||||||
DefineSymbol("nimrodvm")
|
DefineSymbol("nimrodvm")
|
||||||
|
|
@ -390,6 +392,15 @@ proc wantMainModule =
|
||||||
|
|
||||||
gProjectMainIdx = addFileExt(gProjectFull, nimExt).fileInfoIdx
|
gProjectMainIdx = addFileExt(gProjectFull, nimExt).fileInfoIdx
|
||||||
|
|
||||||
|
proc requireMainModuleOption =
|
||||||
|
if optMainModule.len == 0:
|
||||||
|
Fatal(gCmdLineInfo, errMainModuleMustBeSpecified)
|
||||||
|
else:
|
||||||
|
gProjectName = optMainModule
|
||||||
|
gProjectFull = gProjectPath / gProjectName
|
||||||
|
|
||||||
|
gProjectMainIdx = addFileExt(gProjectFull, nimExt).fileInfoIdx
|
||||||
|
|
||||||
proc resetMemory =
|
proc resetMemory =
|
||||||
resetCompilationLists()
|
resetCompilationLists()
|
||||||
ccgutils.resetCaches()
|
ccgutils.resetCaches()
|
||||||
|
|
@ -461,9 +472,10 @@ proc MainCommand =
|
||||||
gCmd = cmdCompileToC
|
gCmd = cmdCompileToC
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
CommandCompileToC()
|
CommandCompileToC()
|
||||||
of "cpp", "compiletocpp":
|
of "cpp", "compiletocpp":
|
||||||
extccomp.cExt = ".cpp"
|
extccomp.cExt = ".cpp"
|
||||||
gCmd = cmdCompileToCpp
|
gCmd = cmdCompileToCpp
|
||||||
|
if cCompiler == ccGcc: setCC("gpp")
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
DefineSymbol("cpp")
|
DefineSymbol("cpp")
|
||||||
CommandCompileToC()
|
CommandCompileToC()
|
||||||
|
|
@ -481,10 +493,10 @@ proc MainCommand =
|
||||||
CommandCompileToC()
|
CommandCompileToC()
|
||||||
else:
|
else:
|
||||||
rawMessage(errInvalidCommandX, command)
|
rawMessage(errInvalidCommandX, command)
|
||||||
of "js", "compiletoecmascript":
|
of "js", "compiletojs":
|
||||||
gCmd = cmdCompileToEcmaScript
|
gCmd = cmdCompileToJS
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
CommandCompileToEcmaScript()
|
CommandCompileToJS()
|
||||||
of "compiletollvm":
|
of "compiletollvm":
|
||||||
gCmd = cmdCompileToLLVM
|
gCmd = cmdCompileToLLVM
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
|
|
@ -526,9 +538,30 @@ proc MainCommand =
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
CommandGenDepend()
|
CommandGenDepend()
|
||||||
of "dump":
|
of "dump":
|
||||||
gCmd = cmdDump
|
gcmd = cmdDump
|
||||||
condsyms.ListSymbols()
|
if getconfigvar("dump.format") == "json":
|
||||||
for it in iterSearchPath(searchPaths): MsgWriteln(it)
|
requireMainModuleOption()
|
||||||
|
|
||||||
|
var definedSymbols = newJArray()
|
||||||
|
for s in definedSymbolNames(): definedSymbols.elems.add(%s)
|
||||||
|
|
||||||
|
var libpaths = newJArray()
|
||||||
|
for dir in itersearchpath(searchpaths): libpaths.elems.add(%dir)
|
||||||
|
|
||||||
|
var dumpdata = % [
|
||||||
|
(key: "version", val: %VersionAsString),
|
||||||
|
(key: "project_path", val: %gProjectFull),
|
||||||
|
(key: "defined_symbols", val: definedSymbols),
|
||||||
|
(key: "lib_paths", val: libpaths)
|
||||||
|
]
|
||||||
|
|
||||||
|
outWriteLn($dumpdata)
|
||||||
|
else:
|
||||||
|
outWriteLn("-- list of currently defined symbols --")
|
||||||
|
for s in definedSymbolNames(): outWriteLn(s)
|
||||||
|
outWriteLn("-- end of list --")
|
||||||
|
|
||||||
|
for it in iterSearchPath(searchpaths): msgWriteLn(it)
|
||||||
of "check":
|
of "check":
|
||||||
gCmd = cmdCheck
|
gCmd = cmdCheck
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
|
|
@ -558,13 +591,14 @@ proc MainCommand =
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
CommandSuggest()
|
CommandSuggest()
|
||||||
of "serve":
|
of "serve":
|
||||||
|
isServing = true
|
||||||
gGlobalOptions.incl(optCaasEnabled)
|
gGlobalOptions.incl(optCaasEnabled)
|
||||||
msgs.gErrorMax = high(int) # do not stop after first error
|
msgs.gErrorMax = high(int) # do not stop after first error
|
||||||
serve(MainCommand)
|
serve(MainCommand)
|
||||||
else:
|
else:
|
||||||
rawMessage(errInvalidCommandX, command)
|
rawMessage(errInvalidCommandX, command)
|
||||||
|
|
||||||
if msgs.gErrorCounter == 0 and gCmd notin {cmdInterpret, cmdRun}:
|
if msgs.gErrorCounter == 0 and gCmd notin {cmdInterpret, cmdRun, cmdDump}:
|
||||||
rawMessage(hintSuccessX, [$gLinesCompiled,
|
rawMessage(hintSuccessX, [$gLinesCompiled,
|
||||||
formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3),
|
formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3),
|
||||||
formatSize(getTotalMem())])
|
formatSize(getTotalMem())])
|
||||||
|
|
|
||||||
24
compiler/msgs.nim
Executable file → Normal file
24
compiler/msgs.nim
Executable file → Normal file
|
|
@ -83,7 +83,9 @@ type
|
||||||
errInvalidCommandX, errXOnlyAtModuleScope,
|
errInvalidCommandX, errXOnlyAtModuleScope,
|
||||||
errXNeedsParamObjectType,
|
errXNeedsParamObjectType,
|
||||||
errTemplateInstantiationTooNested, errInstantiationFrom,
|
errTemplateInstantiationTooNested, errInstantiationFrom,
|
||||||
errInvalidIndexValueForTuple, errCommandExpectsFilename, errXExpected,
|
errInvalidIndexValueForTuple, errCommandExpectsFilename,
|
||||||
|
errMainModuleMustBeSpecified,
|
||||||
|
errXExpected,
|
||||||
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
|
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
|
||||||
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
|
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
|
||||||
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
|
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
|
||||||
|
|
@ -301,6 +303,7 @@ const
|
||||||
errInstantiationFrom: "instantiation from here",
|
errInstantiationFrom: "instantiation from here",
|
||||||
errInvalidIndexValueForTuple: "invalid index value for tuple subscript",
|
errInvalidIndexValueForTuple: "invalid index value for tuple subscript",
|
||||||
errCommandExpectsFilename: "command expects a filename argument",
|
errCommandExpectsFilename: "command expects a filename argument",
|
||||||
|
errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
|
||||||
errXExpected: "\'$1\' expected",
|
errXExpected: "\'$1\' expected",
|
||||||
errInvalidSectionStart: "invalid section start",
|
errInvalidSectionStart: "invalid section start",
|
||||||
errGridTableNotImplemented: "grid table is not implemented",
|
errGridTableNotImplemented: "grid table is not implemented",
|
||||||
|
|
@ -506,6 +509,8 @@ var gCodegenLineInfo* = newLineInfo(int32(1), 1, 1)
|
||||||
proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} =
|
proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} =
|
||||||
raise newException(ERecoverableError, msg)
|
raise newException(ERecoverableError, msg)
|
||||||
|
|
||||||
|
proc sourceLine*(i: TLineInfo): PRope
|
||||||
|
|
||||||
var
|
var
|
||||||
gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent}
|
gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent}
|
||||||
gErrorCounter*: int = 0 # counts the number of errors
|
gErrorCounter*: int = 0 # counts the number of errors
|
||||||
|
|
@ -523,8 +528,8 @@ proc SuggestWriteln*(s: string) =
|
||||||
stdoutSocket.send(s & "\c\L")
|
stdoutSocket.send(s & "\c\L")
|
||||||
|
|
||||||
proc SuggestQuit*() =
|
proc SuggestQuit*() =
|
||||||
if isNil(stdoutSocket): quit(0)
|
if not isServing: quit(0)
|
||||||
else:
|
elif not isNil(stdoutSocket):
|
||||||
stdoutSocket.send("\c\L")
|
stdoutSocket.send("\c\L")
|
||||||
raise newException(ESuggestDone, "suggest done")
|
raise newException(ESuggestDone, "suggest done")
|
||||||
|
|
||||||
|
|
@ -707,6 +712,11 @@ proc rawMessage*(msg: TMsgKind, arg: string) =
|
||||||
var
|
var
|
||||||
lastError = UnknownLineInfo()
|
lastError = UnknownLineInfo()
|
||||||
|
|
||||||
|
proc writeSurroundingSrc(info: TLineInfo) =
|
||||||
|
const indent = " "
|
||||||
|
MsgWriteln(indent & info.sourceLine.data)
|
||||||
|
MsgWriteln(indent & repeatChar(info.col, ' ') & '^')
|
||||||
|
|
||||||
proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
|
proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
|
||||||
eh: TErrorHandling) =
|
eh: TErrorHandling) =
|
||||||
var frmt: string
|
var frmt: string
|
||||||
|
|
@ -732,6 +742,8 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
|
||||||
coordToStr(info.col), getMessageStr(msg, arg)]
|
coordToStr(info.col), getMessageStr(msg, arg)]
|
||||||
if not ignoreMsg:
|
if not ignoreMsg:
|
||||||
MsgWriteln(s)
|
MsgWriteln(s)
|
||||||
|
if optPrintSurroundingSrc and msg in errMin..errMax:
|
||||||
|
info.writeSurroundingSrc
|
||||||
handleError(msg, eh, s)
|
handleError(msg, eh, s)
|
||||||
|
|
||||||
proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") =
|
proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") =
|
||||||
|
|
@ -771,6 +783,12 @@ proc addSourceLine*(fileIdx: int32, line: string) =
|
||||||
|
|
||||||
proc sourceLine*(i: TLineInfo): PRope =
|
proc sourceLine*(i: TLineInfo): PRope =
|
||||||
if i.fileIndex < 0: return nil
|
if i.fileIndex < 0: return nil
|
||||||
|
|
||||||
|
if not optPreserveOrigSource and
|
||||||
|
fileInfos[i.fileIndex].lines.len == 0:
|
||||||
|
for line in lines(i.toFullPath):
|
||||||
|
addSourceLine i.fileIndex, line.string
|
||||||
|
|
||||||
InternalAssert i.fileIndex < fileInfos.len and
|
InternalAssert i.fileIndex < fileInfos.len and
|
||||||
i.line <= fileInfos[i.fileIndex].lines.len
|
i.line <= fileInfos[i.fileIndex].lines.len
|
||||||
|
|
||||||
|
|
|
||||||
0
compiler/nimconf.nim
Executable file → Normal file
0
compiler/nimconf.nim
Executable file → Normal file
0
compiler/lexbase.nim → compiler/nimlexbase.nim
Executable file → Normal file
0
compiler/lexbase.nim → compiler/nimlexbase.nim
Executable file → Normal file
2
compiler/nimrod.cfg
Executable file → Normal file
2
compiler/nimrod.cfg
Executable file → Normal file
|
|
@ -6,7 +6,7 @@ hint[XDeclaredButNotUsed]:off
|
||||||
path:"llvm"
|
path:"llvm"
|
||||||
path:"$projectPath/.."
|
path:"$projectPath/.."
|
||||||
|
|
||||||
path:"$nimrod/packages/docutils"
|
path:"$lib/packages/docutils"
|
||||||
|
|
||||||
define:booting
|
define:booting
|
||||||
|
|
||||||
|
|
|
||||||
54
compiler/nimrod.dot
Executable file → Normal file
54
compiler/nimrod.dot
Executable file → Normal file
|
|
@ -472,32 +472,32 @@ cgen -> wordrecg;
|
||||||
cgen -> rnimsyn;
|
cgen -> rnimsyn;
|
||||||
cgen -> treetab;
|
cgen -> treetab;
|
||||||
cgen -> cgmeth;
|
cgen -> cgmeth;
|
||||||
ecmasgen -> ast;
|
jsgen -> ast;
|
||||||
ecmasgen -> astalgo;
|
jsgen -> astalgo;
|
||||||
ecmasgen -> strutils;
|
jsgen -> strutils;
|
||||||
ecmasgen -> nhashes;
|
jsgen -> nhashes;
|
||||||
ecmasgen -> trees;
|
jsgen -> trees;
|
||||||
ecmasgen -> platform;
|
jsgen -> platform;
|
||||||
ecmasgen -> magicsys;
|
jsgen -> magicsys;
|
||||||
ecmasgen -> extccomp;
|
jsgen -> extccomp;
|
||||||
ecmasgen -> options;
|
jsgen -> options;
|
||||||
ecmasgen -> nversion;
|
jsgen -> nversion;
|
||||||
ecmasgen -> nimsets;
|
jsgen -> nimsets;
|
||||||
ecmasgen -> msgs;
|
jsgen -> msgs;
|
||||||
ecmasgen -> crc;
|
jsgen -> crc;
|
||||||
ecmasgen -> bitsets;
|
jsgen -> bitsets;
|
||||||
ecmasgen -> idents;
|
jsgen -> idents;
|
||||||
ecmasgen -> lists;
|
jsgen -> lists;
|
||||||
ecmasgen -> types;
|
jsgen -> types;
|
||||||
ecmasgen -> os;
|
jsgen -> os;
|
||||||
ecmasgen -> times;
|
jsgen -> times;
|
||||||
ecmasgen -> ropes;
|
jsgen -> ropes;
|
||||||
ecmasgen -> math;
|
jsgen -> math;
|
||||||
ecmasgen -> passes;
|
jsgen -> passes;
|
||||||
ecmasgen -> ccgutils;
|
jsgen -> ccgutils;
|
||||||
ecmasgen -> wordrecg;
|
jsgen -> wordrecg;
|
||||||
ecmasgen -> rnimsyn;
|
jsgen -> rnimsyn;
|
||||||
ecmasgen -> rodread;
|
jsgen -> rodread;
|
||||||
interact -> llstream;
|
interact -> llstream;
|
||||||
interact -> strutils;
|
interact -> strutils;
|
||||||
interact -> ropes;
|
interact -> ropes;
|
||||||
|
|
@ -561,7 +561,7 @@ main -> passes;
|
||||||
main -> docgen;
|
main -> docgen;
|
||||||
main -> extccomp;
|
main -> extccomp;
|
||||||
main -> cgen;
|
main -> cgen;
|
||||||
main -> ecmasgen;
|
main -> jsgen;
|
||||||
main -> platform;
|
main -> platform;
|
||||||
main -> interact;
|
main -> interact;
|
||||||
main -> nimconf;
|
main -> nimconf;
|
||||||
|
|
|
||||||
5
compiler/nimrod.ini
Executable file → Normal file
5
compiler/nimrod.ini
Executable file → Normal file
|
|
@ -57,8 +57,6 @@ Files: "compiler/*.nim"
|
||||||
Files: "build/empty.txt"
|
Files: "build/empty.txt"
|
||||||
Files: "bin/empty.txt"
|
Files: "bin/empty.txt"
|
||||||
|
|
||||||
Files: "packages/docutils/*.nim"
|
|
||||||
|
|
||||||
|
|
||||||
[Lib]
|
[Lib]
|
||||||
Files: "lib/nimbase.h"
|
Files: "lib/nimbase.h"
|
||||||
|
|
@ -84,7 +82,8 @@ Files: "lib/wrappers/zip/libzip_all.c"
|
||||||
|
|
||||||
Files: "lib/windows/*.nim"
|
Files: "lib/windows/*.nim"
|
||||||
Files: "lib/posix/*.nim"
|
Files: "lib/posix/*.nim"
|
||||||
Files: "lib/ecmas/*.nim"
|
Files: "lib/js/*.nim"
|
||||||
|
Files: "lib/packages/docutils/*.nim"
|
||||||
|
|
||||||
|
|
||||||
[Other]
|
[Other]
|
||||||
|
|
|
||||||
2
compiler/nimrod.nim
Executable file → Normal file
2
compiler/nimrod.nim
Executable file → Normal file
|
|
@ -60,7 +60,7 @@ proc HandleCmdLine() =
|
||||||
if gCmd == cmdRun:
|
if gCmd == cmdRun:
|
||||||
tccgen.run()
|
tccgen.run()
|
||||||
if optRun in gGlobalOptions:
|
if optRun in gGlobalOptions:
|
||||||
if gCmd == cmdCompileToEcmaScript:
|
if gCmd == cmdCompileToJS:
|
||||||
var ex = quoteIfContainsWhite(
|
var ex = quoteIfContainsWhite(
|
||||||
completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
|
completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
|
||||||
execExternalProgram("node " & ex & ' ' & service.arguments)
|
execExternalProgram("node " & ex & ' ' & service.arguments)
|
||||||
|
|
|
||||||
10
compiler/nimsets.nim
Executable file → Normal file
10
compiler/nimsets.nim
Executable file → Normal file
|
|
@ -44,9 +44,9 @@ proc inSet(s: PNode, elem: PNode): bool =
|
||||||
return true
|
return true
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc overlap(a, b: PNode): bool =
|
proc overlap(a, b: PNode): bool =
|
||||||
if a.kind == nkRange:
|
if a.kind == nkRange:
|
||||||
if b.kind == nkRange:
|
if b.kind == nkRange:
|
||||||
# X..Y and C..D overlap iff (X <= D and C <= Y)
|
# X..Y and C..D overlap iff (X <= D and C <= Y)
|
||||||
result = leValue(a.sons[0], b.sons[1]) and
|
result = leValue(a.sons[0], b.sons[1]) and
|
||||||
leValue(b.sons[0], a.sons[1])
|
leValue(b.sons[0], a.sons[1])
|
||||||
|
|
@ -98,13 +98,13 @@ proc ToTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
|
||||||
result.typ = settype
|
result.typ = settype
|
||||||
result.info = info
|
result.info = info
|
||||||
e = 0
|
e = 0
|
||||||
while e < high(s) * elemSize:
|
while e < len(s) * elemSize:
|
||||||
if bitSetIn(s, e):
|
if bitSetIn(s, e):
|
||||||
a = e
|
a = e
|
||||||
b = e
|
b = e
|
||||||
while true:
|
while true:
|
||||||
Inc(b)
|
Inc(b)
|
||||||
if (b > high(s) * elemSize) or not bitSetIn(s, b): break
|
if (b >= len(s) * elemSize) or not bitSetIn(s, b): break
|
||||||
Dec(b)
|
Dec(b)
|
||||||
if a == b:
|
if a == b:
|
||||||
addSon(result, newIntTypeNode(nkIntLit, a + first, elemType))
|
addSon(result, newIntTypeNode(nkIntLit, a + first, elemType))
|
||||||
|
|
|
||||||
2
compiler/nversion.nim
Executable file → Normal file
2
compiler/nversion.nim
Executable file → Normal file
|
|
@ -18,5 +18,5 @@ const
|
||||||
VersionPatch* = 1
|
VersionPatch* = 1
|
||||||
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
|
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
|
||||||
|
|
||||||
RodFileVersion* = "1210" # modify this if the rod-format changes!
|
RodFileVersion* = "1212" # modify this if the rod-format changes!
|
||||||
|
|
||||||
|
|
|
||||||
35
compiler/options.nim
Executable file → Normal file
35
compiler/options.nim
Executable file → Normal file
|
|
@ -68,7 +68,7 @@ type # please make sure we have under 32 options
|
||||||
TCommands* = enum # Nimrod's commands
|
TCommands* = enum # Nimrod's commands
|
||||||
# **keep binary compatible**
|
# **keep binary compatible**
|
||||||
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
||||||
cmdCompileToEcmaScript, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
|
cmdCompileToJS, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
|
||||||
cmdGenDepend, cmdDump,
|
cmdGenDepend, cmdDump,
|
||||||
cmdCheck, # semantic checking for whole project
|
cmdCheck, # semantic checking for whole project
|
||||||
cmdParse, # parse a single file (for debugging)
|
cmdParse, # parse a single file (for debugging)
|
||||||
|
|
@ -81,7 +81,7 @@ type # please make sure we have under 32 options
|
||||||
cmdRun # run the project via TCC backend
|
cmdRun # run the project via TCC backend
|
||||||
TStringSeq* = seq[string]
|
TStringSeq* = seq[string]
|
||||||
TGCMode* = enum # the selected GC
|
TGCMode* = enum # the selected GC
|
||||||
gcNone, gcBoehm, gcMarkAndSweep, gcRefc, gcV2
|
gcNone, gcBoehm, gcMarkAndSweep, gcRefc, gcV2, gcGenerational
|
||||||
|
|
||||||
const
|
const
|
||||||
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
|
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
|
||||||
|
|
@ -99,16 +99,26 @@ var
|
||||||
searchPaths*, lazyPaths*: TLinkedList
|
searchPaths*, lazyPaths*: TLinkedList
|
||||||
outFile*: string = ""
|
outFile*: string = ""
|
||||||
headerFile*: string = ""
|
headerFile*: string = ""
|
||||||
gVerbosity*: int # how verbose the compiler is
|
gVerbosity* = 1 # how verbose the compiler is
|
||||||
gNumberOfProcessors*: int # number of processors
|
gNumberOfProcessors*: int # number of processors
|
||||||
gWholeProject*: bool # for 'doc2': output any dependency
|
gWholeProject*: bool # for 'doc2': output any dependency
|
||||||
gEvalExpr* = "" # expression for idetools --eval
|
gEvalExpr* = "" # expression for idetools --eval
|
||||||
gLastCmdTime*: float # when caas is enabled, we measure each command
|
gLastCmdTime*: float # when caas is enabled, we measure each command
|
||||||
gListFullPaths*: bool
|
gListFullPaths*: bool
|
||||||
|
isServing*: bool = false
|
||||||
|
|
||||||
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
|
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
|
||||||
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
|
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
|
||||||
|
|
||||||
|
template compilationCachePresent*: expr =
|
||||||
|
{optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
|
||||||
|
|
||||||
|
template optPreserveOrigSource*: expr =
|
||||||
|
optEmbedOrigSrc in gGlobalOptions
|
||||||
|
|
||||||
|
template optPrintSurroundingSrc*: expr =
|
||||||
|
gVerbosity >= 2
|
||||||
|
|
||||||
const
|
const
|
||||||
genSubDir* = "nimcache"
|
genSubDir* = "nimcache"
|
||||||
NimExt* = "nim"
|
NimExt* = "nim"
|
||||||
|
|
@ -123,6 +133,7 @@ const
|
||||||
# additional configuration variables:
|
# additional configuration variables:
|
||||||
var
|
var
|
||||||
gConfigVars* = newStringTable(modeStyleInsensitive)
|
gConfigVars* = newStringTable(modeStyleInsensitive)
|
||||||
|
gDllOverrides = newStringtable(modeCaseInsensitive)
|
||||||
libpath* = ""
|
libpath* = ""
|
||||||
gProjectName* = "" # holds a name like 'nimrod'
|
gProjectName* = "" # holds a name like 'nimrod'
|
||||||
gProjectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
|
gProjectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
|
||||||
|
|
@ -255,6 +266,20 @@ proc libCandidates*(s: string, dest: var seq[string]) =
|
||||||
else:
|
else:
|
||||||
add(dest, s)
|
add(dest, s)
|
||||||
|
|
||||||
|
proc canonDynlibName(s: string): string =
|
||||||
|
let start = if s.startsWith("lib"): 3 else: 0
|
||||||
|
let ende = strutils.find(s, {'(', ')', '.'})
|
||||||
|
if ende >= 0:
|
||||||
|
result = s.substr(start, ende-1)
|
||||||
|
else:
|
||||||
|
result = s.substr(start)
|
||||||
|
|
||||||
|
proc inclDynlibOverride*(lib: string) =
|
||||||
|
gDllOverrides[lib.canonDynlibName] = "true"
|
||||||
|
|
||||||
|
proc isDynlibOverride*(lib: string): bool =
|
||||||
|
result = gDllOverrides.hasKey(lib.canonDynlibName)
|
||||||
|
|
||||||
proc binaryStrSearch*(x: openarray[string], y: string): int =
|
proc binaryStrSearch*(x: openarray[string], y: string): int =
|
||||||
var a = 0
|
var a = 0
|
||||||
var b = len(x) - 1
|
var b = len(x) - 1
|
||||||
|
|
|
||||||
|
|
@ -187,21 +187,24 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||||
else:
|
else:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
|
||||||
|
{tyVar, tyPtr, tyRef}:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
else:
|
else:
|
||||||
result = isAssignable(owner, n.sons[0])
|
result = isAssignable(owner, n.sons[0])
|
||||||
if result != arNone and sfDiscriminant in n.sons[1].sym.flags:
|
if result != arNone and sfDiscriminant in n.sons[1].sym.flags:
|
||||||
result = arDiscriminant
|
result = arDiscriminant
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
|
||||||
|
{tyVar, tyPtr, tyRef}:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
else:
|
else:
|
||||||
result = isAssignable(owner, n.sons[0])
|
result = isAssignable(owner, n.sons[0])
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||||
# Object and tuple conversions are still addressable, so we skip them
|
# Object and tuple conversions are still addressable, so we skip them
|
||||||
# XXX why is 'tyOpenArray' allowed here?
|
# XXX why is 'tyOpenArray' allowed here?
|
||||||
if skipTypes(n.typ, abstractPtrs).kind in {tyOpenArray, tyTuple, tyObject}:
|
if skipTypes(n.typ, abstractPtrs-{tyTypeDesc}).kind in
|
||||||
|
{tyOpenArray, tyTuple, tyObject}:
|
||||||
result = isAssignable(owner, n.sons[1])
|
result = isAssignable(owner, n.sons[1])
|
||||||
elif compareTypes(n.typ, n.sons[1].typ, dcEqIgnoreDistinct):
|
elif compareTypes(n.typ, n.sons[1].typ, dcEqIgnoreDistinct):
|
||||||
# types that are equal modulo distinction preserve l-value:
|
# types that are equal modulo distinction preserve l-value:
|
||||||
|
|
|
||||||
2
compiler/parsecfg.nim
Executable file → Normal file
2
compiler/parsecfg.nim
Executable file → Normal file
|
|
@ -12,7 +12,7 @@
|
||||||
# standard library.
|
# standard library.
|
||||||
|
|
||||||
import
|
import
|
||||||
llstream, nhashes, strutils, lexbase
|
llstream, nhashes, strutils, nimlexbase
|
||||||
|
|
||||||
type
|
type
|
||||||
TCfgEventKind* = enum
|
TCfgEventKind* = enum
|
||||||
|
|
|
||||||
53
compiler/parser.nim
Executable file → Normal file
53
compiler/parser.nim
Executable file → Normal file
|
|
@ -254,15 +254,21 @@ proc indexExprList(p: var TParser, first: PNode, k: TNodeKind,
|
||||||
optPar(p)
|
optPar(p)
|
||||||
eat(p, endToken)
|
eat(p, endToken)
|
||||||
|
|
||||||
proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode =
|
proc exprColonEqExpr(p: var TParser): PNode =
|
||||||
var a = parseExpr(p)
|
var a = parseExpr(p)
|
||||||
if p.tok.tokType == tok:
|
if p.tok.tokType == tkColon:
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(nkExprColonExpr, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
#optInd(p, result)
|
#optInd(p, result)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
addSon(result, parseExpr(p))
|
addSon(result, parseExpr(p))
|
||||||
else:
|
elif p.tok.tokType == tkEquals:
|
||||||
|
result = newNodeP(nkExprEqExpr, p)
|
||||||
|
getTok(p)
|
||||||
|
#optInd(p, result)
|
||||||
|
addSon(result, a)
|
||||||
|
addSon(result, parseExpr(p))
|
||||||
|
else:
|
||||||
result = a
|
result = a
|
||||||
|
|
||||||
proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
|
proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
|
||||||
|
|
@ -309,14 +315,13 @@ proc qualifiedIdentListAux(p: var TParser, endTok: TTokType, result: PNode) =
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
eat(p, endTok)
|
eat(p, endTok)
|
||||||
|
|
||||||
proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind,
|
proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) =
|
||||||
endTok, sepTok: TTokType, result: PNode) =
|
|
||||||
assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi})
|
assert(endTok in {tkCurlyRi, tkCurlyDotRi, tkBracketRi, tkParRi})
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof) and
|
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof) and
|
||||||
(p.tok.tokType != tkSad) and (p.tok.tokType != tkInd):
|
(p.tok.tokType != tkSad) and (p.tok.tokType != tkInd):
|
||||||
var a = exprColonEqExpr(p, elemKind, sepTok)
|
var a = exprColonEqExpr(p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
@ -324,10 +329,10 @@ proc exprColonEqExprListAux(p: var TParser, elemKind: TNodeKind,
|
||||||
optPar(p)
|
optPar(p)
|
||||||
eat(p, endTok)
|
eat(p, endTok)
|
||||||
|
|
||||||
proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind,
|
proc exprColonEqExprList(p: var TParser, kind: TNodeKind,
|
||||||
endTok, sepTok: TTokType): PNode =
|
endTok: TTokType): PNode =
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(kind, p)
|
||||||
exprColonEqExprListAux(p, elemKind, endTok, sepTok, result)
|
exprColonEqExprListAux(p, endTok, result)
|
||||||
|
|
||||||
proc setOrTableConstr(p: var TParser): PNode =
|
proc setOrTableConstr(p: var TParser): PNode =
|
||||||
result = newNodeP(nkCurly, p)
|
result = newNodeP(nkCurly, p)
|
||||||
|
|
@ -338,7 +343,7 @@ proc setOrTableConstr(p: var TParser): PNode =
|
||||||
result.kind = nkTableConstr
|
result.kind = nkTableConstr
|
||||||
else:
|
else:
|
||||||
while p.tok.tokType notin {tkCurlyRi, tkEof, tkSad, tkInd}:
|
while p.tok.tokType notin {tkCurlyRi, tkEof, tkSad, tkInd}:
|
||||||
var a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
|
var a = exprColonEqExpr(p)
|
||||||
if a.kind == nkExprColonExpr: result.kind = nkTableConstr
|
if a.kind == nkExprColonExpr: result.kind = nkTableConstr
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
|
|
@ -471,16 +476,15 @@ proc identOrLiteral(p: var TParser): PNode =
|
||||||
of tkNil:
|
of tkNil:
|
||||||
result = newNodeP(nkNilLit, p)
|
result = newNodeP(nkNilLit, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
of tkParLe:
|
of tkParLe:
|
||||||
# () constructor
|
# () constructor
|
||||||
result = exprColonEqExprList(p, nkPar, nkExprColonExpr, tkParRi, tkColon)
|
result = exprColonEqExprList(p, nkPar, tkParRi)
|
||||||
of tkCurlyLe:
|
of tkCurlyLe:
|
||||||
# {} constructor
|
# {} constructor
|
||||||
result = setOrTableConstr(p)
|
result = setOrTableConstr(p)
|
||||||
of tkBracketLe:
|
of tkBracketLe:
|
||||||
# [] constructor
|
# [] constructor
|
||||||
result = exprColonEqExprList(p, nkBracket, nkExprColonExpr, tkBracketRi,
|
result = exprColonEqExprList(p, nkBracket, tkBracketRi)
|
||||||
tkColon)
|
|
||||||
of tkCast:
|
of tkCast:
|
||||||
result = parseCast(p)
|
result = parseCast(p)
|
||||||
else:
|
else:
|
||||||
|
|
@ -496,8 +500,11 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
|
||||||
var a = result
|
var a = result
|
||||||
result = newNodeP(nkCall, p)
|
result = newNodeP(nkCall, p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
|
exprColonEqExprListAux(p, tkParRi, result)
|
||||||
parseDoBlocks(p, result)
|
if result.len > 1 and result.sons[1].kind == nkExprColonExpr:
|
||||||
|
result.kind = nkObjConstr
|
||||||
|
else:
|
||||||
|
parseDoBlocks(p, result)
|
||||||
of tkDo:
|
of tkDo:
|
||||||
var a = result
|
var a = result
|
||||||
result = newNodeP(nkCall, p)
|
result = newNodeP(nkCall, p)
|
||||||
|
|
@ -564,7 +571,7 @@ proc parsePragma(p: var TParser): PNode =
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and
|
while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and
|
||||||
(p.tok.tokType != tkEof) and (p.tok.tokType != tkSad):
|
(p.tok.tokType != tkEof) and (p.tok.tokType != tkSad):
|
||||||
var a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
|
var a = exprColonEqExpr(p)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType == tkComma:
|
if p.tok.tokType == tkComma:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
@ -739,7 +746,7 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
|
||||||
proc isExprStart(p: TParser): bool =
|
proc isExprStart(p: TParser): bool =
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf,
|
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf,
|
||||||
tkProc, tkIterator, tkBind,
|
tkProc, tkIterator, tkBind, tkAddr,
|
||||||
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
|
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
|
||||||
tkTuple, tkObject, tkType, tkWhen, tkCase, tkShared:
|
tkTuple, tkObject, tkType, tkWhen, tkCase, tkShared:
|
||||||
result = true
|
result = true
|
||||||
|
|
@ -1200,9 +1207,9 @@ proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
|
||||||
addSon(result, ast.emptyNode)
|
addSon(result, ast.emptyNode)
|
||||||
indAndComment(p, result) # XXX: document this in the grammar!
|
indAndComment(p, result) # XXX: document this in the grammar!
|
||||||
|
|
||||||
proc newCommentStmt(p: var TParser): PNode =
|
proc newCommentStmt(p: var TParser): PNode =
|
||||||
result = newNodeP(nkCommentStmt, p)
|
result = newNodeP(nkCommentStmt, p)
|
||||||
result.info.line = result.info.line - int16(1)
|
result.info.line = result.info.line - int16(1) - int16(p.tok.iNumber)
|
||||||
|
|
||||||
type
|
type
|
||||||
TDefParser = proc (p: var TParser): PNode {.nimcall.}
|
TDefParser = proc (p: var TParser): PNode {.nimcall.}
|
||||||
|
|
|
||||||
0
compiler/pas2nim/nimrod.cfg
Executable file → Normal file
0
compiler/pas2nim/nimrod.cfg
Executable file → Normal file
0
compiler/pas2nim/pas2nim.nim
Executable file → Normal file
0
compiler/pas2nim/pas2nim.nim
Executable file → Normal file
0
compiler/pas2nim/paslex.nim
Executable file → Normal file
0
compiler/pas2nim/paslex.nim
Executable file → Normal file
0
compiler/pas2nim/pasparse.nim
Executable file → Normal file
0
compiler/pas2nim/pasparse.nim
Executable file → Normal file
0
compiler/passaux.nim
Executable file → Normal file
0
compiler/passaux.nim
Executable file → Normal file
0
compiler/passes.nim
Executable file → Normal file
0
compiler/passes.nim
Executable file → Normal file
0
compiler/pbraces.nim
Executable file → Normal file
0
compiler/pbraces.nim
Executable file → Normal file
0
compiler/pendx.nim
Executable file → Normal file
0
compiler/pendx.nim
Executable file → Normal file
8
compiler/platform.nim
Executable file → Normal file
8
compiler/platform.nim
Executable file → Normal file
|
|
@ -21,7 +21,7 @@ type
|
||||||
# conditionals to condsyms (end of module).
|
# conditionals to condsyms (end of module).
|
||||||
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
||||||
osIrix, osNetbsd, osFreebsd, osOpenbsd, osAix, osPalmos, osQnx, osAmiga,
|
osIrix, osNetbsd, osFreebsd, osOpenbsd, osAix, osPalmos, osQnx, osAmiga,
|
||||||
osAtari, osNetware, osMacos, osMacosx, osHaiku, osEcmaScript, osNimrodVM,
|
osAtari, osNetware, osMacos, osMacosx, osHaiku, osJS, osNimrodVM,
|
||||||
osStandalone
|
osStandalone
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -136,7 +136,7 @@ const
|
||||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||||
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
|
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
|
||||||
(name: "EcmaScript", parDir: "..",
|
(name: "JS", parDir: "..",
|
||||||
dllFrmt: "lib$1.so", altDirSep: "/",
|
dllFrmt: "lib$1.so", altDirSep: "/",
|
||||||
objExt: ".o", newLine: "\x0A",
|
objExt: ".o", newLine: "\x0A",
|
||||||
pathSep: ":", dirSep: "/",
|
pathSep: ":", dirSep: "/",
|
||||||
|
|
@ -155,7 +155,7 @@ type
|
||||||
# alias conditionals to condsyms (end of module).
|
# alias conditionals to condsyms (end of module).
|
||||||
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
|
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
|
||||||
cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuArm,
|
cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuArm,
|
||||||
cpuEcmaScript, cpuNimrodVM, cpuAVR
|
cpuJS, cpuNimrodVM, cpuAVR
|
||||||
|
|
||||||
type
|
type
|
||||||
TEndian* = enum
|
TEndian* = enum
|
||||||
|
|
@ -177,7 +177,7 @@ const
|
||||||
(name: "amd64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
(name: "amd64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||||
(name: "mips", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
(name: "mips", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
||||||
(name: "arm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
(name: "arm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||||
(name: "ecmascript", intSize: 32, endian: bigEndian,floatSize: 64,bit: 32),
|
(name: "js", intSize: 32, endian: bigEndian,floatSize: 64,bit: 32),
|
||||||
(name: "nimrodvm", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
(name: "nimrodvm", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
||||||
(name: "avr", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16)]
|
(name: "avr", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16)]
|
||||||
|
|
||||||
|
|
|
||||||
7
compiler/pragmas.nim
Executable file → Normal file
7
compiler/pragmas.nim
Executable file → Normal file
|
|
@ -202,6 +202,8 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
|
||||||
result = newLib(kind)
|
result = newLib(kind)
|
||||||
result.path = path
|
result.path = path
|
||||||
Append(c.libs, result)
|
Append(c.libs, result)
|
||||||
|
if path.kind in {nkStrLit..nkTripleStrLit}:
|
||||||
|
result.isOverriden = options.isDynLibOverride(path.strVal)
|
||||||
|
|
||||||
proc expectDynlibNode(c: PContext, n: PNode): PNode =
|
proc expectDynlibNode(c: PContext, n: PNode): PNode =
|
||||||
if n.kind != nkExprColonExpr:
|
if n.kind != nkExprColonExpr:
|
||||||
|
|
@ -225,8 +227,9 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
||||||
else:
|
else:
|
||||||
if n.kind == nkExprColonExpr:
|
if n.kind == nkExprColonExpr:
|
||||||
var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
|
var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
|
||||||
addToLib(lib, sym)
|
if not lib.isOverriden:
|
||||||
incl(sym.loc.flags, lfDynamicLib)
|
addToLib(lib, sym)
|
||||||
|
incl(sym.loc.flags, lfDynamicLib)
|
||||||
else:
|
else:
|
||||||
incl(sym.loc.flags, lfExportLib)
|
incl(sym.loc.flags, lfExportLib)
|
||||||
# since we'll be loading the dynlib symbols dynamically, we must use
|
# since we'll be loading the dynlib symbols dynamically, we must use
|
||||||
|
|
|
||||||
59
compiler/procfind.nim
Executable file → Normal file
59
compiler/procfind.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -10,28 +10,24 @@
|
||||||
# This module implements the searching for procs and iterators.
|
# This module implements the searching for procs and iterators.
|
||||||
# This is needed for proper handling of forward declarations.
|
# This is needed for proper handling of forward declarations.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, msgs, semdata, types, trees
|
ast, astalgo, msgs, semdata, types, trees
|
||||||
|
|
||||||
proc equalGenericParams(procA, procB: PNode): bool =
|
proc equalGenericParams(procA, procB: PNode): bool =
|
||||||
var a, b: PSym
|
if sonsLen(procA) != sonsLen(procB): return
|
||||||
result = procA == procB
|
for i in countup(0, sonsLen(procA) - 1):
|
||||||
if result: return
|
if procA.sons[i].kind != nkSym:
|
||||||
if (procA == nil) or (procB == nil): return
|
|
||||||
if sonsLen(procA) != sonsLen(procB): return
|
|
||||||
for i in countup(0, sonsLen(procA) - 1):
|
|
||||||
if procA.sons[i].kind != nkSym:
|
|
||||||
InternalError(procA.info, "equalGenericParams")
|
InternalError(procA.info, "equalGenericParams")
|
||||||
return
|
return
|
||||||
if procB.sons[i].kind != nkSym:
|
if procB.sons[i].kind != nkSym:
|
||||||
InternalError(procB.info, "equalGenericParams")
|
InternalError(procB.info, "equalGenericParams")
|
||||||
return
|
return
|
||||||
a = procA.sons[i].sym
|
let a = procA.sons[i].sym
|
||||||
b = procB.sons[i].sym
|
let b = procB.sons[i].sym
|
||||||
if (a.name.id != b.name.id) or
|
if a.name.id != b.name.id or
|
||||||
not sameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}): return
|
not sameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}): return
|
||||||
if (a.ast != nil) and (b.ast != nil):
|
if a.ast != nil and b.ast != nil:
|
||||||
if not ExprStructuralEquivalent(a.ast, b.ast): return
|
if not ExprStructuralEquivalent(a.ast, b.ast): return
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym =
|
proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym =
|
||||||
|
|
@ -39,19 +35,32 @@ proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym =
|
||||||
# the same the sym in the symbol table is returned, else nil.
|
# the same the sym in the symbol table is returned, else nil.
|
||||||
var it: TIdentIter
|
var it: TIdentIter
|
||||||
result = initIdentIter(it, c.tab.stack[tos], fn.Name)
|
result = initIdentIter(it, c.tab.stack[tos], fn.Name)
|
||||||
while result != nil:
|
if isGenericRoutine(fn):
|
||||||
if (result.Kind == fn.kind):
|
# we simply check the AST; this is imprecise but nearly the best what
|
||||||
if equalGenericParams(result.ast.sons[genericParamsPos],
|
# can be done; this doesn't work either though as type constraints are
|
||||||
fn.ast.sons[genericParamsPos]):
|
# not kept in the AST ..
|
||||||
|
while result != nil:
|
||||||
|
if result.Kind == fn.kind and isGenericRoutine(result):
|
||||||
|
let genR = result.ast.sons[genericParamsPos]
|
||||||
|
let genF = fn.ast.sons[genericParamsPos]
|
||||||
|
if ExprStructuralEquivalent(genR, genF) and
|
||||||
|
ExprStructuralEquivalent(result.ast.sons[paramsPos],
|
||||||
|
fn.ast.sons[paramsPos]) and
|
||||||
|
equalGenericParams(genR, genF):
|
||||||
|
return
|
||||||
|
result = NextIdentIter(it, c.tab.stack[tos])
|
||||||
|
else:
|
||||||
|
while result != nil:
|
||||||
|
if result.Kind == fn.kind and not isGenericRoutine(result):
|
||||||
case equalParams(result.typ.n, fn.typ.n)
|
case equalParams(result.typ.n, fn.typ.n)
|
||||||
of paramsEqual:
|
of paramsEqual:
|
||||||
return
|
return
|
||||||
of paramsIncompatible:
|
of paramsIncompatible:
|
||||||
LocalError(fn.info, errNotOverloadable, fn.name.s)
|
LocalError(fn.info, errNotOverloadable, fn.name.s)
|
||||||
return
|
return
|
||||||
of paramsNotEqual:
|
of paramsNotEqual:
|
||||||
nil
|
nil
|
||||||
result = NextIdentIter(it, c.tab.stack[tos])
|
result = NextIdentIter(it, c.tab.stack[tos])
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
proc paramsFitBorrow(child, parent: PNode): bool =
|
proc paramsFitBorrow(child, parent: PNode): bool =
|
||||||
|
|
|
||||||
0
compiler/readme.txt
Executable file → Normal file
0
compiler/readme.txt
Executable file → Normal file
4
compiler/renderer.nim
Executable file → Normal file
4
compiler/renderer.nim
Executable file → Normal file
|
|
@ -367,7 +367,7 @@ proc lsub(n: PNode): int =
|
||||||
else: result = len(atom(n))
|
else: result = len(atom(n))
|
||||||
of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
|
of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
|
||||||
result = len(atom(n))
|
result = len(atom(n))
|
||||||
of nkCall, nkBracketExpr, nkCurlyExpr, nkConv, nkPattern:
|
of nkCall, nkBracketExpr, nkCurlyExpr, nkConv, nkPattern, nkObjConstr:
|
||||||
result = lsub(n.sons[0]) + lcomma(n, 1) + 2
|
result = lsub(n.sons[0]) + lcomma(n, 1) + 2
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
|
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
|
||||||
of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()")
|
of nkCast: result = lsub(n.sons[0]) + lsub(n.sons[1]) + len("cast[]()")
|
||||||
|
|
@ -779,7 +779,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
of nkRStrLit: put(g, tkRStrLit, atom(n))
|
of nkRStrLit: put(g, tkRStrLit, atom(n))
|
||||||
of nkCharLit: put(g, tkCharLit, atom(n))
|
of nkCharLit: put(g, tkCharLit, atom(n))
|
||||||
of nkNilLit: put(g, tkNil, atom(n)) # complex expressions
|
of nkNilLit: put(g, tkNil, atom(n)) # complex expressions
|
||||||
of nkCall, nkConv, nkDotCall, nkPattern:
|
of nkCall, nkConv, nkDotCall, nkPattern, nkObjConstr:
|
||||||
if sonsLen(n) >= 1: gsub(g, n.sons[0])
|
if sonsLen(n) >= 1: gsub(g, n.sons[0])
|
||||||
put(g, tkParLe, "(")
|
put(g, tkParLe, "(")
|
||||||
gcomma(g, n, 1)
|
gcomma(g, n, 1)
|
||||||
|
|
|
||||||
323
compiler/rodread.nim
Executable file → Normal file
323
compiler/rodread.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -127,7 +127,7 @@ type
|
||||||
options: TOptions
|
options: TOptions
|
||||||
reason: TReasonForRecompile
|
reason: TReasonForRecompile
|
||||||
modDeps: seq[int32]
|
modDeps: seq[int32]
|
||||||
files: TStringSeq
|
files: seq[int32]
|
||||||
dataIdx: int # offset of start of data section
|
dataIdx: int # offset of start of data section
|
||||||
convertersIdx: int # offset of start of converters section
|
convertersIdx: int # offset of start of converters section
|
||||||
initIdx, interfIdx, compilerProcsIdx, methodsIdx: int
|
initIdx, interfIdx, compilerProcsIdx, methodsIdx: int
|
||||||
|
|
@ -140,6 +140,7 @@ type
|
||||||
memfile: TMemFile # unfortunately there is no point in time where we
|
memfile: TMemFile # unfortunately there is no point in time where we
|
||||||
# can close this! XXX
|
# can close this! XXX
|
||||||
methods*: TSymSeq
|
methods*: TSymSeq
|
||||||
|
inViewMode: bool
|
||||||
|
|
||||||
PRodReader* = ref TRodReader
|
PRodReader* = ref TRodReader
|
||||||
|
|
||||||
|
|
@ -367,12 +368,12 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
id = decodeVInt(r.s, r.pos)
|
id = decodeVInt(r.s, r.pos)
|
||||||
setId(id)
|
setId(id)
|
||||||
else:
|
else:
|
||||||
InternalError(info, "decodeSym: no id")
|
InternalError(info, "decodeSym: no id")
|
||||||
if r.s[r.pos] == '&':
|
if r.s[r.pos] == '&':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
ident = getIdent(decodeStr(r.s, r.pos))
|
ident = getIdent(decodeStr(r.s, r.pos))
|
||||||
else:
|
else:
|
||||||
InternalError(info, "decodeSym: no ident")
|
InternalError(info, "decodeSym: no ident")
|
||||||
#echo "decoding: {", ident.s
|
#echo "decoding: {", ident.s
|
||||||
result = PSym(IdTableGet(r.syms, id))
|
result = PSym(IdTableGet(r.syms, id))
|
||||||
|
|
@ -381,8 +382,14 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||||
result.id = id
|
result.id = id
|
||||||
IdTablePut(r.syms, result, result)
|
IdTablePut(r.syms, result, result)
|
||||||
if debugIds: registerID(result)
|
if debugIds: registerID(result)
|
||||||
elif (result.id != id):
|
elif result.id != id:
|
||||||
InternalError(info, "decodeSym: wrong id")
|
InternalError(info, "decodeSym: wrong id")
|
||||||
|
elif result.kind != skStub and not r.inViewMode:
|
||||||
|
# we already loaded the symbol
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
reset(result[])
|
||||||
|
result.id = id
|
||||||
result.kind = k
|
result.kind = k
|
||||||
result.name = ident # read the rest of the symbol description:
|
result.name = ident # read the rest of the symbol description:
|
||||||
if r.s[r.pos] == '^':
|
if r.s[r.pos] == '^':
|
||||||
|
|
@ -495,7 +502,7 @@ proc processCompilerProcs(r: PRodReader, module: PSym) =
|
||||||
IdTablePut(r.syms, s, s)
|
IdTablePut(r.syms, s, s)
|
||||||
StrTableAdd(rodCompilerProcs, s)
|
StrTableAdd(rodCompilerProcs, s)
|
||||||
|
|
||||||
proc processIndex(r: PRodReader, idx: var TIndex) =
|
proc processIndex(r: PRodReader; idx: var TIndex; outf: TFile = nil) =
|
||||||
var key, val, tmp: int
|
var key, val, tmp: int
|
||||||
inc(r.pos, 2) # skip "(\10"
|
inc(r.pos, 2) # skip "(\10"
|
||||||
inc(r.line)
|
inc(r.line)
|
||||||
|
|
@ -505,10 +512,11 @@ proc processIndex(r: PRodReader, idx: var TIndex) =
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
key = idx.lastIdxKey + tmp
|
key = idx.lastIdxKey + tmp
|
||||||
val = decodeVInt(r.s, r.pos) + idx.lastIdxVal
|
val = decodeVInt(r.s, r.pos) + idx.lastIdxVal
|
||||||
else:
|
else:
|
||||||
key = idx.lastIdxKey + 1
|
key = idx.lastIdxKey + 1
|
||||||
val = tmp + idx.lastIdxVal
|
val = tmp + idx.lastIdxVal
|
||||||
IITablePut(idx.tab, key, val)
|
IITablePut(idx.tab, key, val)
|
||||||
|
if not outf.isNil: outf.write(key, " ", val, "\n")
|
||||||
idx.lastIdxKey = key
|
idx.lastIdxKey = key
|
||||||
idx.lastIdxVal = val
|
idx.lastIdxVal = val
|
||||||
setID(key) # ensure that this id will not be used
|
setID(key) # ensure that this id will not be used
|
||||||
|
|
@ -523,7 +531,7 @@ proc cmdChangeTriggersRecompilation(old, new: TCommands): bool =
|
||||||
# new command forces us to consider it here :-)
|
# new command forces us to consider it here :-)
|
||||||
case old
|
case old
|
||||||
of cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
of cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
||||||
cmdCompileToEcmaScript, cmdCompileToLLVM:
|
cmdCompileToJS, cmdCompileToLLVM:
|
||||||
if new in {cmdDoc, cmdCheck, cmdIdeTools, cmdPretty, cmdDef,
|
if new in {cmdDoc, cmdCheck, cmdIdeTools, cmdPretty, cmdDef,
|
||||||
cmdInteractive}:
|
cmdInteractive}:
|
||||||
return false
|
return false
|
||||||
|
|
@ -576,9 +584,10 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||||
inc(r.pos, 2) # skip "(\10"
|
inc(r.pos, 2) # skip "(\10"
|
||||||
inc(r.line)
|
inc(r.line)
|
||||||
while r.s[r.pos] != ')':
|
while r.s[r.pos] != ')':
|
||||||
var relativePath = decodeStr(r.s, r.pos)
|
let relativePath = decodeStr(r.s, r.pos)
|
||||||
var resolvedPath = relativePath.findModule
|
let resolvedPath = relativePath.findModule
|
||||||
r.files.add(if resolvedPath.len > 0: resolvedPath else: relativePath)
|
let finalPath = if resolvedPath.len > 0: resolvedPath else: relativePath
|
||||||
|
r.files.add(finalPath.fileInfoIdx)
|
||||||
inc(r.pos) # skip #10
|
inc(r.pos) # skip #10
|
||||||
inc(r.line)
|
inc(r.line)
|
||||||
if r.s[r.pos] == ')': inc(r.pos)
|
if r.s[r.pos] == ')': inc(r.pos)
|
||||||
|
|
@ -586,7 +595,7 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||||
inc(r.pos, 2) # skip "(\10"
|
inc(r.pos, 2) # skip "(\10"
|
||||||
inc(r.line)
|
inc(r.line)
|
||||||
while r.s[r.pos] != ')':
|
while r.s[r.pos] != ')':
|
||||||
w = r.files[decodeVInt(r.s, r.pos)]
|
w = r.files[decodeVInt(r.s, r.pos)].toFullPath
|
||||||
inc(r.pos) # skip ' '
|
inc(r.pos) # skip ' '
|
||||||
inclCrc = decodeVInt(r.s, r.pos)
|
inclCrc = decodeVInt(r.s, r.pos)
|
||||||
if r.reason == rrNone:
|
if r.reason == rrNone:
|
||||||
|
|
@ -598,8 +607,8 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||||
if r.s[r.pos] == ')': inc(r.pos)
|
if r.s[r.pos] == ')': inc(r.pos)
|
||||||
of "DEPS":
|
of "DEPS":
|
||||||
inc(r.pos) # skip ':'
|
inc(r.pos) # skip ':'
|
||||||
while r.s[r.pos] > '\x0A':
|
while r.s[r.pos] > '\x0A':
|
||||||
r.modDeps.add int32(decodeVInt(r.s, r.pos))
|
r.modDeps.add(r.files[int32(decodeVInt(r.s, r.pos))])
|
||||||
if r.s[r.pos] == ' ': inc(r.pos)
|
if r.s[r.pos] == ' ': inc(r.pos)
|
||||||
of "INTERF":
|
of "INTERF":
|
||||||
r.interfIdx = r.pos + 2
|
r.interfIdx = r.pos + 2
|
||||||
|
|
@ -670,11 +679,9 @@ proc newRodReader(modfilename: string, crc: TCrc32,
|
||||||
add(version, r.s[r.pos])
|
add(version, r.s[r.pos])
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
if r.s[r.pos] == '\x0A': inc(r.pos)
|
if r.s[r.pos] == '\x0A': inc(r.pos)
|
||||||
if version == RodFileVersion:
|
if version != RodFileVersion:
|
||||||
# since ROD files are only for caching, no backwards compatibility is
|
# since ROD files are only for caching, no backwards compatibility is
|
||||||
# needed
|
# needed
|
||||||
processRodFile(r, crc)
|
|
||||||
else:
|
|
||||||
result = nil
|
result = nil
|
||||||
else:
|
else:
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -719,8 +726,14 @@ proc findSomeWhere(id: int) =
|
||||||
echo "found id ", id, " in ", gMods[i].filename
|
echo "found id ", id, " in ", gMods[i].filename
|
||||||
|
|
||||||
proc getReader(moduleId: int): PRodReader =
|
proc getReader(moduleId: int): PRodReader =
|
||||||
InternalAssert moduleId >= 0 and moduleId < gMods.len
|
# we can't index 'gMods' here as it's indexed by a *file index* which is not
|
||||||
result = gMods[moduleId].rd
|
# the module ID! We could introduce a mapping ID->PRodReader but I'll leave
|
||||||
|
# this for later versions if benchmarking shows the linear search causes
|
||||||
|
# problems:
|
||||||
|
for i in 0 .. <gMods.len:
|
||||||
|
result = gMods[i].rd
|
||||||
|
if result != nil and result.moduleId == moduleId: return result
|
||||||
|
return nil
|
||||||
|
|
||||||
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
|
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
|
||||||
result = PSym(IdTableGet(r.syms, id))
|
result = PSym(IdTableGet(r.syms, id))
|
||||||
|
|
@ -810,6 +823,7 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
|
||||||
if r == nil:
|
if r == nil:
|
||||||
result = (if ExistsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist)
|
result = (if ExistsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist)
|
||||||
else:
|
else:
|
||||||
|
processRodFile(r, crc)
|
||||||
result = r.reason
|
result = r.reason
|
||||||
if result == rrNone:
|
if result == rrNone:
|
||||||
# check modules it depends on
|
# check modules it depends on
|
||||||
|
|
@ -818,10 +832,10 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
|
||||||
# this, since results are cached.
|
# this, since results are cached.
|
||||||
var res = checkDep(SystemFileIdx)
|
var res = checkDep(SystemFileIdx)
|
||||||
if res != rrNone: result = rrModDeps
|
if res != rrNone: result = rrModDeps
|
||||||
for i in countup(0, high(r.modDeps)):
|
for i in countup(0, high(r.modDeps)):
|
||||||
res = checkDep(r.modDeps[i])
|
res = checkDep(r.modDeps[i])
|
||||||
if res != rrNone:
|
if res != rrNone:
|
||||||
result = rrModDeps
|
result = rrModDeps
|
||||||
# we cannot break here, because of side-effects of `checkDep`
|
# we cannot break here, because of side-effects of `checkDep`
|
||||||
if result != rrNone and gVerbosity > 0:
|
if result != rrNone and gVerbosity > 0:
|
||||||
rawMessage(hintProcessing, reasonToFrmt[result] % filename)
|
rawMessage(hintProcessing, reasonToFrmt[result] % filename)
|
||||||
|
|
@ -859,7 +873,9 @@ proc rawLoadStub(s: PSym) =
|
||||||
var d = IITableGet(rd.index.tab, s.id)
|
var d = IITableGet(rd.index.tab, s.id)
|
||||||
if d == invalidKey: InternalError("loadStub: invalid key")
|
if d == invalidKey: InternalError("loadStub: invalid key")
|
||||||
var rs = decodeSymSafePos(rd, d, UnknownLineInfo())
|
var rs = decodeSymSafePos(rd, d, UnknownLineInfo())
|
||||||
if rs != s:
|
if rs != s:
|
||||||
|
#echo "rs: ", toHex(cast[int](rs.position), int.sizeof * 2),
|
||||||
|
# "\ns: ", toHex(cast[int](s.position), int.sizeof * 2)
|
||||||
InternalError(rs.info, "loadStub: wrong symbol")
|
InternalError(rs.info, "loadStub: wrong symbol")
|
||||||
elif rs.id != theId:
|
elif rs.id != theId:
|
||||||
InternalError(rs.info, "loadStub: wrong ID")
|
InternalError(rs.info, "loadStub: wrong ID")
|
||||||
|
|
@ -894,3 +910,264 @@ proc getBody*(s: PSym): PNode =
|
||||||
|
|
||||||
InitIdTable(gTypeTable)
|
InitIdTable(gTypeTable)
|
||||||
InitStrTable(rodCompilerProcs)
|
InitStrTable(rodCompilerProcs)
|
||||||
|
|
||||||
|
# viewer:
|
||||||
|
proc writeNode(f: TFile; n: PNode) =
|
||||||
|
f.write("(")
|
||||||
|
if n != nil:
|
||||||
|
f.write($n.kind)
|
||||||
|
if n.typ != nil:
|
||||||
|
f.write('^')
|
||||||
|
f.write(n.typ.id)
|
||||||
|
case n.kind
|
||||||
|
of nkCharLit..nkInt64Lit:
|
||||||
|
if n.intVal != 0:
|
||||||
|
f.write('!')
|
||||||
|
f.write(n.intVal)
|
||||||
|
of nkFloatLit..nkFloat64Lit:
|
||||||
|
if n.floatVal != 0.0:
|
||||||
|
f.write('!')
|
||||||
|
f.write($n.floatVal)
|
||||||
|
of nkStrLit..nkTripleStrLit:
|
||||||
|
if n.strVal != "":
|
||||||
|
f.write('!')
|
||||||
|
f.write(n.strVal.escape)
|
||||||
|
of nkIdent:
|
||||||
|
f.write('!')
|
||||||
|
f.write(n.ident.s)
|
||||||
|
of nkSym:
|
||||||
|
f.write('!')
|
||||||
|
f.write(n.sym.id)
|
||||||
|
else:
|
||||||
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
writeNode(f, n.sons[i])
|
||||||
|
f.write(")")
|
||||||
|
|
||||||
|
proc writeSym(f: TFile; s: PSym) =
|
||||||
|
if s == nil:
|
||||||
|
f.write("{}\n")
|
||||||
|
return
|
||||||
|
f.write("{")
|
||||||
|
f.write($s.kind)
|
||||||
|
f.write('+')
|
||||||
|
f.write(s.id)
|
||||||
|
f.write('&')
|
||||||
|
f.write(s.name.s)
|
||||||
|
if s.typ != nil:
|
||||||
|
f.write('^')
|
||||||
|
f.write(s.typ.id)
|
||||||
|
if s.owner != nil:
|
||||||
|
f.write('*')
|
||||||
|
f.write(s.owner.id)
|
||||||
|
if s.flags != {}:
|
||||||
|
f.write('$')
|
||||||
|
f.write($s.flags)
|
||||||
|
if s.magic != mNone:
|
||||||
|
f.write('@')
|
||||||
|
f.write($s.magic)
|
||||||
|
if s.options != gOptions:
|
||||||
|
f.write('!')
|
||||||
|
f.write($s.options)
|
||||||
|
if s.position != 0:
|
||||||
|
f.write('%')
|
||||||
|
f.write($s.position)
|
||||||
|
if s.offset != -1:
|
||||||
|
f.write('`')
|
||||||
|
f.write($s.offset)
|
||||||
|
if s.constraint != nil:
|
||||||
|
f.write('#')
|
||||||
|
f.writeNode(s.constraint)
|
||||||
|
if s.ast != nil:
|
||||||
|
f.writeNode(s.ast)
|
||||||
|
f.write("}\n")
|
||||||
|
|
||||||
|
proc writeType(f: TFile; t: PType) =
|
||||||
|
if t == nil:
|
||||||
|
f.write("[]\n")
|
||||||
|
return
|
||||||
|
f.write('[')
|
||||||
|
f.write($t.kind)
|
||||||
|
f.write('+')
|
||||||
|
f.write($t.id)
|
||||||
|
if t.n != nil:
|
||||||
|
f.writeNode(t.n)
|
||||||
|
if t.flags != {}:
|
||||||
|
f.write('$')
|
||||||
|
f.write($t.flags)
|
||||||
|
if t.callConv != low(t.callConv):
|
||||||
|
f.write('?')
|
||||||
|
f.write($t.callConv)
|
||||||
|
if t.owner != nil:
|
||||||
|
f.write('*')
|
||||||
|
f.write($t.owner.id)
|
||||||
|
if t.sym != nil:
|
||||||
|
f.write('&')
|
||||||
|
f.write(t.sym.id)
|
||||||
|
if t.size != -1:
|
||||||
|
f.write('/')
|
||||||
|
f.write($t.size)
|
||||||
|
if t.align != 2:
|
||||||
|
f.write('=')
|
||||||
|
f.write($t.align)
|
||||||
|
if t.containerID != 0:
|
||||||
|
f.write('@')
|
||||||
|
f.write($t.containerID)
|
||||||
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
|
if t.sons[i] == nil:
|
||||||
|
f.write("^()")
|
||||||
|
else:
|
||||||
|
f.write('^')
|
||||||
|
f.write($t.sons[i].id)
|
||||||
|
f.write("]\n")
|
||||||
|
|
||||||
|
proc viewFile(rodfile: string) =
|
||||||
|
var r = newRodReader(rodfile, 0, 0)
|
||||||
|
if r == nil:
|
||||||
|
rawMessage(errGenerated, "cannot open file (or maybe wrong version):" &
|
||||||
|
rodfile)
|
||||||
|
return
|
||||||
|
r.inViewMode = true
|
||||||
|
var outf = system.open(rodfile.changeFileExt(".rod.txt"), fmWrite)
|
||||||
|
while r.s[r.pos] != '\0':
|
||||||
|
let section = rdWord(r)
|
||||||
|
case section
|
||||||
|
of "CRC":
|
||||||
|
inc(r.pos) # skip ':'
|
||||||
|
outf.writeln("CRC:", $decodeVInt(r.s, r.pos))
|
||||||
|
of "ID":
|
||||||
|
inc(r.pos) # skip ':'
|
||||||
|
r.moduleID = decodeVInt(r.s, r.pos)
|
||||||
|
setID(r.moduleID)
|
||||||
|
outf.writeln("ID:", $r.moduleID)
|
||||||
|
of "OPTIONS":
|
||||||
|
inc(r.pos) # skip ':'
|
||||||
|
r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos)))
|
||||||
|
outf.writeln("OPTIONS:", $r.options)
|
||||||
|
of "GOPTIONS":
|
||||||
|
inc(r.pos) # skip ':'
|
||||||
|
let dep = cast[TGlobalOptions](int32(decodeVInt(r.s, r.pos)))
|
||||||
|
outf.writeln("GOPTIONS:", $dep)
|
||||||
|
of "CMD":
|
||||||
|
inc(r.pos) # skip ':'
|
||||||
|
let dep = cast[TCommands](int32(decodeVInt(r.s, r.pos)))
|
||||||
|
outf.writeln("CMD:", $dep)
|
||||||
|
of "DEFINES":
|
||||||
|
inc(r.pos) # skip ':'
|
||||||
|
var d = 0
|
||||||
|
outf.write("DEFINES:")
|
||||||
|
while r.s[r.pos] > '\x0A':
|
||||||
|
let w = decodeStr(r.s, r.pos)
|
||||||
|
inc(d)
|
||||||
|
outf.write(" ", w)
|
||||||
|
if r.s[r.pos] == ' ': inc(r.pos)
|
||||||
|
outf.write("\n")
|
||||||
|
of "FILES":
|
||||||
|
inc(r.pos, 2) # skip "(\10"
|
||||||
|
inc(r.line)
|
||||||
|
outf.write("FILES(\n")
|
||||||
|
while r.s[r.pos] != ')':
|
||||||
|
let relativePath = decodeStr(r.s, r.pos)
|
||||||
|
let resolvedPath = relativePath.findModule
|
||||||
|
let finalPath = if resolvedPath.len > 0: resolvedPath else: relativePath
|
||||||
|
r.files.add(finalPath.fileInfoIdx)
|
||||||
|
inc(r.pos) # skip #10
|
||||||
|
inc(r.line)
|
||||||
|
outf.writeln finalPath
|
||||||
|
if r.s[r.pos] == ')': inc(r.pos)
|
||||||
|
outf.write(")\n")
|
||||||
|
of "INCLUDES":
|
||||||
|
inc(r.pos, 2) # skip "(\10"
|
||||||
|
inc(r.line)
|
||||||
|
outf.write("INCLUDES(\n")
|
||||||
|
while r.s[r.pos] != ')':
|
||||||
|
let w = r.files[decodeVInt(r.s, r.pos)]
|
||||||
|
inc(r.pos) # skip ' '
|
||||||
|
let inclCrc = decodeVInt(r.s, r.pos)
|
||||||
|
if r.s[r.pos] == '\x0A':
|
||||||
|
inc(r.pos)
|
||||||
|
inc(r.line)
|
||||||
|
outf.write(w, " ", inclCrc, "\n")
|
||||||
|
if r.s[r.pos] == ')': inc(r.pos)
|
||||||
|
outf.write(")\n")
|
||||||
|
of "DEPS":
|
||||||
|
inc(r.pos) # skip ':'
|
||||||
|
outf.write("DEPS:")
|
||||||
|
while r.s[r.pos] > '\x0A':
|
||||||
|
let v = int32(decodeVInt(r.s, r.pos))
|
||||||
|
r.modDeps.add(r.files[v])
|
||||||
|
if r.s[r.pos] == ' ': inc(r.pos)
|
||||||
|
outf.write(" ", r.files[v])
|
||||||
|
outf.write("\n")
|
||||||
|
of "INTERF", "COMPILERPROCS":
|
||||||
|
inc r.pos, 2
|
||||||
|
if section == "INTERF": r.interfIdx = r.pos
|
||||||
|
else: r.compilerProcsIdx = r.pos
|
||||||
|
outf.write(section, "(\n")
|
||||||
|
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
||||||
|
let w = decodeStr(r.s, r.pos)
|
||||||
|
inc(r.pos)
|
||||||
|
let key = decodeVInt(r.s, r.pos)
|
||||||
|
inc(r.pos) # #10
|
||||||
|
outf.write(w, " ", key, "\n")
|
||||||
|
if r.s[r.pos] == ')': inc r.pos
|
||||||
|
outf.write(")\n")
|
||||||
|
of "INDEX":
|
||||||
|
outf.write(section, "(\n")
|
||||||
|
processIndex(r, r.index, outf)
|
||||||
|
outf.write(")\n")
|
||||||
|
of "IMPORTS":
|
||||||
|
outf.write(section, "(\n")
|
||||||
|
processIndex(r, r.imports, outf)
|
||||||
|
outf.write(")\n")
|
||||||
|
of "CONVERTERS", "METHODS":
|
||||||
|
inc r.pos
|
||||||
|
if section == "METHODS": r.methodsIdx = r.pos
|
||||||
|
else: r.convertersIdx = r.pos
|
||||||
|
outf.write(section, ":")
|
||||||
|
while r.s[r.pos] > '\x0A':
|
||||||
|
let d = decodeVInt(r.s, r.pos)
|
||||||
|
outf.write(" ", $d)
|
||||||
|
if r.s[r.pos] == ' ': inc(r.pos)
|
||||||
|
outf.write("\n")
|
||||||
|
of "DATA":
|
||||||
|
inc(r.pos, 2)
|
||||||
|
r.dataIdx = r.pos
|
||||||
|
outf.write("DATA(\n")
|
||||||
|
while r.s[r.pos] != ')':
|
||||||
|
if r.s[r.pos] == '(':
|
||||||
|
outf.writeNode decodeNode(r, UnknownLineInfo())
|
||||||
|
outf.write("\n")
|
||||||
|
elif r.s[r.pos] == '[':
|
||||||
|
outf.writeType decodeType(r, UnknownLineInfo())
|
||||||
|
else:
|
||||||
|
outf.writeSym decodeSym(r, UnknownLineInfo())
|
||||||
|
if r.s[r.pos] == '\x0A':
|
||||||
|
inc(r.pos)
|
||||||
|
inc(r.line)
|
||||||
|
if r.s[r.pos] == ')': inc r.pos
|
||||||
|
outf.write(")\n")
|
||||||
|
of "INIT":
|
||||||
|
outf.write("INIT(\n")
|
||||||
|
inc r.pos, 2
|
||||||
|
r.initIdx = r.pos
|
||||||
|
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
|
||||||
|
let d = decodeVInt(r.s, r.pos)
|
||||||
|
inc(r.pos) # #10
|
||||||
|
#let p = r.pos
|
||||||
|
#r.pos = d + r.dataIdx
|
||||||
|
#outf.writeNode decodeNode(r, UnknownLineInfo())
|
||||||
|
#outf.write("\n")
|
||||||
|
#r.pos = p
|
||||||
|
if r.s[r.pos] == ')': inc r.pos
|
||||||
|
outf.write("<not supported by viewer>)\n")
|
||||||
|
else:
|
||||||
|
InternalError("invalid section: '" & section &
|
||||||
|
"' at " & $r.line & " in " & r.filename)
|
||||||
|
skipSection(r)
|
||||||
|
if r.s[r.pos] == '\x0A':
|
||||||
|
inc(r.pos)
|
||||||
|
inc(r.line)
|
||||||
|
outf.close
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
viewFile(paramStr(1).addFileExt(rodExt))
|
||||||
|
|
|
||||||
0
compiler/rodutils.nim
Executable file → Normal file
0
compiler/rodutils.nim
Executable file → Normal file
3
compiler/rodwrite.nim
Executable file → Normal file
3
compiler/rodwrite.nim
Executable file → Normal file
|
|
@ -205,6 +205,9 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
|
||||||
return
|
return
|
||||||
# we need no surrounding [] here because the type is in a line of its own
|
# we need no surrounding [] here because the type is in a line of its own
|
||||||
if t.kind == tyForward: InternalError("encodeType: tyForward")
|
if t.kind == tyForward: InternalError("encodeType: tyForward")
|
||||||
|
# for the new rodfile viewer we use a preceeding [ so that the data section
|
||||||
|
# can easily be disambiguated:
|
||||||
|
add(result, '[')
|
||||||
encodeVInt(ord(t.kind), result)
|
encodeVInt(ord(t.kind), result)
|
||||||
add(result, '+')
|
add(result, '+')
|
||||||
encodeVInt(t.id, result)
|
encodeVInt(t.id, result)
|
||||||
|
|
|
||||||
0
compiler/ropes.nim
Executable file → Normal file
0
compiler/ropes.nim
Executable file → Normal file
18
compiler/sem.nim
Executable file → Normal file
18
compiler/sem.nim
Executable file → Normal file
|
|
@ -19,19 +19,15 @@ import
|
||||||
|
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
type
|
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.procvar.}
|
||||||
TExprFlag = enum
|
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.
|
||||||
efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType
|
procvar.}
|
||||||
TExprFlags = set[TExprFlag]
|
|
||||||
|
|
||||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
|
||||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
|
||||||
proc semExprNoType(c: PContext, n: PNode): PNode
|
proc semExprNoType(c: PContext, n: PNode): PNode
|
||||||
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||||
proc semProcBody(c: PContext, n: PNode): PNode
|
proc semProcBody(c: PContext, n: PNode): PNode
|
||||||
|
|
||||||
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode
|
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode
|
||||||
proc changeType(n: PNode, newType: PType)
|
proc changeType(n: PNode, newType: PType, check: bool)
|
||||||
|
|
||||||
proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode
|
proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||||
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType
|
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType
|
||||||
|
|
@ -200,14 +196,12 @@ proc addCodeForGenerics(c: PContext, n: PNode) =
|
||||||
addSon(n, prc.ast)
|
addSon(n, prc.ast)
|
||||||
c.lastGenericIdx = c.generics.len
|
c.lastGenericIdx = c.generics.len
|
||||||
|
|
||||||
proc semExprNoFlags(c: PContext, n: PNode): PNode {.procvar.} =
|
|
||||||
result = semExpr(c, n, {})
|
|
||||||
|
|
||||||
proc myOpen(module: PSym): PPassContext =
|
proc myOpen(module: PSym): PPassContext =
|
||||||
var c = newContext(module)
|
var c = newContext(module)
|
||||||
if c.p != nil: InternalError(module.info, "sem.myOpen")
|
if c.p != nil: InternalError(module.info, "sem.myOpen")
|
||||||
c.semConstExpr = semConstExpr
|
c.semConstExpr = semConstExpr
|
||||||
c.semExpr = semExprNoFlags
|
c.semExpr = semExpr
|
||||||
|
c.semOperand = semOperand
|
||||||
c.semConstBoolExpr = semConstBoolExpr
|
c.semConstBoolExpr = semConstBoolExpr
|
||||||
c.semOverloadedCall = semOverloadedCall
|
c.semOverloadedCall = semOverloadedCall
|
||||||
c.semTypeNode = semTypeNode
|
c.semTypeNode = semTypeNode
|
||||||
|
|
|
||||||
9
compiler/semcall.nim
Executable file → Normal file
9
compiler/semcall.nim
Executable file → Normal file
|
|
@ -85,7 +85,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
#writeMatches(alt)
|
#writeMatches(alt)
|
||||||
if c.inCompilesContext > 0:
|
if c.inCompilesContext > 0:
|
||||||
# quick error message for performance of 'compiles' built-in:
|
# quick error message for performance of 'compiles' built-in:
|
||||||
GlobalError(n.Info, errAmbiguousCallXYZ, "")
|
GlobalError(n.Info, errGenerated, "ambiguous call")
|
||||||
elif gErrorCounter == 0:
|
elif gErrorCounter == 0:
|
||||||
# don't cascade errors
|
# don't cascade errors
|
||||||
var args = "("
|
var args = "("
|
||||||
|
|
@ -174,7 +174,10 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
# common case; check the only candidate has the right
|
# common case; check the only candidate has the right
|
||||||
# number of generic type parameters:
|
# number of generic type parameters:
|
||||||
if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
|
if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
|
||||||
return explicitGenericInstError(n)
|
let expected = safeLen(s.ast.sons[genericParamsPos])
|
||||||
|
LocalError(n.info, errGenerated, "cannot instantiate: " & renderTree(n) &
|
||||||
|
"; got " & $(n.len-1) & " type(s) but expected " & $expected)
|
||||||
|
return n
|
||||||
result = explicitGenericSym(c, n, s)
|
result = explicitGenericSym(c, n, s)
|
||||||
elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
|
elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
|
||||||
# choose the generic proc with the proper number of type parameters.
|
# choose the generic proc with the proper number of type parameters.
|
||||||
|
|
@ -204,7 +207,7 @@ proc SearchForBorrowProc(c: PContext, fn: PSym, tos: int): PSym =
|
||||||
call.add(newIdentNode(fn.name, fn.info))
|
call.add(newIdentNode(fn.name, fn.info))
|
||||||
for i in 1.. <fn.typ.n.len:
|
for i in 1.. <fn.typ.n.len:
|
||||||
let param = fn.typ.n.sons[i]
|
let param = fn.typ.n.sons[i]
|
||||||
let t = skipTypes(param.typ, abstractVar)
|
let t = skipTypes(param.typ, abstractVar-{tyTypeDesc})
|
||||||
call.add(newNodeIT(nkEmpty, fn.info, t.baseOfDistinct))
|
call.add(newNodeIT(nkEmpty, fn.info, t.baseOfDistinct))
|
||||||
var resolved = semOverloadedCall(c, call, call, {fn.kind})
|
var resolved = semOverloadedCall(c, call, call, {fn.kind})
|
||||||
if resolved != nil:
|
if resolved != nil:
|
||||||
|
|
|
||||||
8
compiler/semdata.nim
Executable file → Normal file
8
compiler/semdata.nim
Executable file → Normal file
|
|
@ -39,6 +39,11 @@ type
|
||||||
TInstantiationPair* = object
|
TInstantiationPair* = object
|
||||||
genericSym*: PSym
|
genericSym*: PSym
|
||||||
inst*: PInstantiation
|
inst*: PInstantiation
|
||||||
|
|
||||||
|
TExprFlag* = enum
|
||||||
|
efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType,
|
||||||
|
efAllowDestructor
|
||||||
|
TExprFlags* = set[TExprFlag]
|
||||||
|
|
||||||
PContext* = ref TContext
|
PContext* = ref TContext
|
||||||
TContext* = object of TPassContext # a context represents a module
|
TContext* = object of TPassContext # a context represents a module
|
||||||
|
|
@ -64,7 +69,8 @@ type
|
||||||
# to some new symbol in a generic instantiation
|
# to some new symbol in a generic instantiation
|
||||||
libs*: TLinkedList # all libs used by this module
|
libs*: TLinkedList # all libs used by this module
|
||||||
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
||||||
semExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||||
|
semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||||
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
|
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
|
||||||
semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
|
semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
|
||||||
filter: TSymKinds): PNode {.nimcall.}
|
filter: TSymKinds): PNode {.nimcall.}
|
||||||
|
|
|
||||||
277
compiler/semexprs.nim
Executable file → Normal file
277
compiler/semexprs.nim
Executable file → Normal file
|
|
@ -10,18 +10,6 @@
|
||||||
# this module does the semantic checking for expressions
|
# this module does the semantic checking for expressions
|
||||||
# included from sem.nim
|
# included from sem.nim
|
||||||
|
|
||||||
proc restoreOldStyleType(n: PNode) =
|
|
||||||
# XXX: semExprWithType used to return the same type
|
|
||||||
# for nodes such as (100) or (int).
|
|
||||||
# This is inappropriate. The type of the first expression
|
|
||||||
# should be "int", while the type of the second one should
|
|
||||||
# be typedesc(int).
|
|
||||||
#
|
|
||||||
# This is strictly for backward compatibility until
|
|
||||||
# the transition to types as first-class values is complete.
|
|
||||||
if n.typ.kind == tyTypeDesc and n.typ.sonsLen == 1:
|
|
||||||
n.typ = n.typ.sons[0]
|
|
||||||
|
|
||||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
||||||
markUsed(n, s)
|
markUsed(n, s)
|
||||||
pushInfoContext(n.info)
|
pushInfoContext(n.info)
|
||||||
|
|
@ -31,32 +19,67 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
||||||
|
|
||||||
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||||
|
|
||||||
proc newDeref(n: PNode): PNode {.inline.} =
|
proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
|
||||||
result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0])
|
var smoduleId = getModule(s).id
|
||||||
addSon(result, n)
|
if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
|
||||||
|
smoduleId != c.module.id and smoduleId != c.friendModule.id:
|
||||||
|
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
||||||
|
|
||||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
proc semProcvarCheck(c: PContext, n: PNode) =
|
||||||
|
let n = n.skipConv
|
||||||
|
if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skIterator,
|
||||||
|
skConverter}:
|
||||||
|
performProcvarCheck(c, n, n.sym)
|
||||||
|
|
||||||
|
proc semDestructorCheck(c: PContext, n: PNode, flags: TExprFlags) {.inline.} =
|
||||||
|
if efAllowDestructor notin flags and n.kind in nkCallKinds+{nkObjConstr}:
|
||||||
|
if instantiateDestructor(c, n.typ):
|
||||||
|
LocalError(n.info, errGenerated,
|
||||||
|
"usage of a type with a destructor in a non destructible context")
|
||||||
|
|
||||||
|
proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
|
# same as 'semExprWithType' but doesn't check for proc vars
|
||||||
result = semExpr(c, n, flags)
|
result = semExpr(c, n, flags)
|
||||||
if result.kind == nkEmpty:
|
if result.kind == nkEmpty:
|
||||||
# do not produce another redundant error message:
|
# do not produce another redundant error message:
|
||||||
#raiseRecoverableError("")
|
#raiseRecoverableError("")
|
||||||
result = errorNode(c, n)
|
result = errorNode(c, n)
|
||||||
if result.typ != nil:
|
if result.typ != nil:
|
||||||
|
# XXX tyGenericInst here?
|
||||||
if result.typ.kind == tyVar: result = newDeref(result)
|
if result.typ.kind == tyVar: result = newDeref(result)
|
||||||
else:
|
else:
|
||||||
LocalError(n.info, errExprXHasNoType,
|
LocalError(n.info, errExprXHasNoType,
|
||||||
renderTree(result, {renderNoComments}))
|
renderTree(result, {renderNoComments}))
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
|
|
||||||
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = semExpr(c, n, flags)
|
result = semExpr(c, n, flags)
|
||||||
if result.kind == nkEmpty:
|
if result.kind == nkEmpty:
|
||||||
|
# do not produce another redundant error message:
|
||||||
|
#raiseRecoverableError("")
|
||||||
|
result = errorNode(c, n)
|
||||||
|
if result.typ != nil:
|
||||||
|
# XXX tyGenericInst here?
|
||||||
|
semProcvarCheck(c, result)
|
||||||
|
if result.typ.kind == tyVar: result = newDeref(result)
|
||||||
|
semDestructorCheck(c, result, flags)
|
||||||
|
else:
|
||||||
|
LocalError(n.info, errExprXHasNoType,
|
||||||
|
renderTree(result, {renderNoComments}))
|
||||||
|
result.typ = errorType(c)
|
||||||
|
|
||||||
|
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
|
result = semExpr(c, n, flags)
|
||||||
|
if result.kind == nkEmpty:
|
||||||
# do not produce another redundant error message:
|
# do not produce another redundant error message:
|
||||||
result = errorNode(c, n)
|
result = errorNode(c, n)
|
||||||
if result.typ == nil:
|
if result.typ == nil:
|
||||||
LocalError(n.info, errExprXHasNoType,
|
LocalError(n.info, errExprXHasNoType,
|
||||||
renderTree(result, {renderNoComments}))
|
renderTree(result, {renderNoComments}))
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
|
else:
|
||||||
|
semProcvarCheck(c, result)
|
||||||
|
semDestructorCheck(c, result, flags)
|
||||||
|
|
||||||
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
result = symChoice(c, n, s, scClosed)
|
result = symChoice(c, n, s, scClosed)
|
||||||
|
|
@ -65,21 +88,12 @@ proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
|
||||||
result = copyTree(s.ast)
|
result = copyTree(s.ast)
|
||||||
result.typ = s.typ
|
result.typ = s.typ
|
||||||
result.info = n.info
|
result.info = n.info
|
||||||
|
|
||||||
proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
|
|
||||||
# XXX this not correct; it's valid to pass to templates and macros.
|
|
||||||
# We really need another post nkCallConv check for this. Or maybe do it
|
|
||||||
# in transform().
|
|
||||||
var smoduleId = getModule(s).id
|
|
||||||
if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
|
|
||||||
smoduleId != c.module.id and smoduleId != c.friendModule.id:
|
|
||||||
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
|
||||||
|
|
||||||
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
case s.kind
|
case s.kind
|
||||||
of skConst:
|
of skConst:
|
||||||
markUsed(n, s)
|
markUsed(n, s)
|
||||||
case skipTypes(s.typ, abstractInst).kind
|
case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
|
||||||
of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
|
of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
|
||||||
tyTuple, tySet, tyUInt..tyUInt64:
|
tyTuple, tySet, tyUInt..tyUInt64:
|
||||||
result = inlineConst(n, s)
|
result = inlineConst(n, s)
|
||||||
|
|
@ -149,7 +163,7 @@ proc checkConvertible(castDest, src: PType): TConvStatus =
|
||||||
result = convNotNeedeed
|
result = convNotNeedeed
|
||||||
return
|
return
|
||||||
var d = skipTypes(castDest, abstractVar)
|
var d = skipTypes(castDest, abstractVar)
|
||||||
var s = skipTypes(src, abstractVar)
|
var s = skipTypes(src, abstractVar-{tyTypeDesc})
|
||||||
while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind):
|
while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind):
|
||||||
d = base(d)
|
d = base(d)
|
||||||
s = base(s)
|
s = base(s)
|
||||||
|
|
@ -158,7 +172,7 @@ proc checkConvertible(castDest, src: PType): TConvStatus =
|
||||||
elif d.Kind == tyObject and s.Kind == tyObject:
|
elif d.Kind == tyObject and s.Kind == tyObject:
|
||||||
result = checkConversionBetweenObjects(d, s)
|
result = checkConversionBetweenObjects(d, s)
|
||||||
elif (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes) and
|
elif (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes) and
|
||||||
(skipTypes(src, abstractVarRange).Kind in IntegralTypes):
|
(skipTypes(src, abstractVarRange-{tyTypeDesc}).Kind in IntegralTypes):
|
||||||
# accept conversion between integral types
|
# accept conversion between integral types
|
||||||
else:
|
else:
|
||||||
# we use d, s here to speed up that operation a bit:
|
# we use d, s here to speed up that operation a bit:
|
||||||
|
|
@ -185,7 +199,7 @@ proc isCastable(dst, src: PType): bool =
|
||||||
else:
|
else:
|
||||||
result = (ds >= ss) or
|
result = (ds >= ss) or
|
||||||
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
||||||
(skipTypes(src, abstractInst).kind in IntegralTypes)
|
(skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes)
|
||||||
|
|
||||||
proc isSymChoice(n: PNode): bool {.inline.} =
|
proc isSymChoice(n: PNode): bool {.inline.} =
|
||||||
result = n.kind in nkSymChoices
|
result = n.kind in nkSymChoices
|
||||||
|
|
@ -199,7 +213,7 @@ proc semConv(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
addSon(result, copyTree(n.sons[0]))
|
addSon(result, copyTree(n.sons[0]))
|
||||||
addSon(result, semExprWithType(c, n.sons[1]))
|
addSon(result, semExprWithType(c, n.sons[1]))
|
||||||
var op = result.sons[1]
|
var op = result.sons[1]
|
||||||
|
|
||||||
if not isSymChoice(op):
|
if not isSymChoice(op):
|
||||||
let status = checkConvertible(result.typ, op.typ)
|
let status = checkConvertible(result.typ, op.typ)
|
||||||
case status
|
case status
|
||||||
|
|
@ -238,24 +252,24 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
LocalError(n.info, errXExpectsTypeOrValue, opToStr[m])
|
LocalError(n.info, errXExpectsTypeOrValue, opToStr[m])
|
||||||
else:
|
else:
|
||||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||||
restoreOldStyleType(n.sons[1])
|
|
||||||
var typ = skipTypes(n.sons[1].typ, abstractVarRange)
|
var typ = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||||
case typ.Kind
|
case typ.Kind
|
||||||
of tySequence, tyString, tyOpenArray, tyVarargs:
|
of tySequence, tyString, tyOpenArray, tyVarargs:
|
||||||
n.typ = getSysType(tyInt)
|
n.typ = getSysType(tyInt)
|
||||||
of tyArrayConstr, tyArray:
|
of tyArrayConstr, tyArray:
|
||||||
n.typ = n.sons[1].typ.sons[0] # indextype
|
n.typ = typ.sons[0] # indextype
|
||||||
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32:
|
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32:
|
||||||
n.typ = n.sons[1].typ
|
# do not skip the range!
|
||||||
|
n.typ = n.sons[1].typ.skipTypes(abstractVar)
|
||||||
else: LocalError(n.info, errInvalidArgForX, opToStr[m])
|
else: LocalError(n.info, errInvalidArgForX, opToStr[m])
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc semSizeof(c: PContext, n: PNode): PNode =
|
proc semSizeof(c: PContext, n: PNode): PNode =
|
||||||
if sonsLen(n) != 2:
|
if sonsLen(n) != 2:
|
||||||
LocalError(n.info, errXExpectsTypeOrValue, "sizeof")
|
LocalError(n.info, errXExpectsTypeOrValue, "sizeof")
|
||||||
else:
|
else:
|
||||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||||
restoreOldStyleType(n.sons[1])
|
#restoreOldStyleType(n.sons[1])
|
||||||
n.typ = getSysType(tyInt)
|
n.typ = getSysType(tyInt)
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
|
|
@ -265,10 +279,10 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||||
n.sons[2] = semExprWithType(c, n.sons[2])
|
n.sons[2] = semExprWithType(c, n.sons[2])
|
||||||
#restoreOldStyleType(n.sons[1])
|
#restoreOldStyleType(n.sons[1])
|
||||||
#restoreOldStyleType(n.sons[2])
|
#restoreOldStyleType(n.sons[2])
|
||||||
let a = skipTypes(n.sons[1].typ, typedescPtrs)
|
let a = skipTypes(n.sons[1].typ, abstractPtrs)
|
||||||
let b = skipTypes(n.sons[2].typ, typedescPtrs)
|
let b = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||||
let x = skipTypes(n.sons[1].typ, abstractPtrs)
|
let x = skipTypes(n.sons[1].typ, abstractPtrs-{tyTypeDesc})
|
||||||
let y = skipTypes(n.sons[2].typ, abstractPtrs)
|
let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
|
||||||
|
|
||||||
if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
|
if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
|
||||||
LocalError(n.info, errXExpectsObjectTypes, "of")
|
LocalError(n.info, errXExpectsObjectTypes, "of")
|
||||||
|
|
@ -319,7 +333,7 @@ proc semIs(c: PContext, n: PNode): PNode =
|
||||||
|
|
||||||
proc semOpAux(c: PContext, n: PNode) =
|
proc semOpAux(c: PContext, n: PNode) =
|
||||||
const flags = {efDetermineType}
|
const flags = {efDetermineType}
|
||||||
for i in countup(1, n.sonsLen- 1):
|
for i in countup(1, n.sonsLen-1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
||||||
var info = a.sons[0].info
|
var info = a.sons[0].info
|
||||||
|
|
@ -328,7 +342,7 @@ proc semOpAux(c: PContext, n: PNode) =
|
||||||
a.typ = a.sons[1].typ
|
a.typ = a.sons[1].typ
|
||||||
else:
|
else:
|
||||||
n.sons[i] = semExprWithType(c, a, flags)
|
n.sons[i] = semExprWithType(c, a, flags)
|
||||||
|
|
||||||
proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
||||||
# quick check if there is *any* () operator overloaded:
|
# quick check if there is *any* () operator overloaded:
|
||||||
var par = getIdent("()")
|
var par = getIdent("()")
|
||||||
|
|
@ -340,11 +354,11 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
||||||
for i in countup(0, sonsLen(n) - 1): addSon(result, n.sons[i])
|
for i in countup(0, sonsLen(n) - 1): addSon(result, n.sons[i])
|
||||||
result = semExpr(c, result)
|
result = semExpr(c, result)
|
||||||
|
|
||||||
proc changeType(n: PNode, newType: PType) =
|
proc changeType(n: PNode, newType: PType, check: bool) =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkCurly, nkBracket:
|
of nkCurly, nkBracket:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
changeType(n.sons[i], elemType(newType))
|
changeType(n.sons[i], elemType(newType), check)
|
||||||
of nkPar:
|
of nkPar:
|
||||||
if newType.kind != tyTuple:
|
if newType.kind != tyTuple:
|
||||||
InternalError(n.info, "changeType: no tuple type for constructor")
|
InternalError(n.info, "changeType: no tuple type for constructor")
|
||||||
|
|
@ -359,15 +373,21 @@ proc changeType(n: PNode, newType: PType) =
|
||||||
if f == nil:
|
if f == nil:
|
||||||
internalError(m.info, "changeType(): invalid identifier")
|
internalError(m.info, "changeType(): invalid identifier")
|
||||||
return
|
return
|
||||||
changeType(n.sons[i].sons[1], f.typ)
|
changeType(n.sons[i].sons[1], f.typ, check)
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var m = n.sons[i]
|
var m = n.sons[i]
|
||||||
var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
|
var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
|
||||||
addSon(a, newSymNode(newType.n.sons[i].sym))
|
addSon(a, newSymNode(newType.n.sons[i].sym))
|
||||||
addSon(a, m)
|
addSon(a, m)
|
||||||
changeType(m, newType.sons[i])
|
changeType(m, newType.sons[i], check)
|
||||||
n.sons[i] = a
|
n.sons[i] = a
|
||||||
|
of nkCharLit..nkUInt64Lit:
|
||||||
|
if check:
|
||||||
|
let value = n.intVal
|
||||||
|
if value < firstOrd(newType) or value > lastOrd(newType):
|
||||||
|
LocalError(n.info, errGenerated, "cannot convert " & $value &
|
||||||
|
" to " & typeToString(newType))
|
||||||
else: nil
|
else: nil
|
||||||
n.typ = newType
|
n.typ = newType
|
||||||
|
|
||||||
|
|
@ -384,13 +404,13 @@ proc arrayConstrType(c: PContext, n: PNode): PType =
|
||||||
typ.sons[0] = makeRangeType(c, 0, sonsLen(n) - 1, n.info)
|
typ.sons[0] = makeRangeType(c, 0, sonsLen(n) - 1, n.info)
|
||||||
result = typ
|
result = typ
|
||||||
|
|
||||||
proc semArrayConstr(c: PContext, n: PNode): PNode =
|
proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result = newNodeI(nkBracket, n.info)
|
result = newNodeI(nkBracket, n.info)
|
||||||
result.typ = newTypeS(tyArrayConstr, c)
|
result.typ = newTypeS(tyArrayConstr, c)
|
||||||
rawAddSon(result.typ, nil) # index type
|
rawAddSon(result.typ, nil) # index type
|
||||||
if sonsLen(n) == 0:
|
if sonsLen(n) == 0:
|
||||||
rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
|
rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
|
||||||
else:
|
else:
|
||||||
var x = n.sons[0]
|
var x = n.sons[0]
|
||||||
var lastIndex: biggestInt = 0
|
var lastIndex: biggestInt = 0
|
||||||
var indexType = getSysType(tyInt)
|
var indexType = getSysType(tyInt)
|
||||||
|
|
@ -413,7 +433,7 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
|
||||||
localError(x.info, errInvalidOrderInArrayConstructor)
|
localError(x.info, errInvalidOrderInArrayConstructor)
|
||||||
x = x.sons[1]
|
x = x.sons[1]
|
||||||
|
|
||||||
n.sons[i] = semExprWithType(c, x)
|
n.sons[i] = semExprWithType(c, x, flags*{efAllowDestructor})
|
||||||
addSon(result, fitNode(c, typ, n.sons[i]))
|
addSon(result, fitNode(c, typ, n.sons[i]))
|
||||||
inc(lastIndex)
|
inc(lastIndex)
|
||||||
addSonSkipIntLit(result.typ, typ)
|
addSonSkipIntLit(result.typ, typ)
|
||||||
|
|
@ -447,11 +467,11 @@ proc fixAbstractType(c: PContext, n: PNode) =
|
||||||
elif skipTypes(it.sons[1].typ, abstractVar).kind in
|
elif skipTypes(it.sons[1].typ, abstractVar).kind in
|
||||||
{tyNil, tyArrayConstr, tyTuple, tySet}:
|
{tyNil, tyArrayConstr, tyTuple, tySet}:
|
||||||
var s = skipTypes(it.typ, abstractVar)
|
var s = skipTypes(it.typ, abstractVar)
|
||||||
changeType(it.sons[1], s)
|
changeType(it.sons[1], s, check=true)
|
||||||
n.sons[i] = it.sons[1]
|
n.sons[i] = it.sons[1]
|
||||||
of nkBracket:
|
of nkBracket:
|
||||||
# an implicitely constructed array (passed to an open array):
|
# an implicitely constructed array (passed to an open array):
|
||||||
n.sons[i] = semArrayConstr(c, it)
|
n.sons[i] = semArrayConstr(c, it, {})
|
||||||
else:
|
else:
|
||||||
nil
|
nil
|
||||||
#if (it.typ == nil):
|
#if (it.typ == nil):
|
||||||
|
|
@ -483,9 +503,10 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
|
||||||
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
# n.sym.typ can be nil in 'check' mode ...
|
# n.sym.typ can be nil in 'check' mode ...
|
||||||
if n.sym.typ != nil and skipTypes(n.sym.typ, abstractInst).kind != tyVar:
|
if n.sym.typ != nil and
|
||||||
|
skipTypes(n.sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar:
|
||||||
incl(n.sym.flags, sfAddrTaken)
|
incl(n.sym.flags, sfAddrTaken)
|
||||||
result = newHiddenAddrTaken(c, n)
|
result = newHiddenAddrTaken(c, n)
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
|
|
@ -493,16 +514,16 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
||||||
if n.sons[1].kind != nkSym:
|
if n.sons[1].kind != nkSym:
|
||||||
internalError(n.info, "analyseIfAddressTaken")
|
internalError(n.info, "analyseIfAddressTaken")
|
||||||
return
|
return
|
||||||
if skipTypes(n.sons[1].sym.typ, abstractInst).kind != tyVar:
|
if skipTypes(n.sons[1].sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar:
|
||||||
incl(n.sons[1].sym.flags, sfAddrTaken)
|
incl(n.sons[1].sym.flags, sfAddrTaken)
|
||||||
result = newHiddenAddrTaken(c, n)
|
result = newHiddenAddrTaken(c, n)
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
if skipTypes(n.sons[0].typ, abstractInst).kind != tyVar:
|
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind != tyVar:
|
||||||
if n.sons[0].kind == nkSym: incl(n.sons[0].sym.flags, sfAddrTaken)
|
if n.sons[0].kind == nkSym: incl(n.sons[0].sym.flags, sfAddrTaken)
|
||||||
result = newHiddenAddrTaken(c, n)
|
result = newHiddenAddrTaken(c, n)
|
||||||
else:
|
else:
|
||||||
result = newHiddenAddrTaken(c, n) # BUGFIX!
|
result = newHiddenAddrTaken(c, n)
|
||||||
|
|
||||||
proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
|
|
@ -517,16 +538,24 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||||
|
|
||||||
if n.sons[0].kind == nkSym and n.sons[0].sym.magic in FakeVarParams:
|
if n.sons[0].kind == nkSym and n.sons[0].sym.magic in FakeVarParams:
|
||||||
# BUGFIX: check for L-Value still needs to be done for the arguments!
|
# BUGFIX: check for L-Value still needs to be done for the arguments!
|
||||||
|
# note sometimes this is eval'ed twice so we check for nkHiddenAddr here:
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
if i < sonsLen(t) and t.sons[i] != nil and
|
if i < sonsLen(t) and t.sons[i] != nil and
|
||||||
skipTypes(t.sons[i], abstractInst).kind == tyVar:
|
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
||||||
if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}:
|
if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}:
|
||||||
LocalError(n.sons[i].info, errVarForOutParamNeeded)
|
if n.sons[i].kind != nkHiddenAddr:
|
||||||
|
LocalError(n.sons[i].info, errVarForOutParamNeeded)
|
||||||
return
|
return
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
if n.sons[i].kind == nkHiddenCallConv:
|
||||||
|
# we need to recurse explicitly here as converters can create nested
|
||||||
|
# calls and then they wouldn't be analysed otherwise
|
||||||
|
analyseIfAddressTakenInCall(c, n.sons[i])
|
||||||
|
semProcvarCheck(c, n.sons[i])
|
||||||
if i < sonsLen(t) and
|
if i < sonsLen(t) and
|
||||||
skipTypes(t.sons[i], abstractInst).kind == tyVar:
|
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
||||||
n.sons[i] = analyseIfAddressTaken(c, n.sons[i])
|
if n.sons[i].kind != nkHiddenAddr:
|
||||||
|
n.sons[i] = analyseIfAddressTaken(c, n.sons[i])
|
||||||
|
|
||||||
include semmagic
|
include semmagic
|
||||||
|
|
||||||
|
|
@ -541,11 +570,12 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||||
call.add(n.sons[0])
|
call.add(n.sons[0])
|
||||||
var allConst = true
|
var allConst = true
|
||||||
for i in 1 .. < n.len:
|
for i in 1 .. < n.len:
|
||||||
let a = getConstExpr(c.module, n.sons[i])
|
var a = getConstExpr(c.module, n.sons[i])
|
||||||
if a != nil: call.add(a)
|
if a == nil:
|
||||||
else:
|
|
||||||
allConst = false
|
allConst = false
|
||||||
call.add(n.sons[i])
|
a = n.sons[i]
|
||||||
|
if a.kind == nkHiddenStdConv: a = a.sons[1]
|
||||||
|
call.add(a)
|
||||||
if allConst:
|
if allConst:
|
||||||
result = semfold.getConstExpr(c.module, call)
|
result = semfold.getConstExpr(c.module, call)
|
||||||
if result.isNil: result = n
|
if result.isNil: result = n
|
||||||
|
|
@ -617,6 +647,7 @@ proc semDirectCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||||
flags: TExprFlags): PNode =
|
flags: TExprFlags): PNode =
|
||||||
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
||||||
|
|
||||||
|
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||||
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
|
|
@ -635,8 +666,9 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
let nOrig = n.copyTree
|
let nOrig = n.copyTree
|
||||||
semOpAux(c, n)
|
semOpAux(c, n)
|
||||||
var t: PType = nil
|
var t: PType = nil
|
||||||
if (n.sons[0].typ != nil): t = skipTypes(n.sons[0].typ, abstractInst)
|
if n.sons[0].typ != nil:
|
||||||
if (t != nil) and (t.kind == tyProc):
|
t = skipTypes(n.sons[0].typ, abstractInst-{tyTypedesc})
|
||||||
|
if t != nil and t.kind == tyProc:
|
||||||
# This is a proc variable, apply normal overload resolution
|
# This is a proc variable, apply normal overload resolution
|
||||||
var m: TCandidate
|
var m: TCandidate
|
||||||
initCandidate(m, t)
|
initCandidate(m, t)
|
||||||
|
|
@ -668,10 +700,11 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# we assume that a procedure that calls something indirectly
|
# we assume that a procedure that calls something indirectly
|
||||||
# has side-effects:
|
# has side-effects:
|
||||||
if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
|
if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
|
||||||
elif (t != nil) and t.kind == tyTypeDesc:
|
elif t != nil and t.kind == tyTypeDesc:
|
||||||
|
if n.len == 1: return semObjConstr(c, n, flags)
|
||||||
let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
|
let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
|
||||||
result = semConv(c, n, symFromType(destType, n.info))
|
result = semConv(c, n, symFromType(destType, n.info))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
result = overloadedCallOpr(c, n)
|
result = overloadedCallOpr(c, n)
|
||||||
# Now that nkSym does not imply an iteration over the proc/iterator space,
|
# Now that nkSym does not imply an iteration over the proc/iterator space,
|
||||||
|
|
@ -694,7 +727,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# this seems to be a hotspot in the compiler!
|
# this seems to be a hotspot in the compiler!
|
||||||
let nOrig = n.copyTree
|
let nOrig = n.copyTree
|
||||||
semOpAux(c, n)
|
#semLazyOpAux(c, n)
|
||||||
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = overloadedCallOpr(c, n)
|
result = overloadedCallOpr(c, n)
|
||||||
|
|
@ -706,6 +739,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
of skMacro: result = semMacroExpr(c, result, nOrig, callee)
|
of skMacro: result = semMacroExpr(c, result, nOrig, callee)
|
||||||
of skTemplate: result = semTemplateExpr(c, result, callee)
|
of skTemplate: result = semTemplateExpr(c, result, callee)
|
||||||
else:
|
else:
|
||||||
|
semFinishOperands(c, n)
|
||||||
activate(c, n)
|
activate(c, n)
|
||||||
fixAbstractType(c, result)
|
fixAbstractType(c, result)
|
||||||
analyseIfAddressTakenInCall(c, result)
|
analyseIfAddressTakenInCall(c, result)
|
||||||
|
|
@ -714,7 +748,8 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result = evalAtCompileTime(c, result)
|
result = evalAtCompileTime(c, result)
|
||||||
|
|
||||||
proc buildStringify(c: PContext, arg: PNode): PNode =
|
proc buildStringify(c: PContext, arg: PNode): PNode =
|
||||||
if arg.typ != nil and skipTypes(arg.typ, abstractInst).kind == tyString:
|
if arg.typ != nil and
|
||||||
|
skipTypes(arg.typ, abstractInst-{tyTypeDesc}).kind == tyString:
|
||||||
result = arg
|
result = arg
|
||||||
else:
|
else:
|
||||||
result = newNodeI(nkCall, arg.info)
|
result = newNodeI(nkCall, arg.info)
|
||||||
|
|
@ -752,7 +787,7 @@ proc discardCheck(result: PNode) =
|
||||||
# XXX too much work and fixing would break bootstrapping:
|
# XXX too much work and fixing would break bootstrapping:
|
||||||
#Message(n.info, warnNilStatement)
|
#Message(n.info, warnNilStatement)
|
||||||
result.typ = nil
|
result.typ = nil
|
||||||
elif not ImplicitelyDiscardable(result) and result.typ.kind != tyError and
|
elif not ImplicitlyDiscardable(result) and result.typ.kind != tyError and
|
||||||
gCmd != cmdInteractive:
|
gCmd != cmdInteractive:
|
||||||
localError(result.info, errDiscardValue)
|
localError(result.info, errDiscardValue)
|
||||||
|
|
||||||
|
|
@ -845,16 +880,17 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
return semSym(c, n, s, flags)
|
return semSym(c, n, s, flags)
|
||||||
|
|
||||||
n.sons[0] = semExprWithType(c, n.sons[0], flags)
|
n.sons[0] = semExprWithType(c, n.sons[0], flags)
|
||||||
restoreOldStyleType(n.sons[0])
|
#restoreOldStyleType(n.sons[0])
|
||||||
var i = considerAcc(n.sons[1])
|
var i = considerAcc(n.sons[1])
|
||||||
var ty = n.sons[0].typ
|
var ty = n.sons[0].typ
|
||||||
var f: PSym = nil
|
var f: PSym = nil
|
||||||
result = nil
|
result = nil
|
||||||
if isTypeExpr(n.sons[0]):
|
if isTypeExpr(n.sons[0]) or ty.kind == tyTypeDesc and ty.len == 1:
|
||||||
|
if ty.kind == tyTypeDesc: ty = ty.sons[0]
|
||||||
case ty.kind
|
case ty.kind
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
# look up if the identifier belongs to the enum:
|
# look up if the identifier belongs to the enum:
|
||||||
while ty != nil:
|
while ty != nil:
|
||||||
f = getSymFromList(ty.n, i)
|
f = getSymFromList(ty.n, i)
|
||||||
if f != nil: break
|
if f != nil: break
|
||||||
ty = ty.sons[0] # enum inheritance
|
ty = ty.sons[0] # enum inheritance
|
||||||
|
|
@ -881,7 +917,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# XXX: This is probably not relevant any more
|
# XXX: This is probably not relevant any more
|
||||||
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
|
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
|
||||||
ty = n.sons[0].Typ
|
ty = n.sons[0].Typ
|
||||||
|
|
||||||
ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef})
|
ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef})
|
||||||
var check: PNode = nil
|
var check: PNode = nil
|
||||||
if ty.kind == tyObject:
|
if ty.kind == tyObject:
|
||||||
|
|
@ -971,7 +1007,8 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
n.sons[0] = makeDeref(n.sons[0])
|
n.sons[0] = makeDeref(n.sons[0])
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
n.sons[i] = semExprWithType(c, n.sons[i], flags)
|
n.sons[i] = semExprWithType(c, n.sons[i],
|
||||||
|
flags*{efInTypeof, efDetermineType})
|
||||||
var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
|
var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
|
||||||
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
|
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
|
||||||
if arg != nil:
|
if arg != nil:
|
||||||
|
|
@ -1082,11 +1119,13 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
localError(a.info, errXCannotBeAssignedTo,
|
localError(a.info, errXCannotBeAssignedTo,
|
||||||
renderTree(a, {renderNoComments}))
|
renderTree(a, {renderNoComments}))
|
||||||
else:
|
else:
|
||||||
var
|
let
|
||||||
rhs = semExprWithType(c, n.sons[1])
|
|
||||||
lhs = n.sons[0]
|
lhs = n.sons[0]
|
||||||
if lhs.kind == nkSym and lhs.sym.kind == skResult and
|
lhsIsResult = lhs.kind == nkSym and lhs.sym.kind == skResult
|
||||||
lhs.sym.typ.kind == tyGenericParam:
|
var
|
||||||
|
rhs = semExprWithType(c, n.sons[1],
|
||||||
|
if lhsIsResult: {efAllowDestructor} else: {})
|
||||||
|
if lhsIsResult and lhs.sym.typ.kind == tyGenericParam:
|
||||||
if matchTypeClass(lhs.typ, rhs.typ):
|
if matchTypeClass(lhs.typ, rhs.typ):
|
||||||
InternalAssert c.p.resultSym != nil
|
InternalAssert c.p.resultSym != nil
|
||||||
lhs.typ = rhs.typ
|
lhs.typ = rhs.typ
|
||||||
|
|
@ -1128,7 +1167,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
|
||||||
# ``result``:
|
# ``result``:
|
||||||
if result.kind == nkSym and result.sym == c.p.resultSym:
|
if result.kind == nkSym and result.sym == c.p.resultSym:
|
||||||
nil
|
nil
|
||||||
elif result.kind == nkNilLit or ImplicitelyDiscardable(result):
|
elif result.kind == nkNilLit or ImplicitlyDiscardable(result):
|
||||||
# intended semantic: if it's 'discardable' and the context allows for it,
|
# intended semantic: if it's 'discardable' and the context allows for it,
|
||||||
# discard it. This is bad for chaining but nicer for C wrappers.
|
# discard it. This is bad for chaining but nicer for C wrappers.
|
||||||
# ambiguous :-(
|
# ambiguous :-(
|
||||||
|
|
@ -1531,21 +1570,22 @@ proc checkPar(n: PNode): TParKind =
|
||||||
LocalError(n.sons[i].info, errNamedExprNotAllowed)
|
LocalError(n.sons[i].info, errNamedExprNotAllowed)
|
||||||
return paNone
|
return paNone
|
||||||
|
|
||||||
proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result = newNodeI(nkPar, n.info)
|
result = newNodeI(nkPar, n.info)
|
||||||
var typ = newTypeS(tyTuple, c)
|
var typ = newTypeS(tyTuple, c)
|
||||||
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
|
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
|
||||||
var ids = initIntSet()
|
var ids = initIntSet()
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if (n.sons[i].kind != nkExprColonExpr) or
|
if (n.sons[i].kind != nkExprColonExpr) or
|
||||||
not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
|
not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
|
||||||
illFormedAst(n.sons[i])
|
illFormedAst(n.sons[i])
|
||||||
var id: PIdent
|
var id: PIdent
|
||||||
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
|
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
|
||||||
else: id = n.sons[i].sons[0].sym.name
|
else: id = n.sons[i].sons[0].sym.name
|
||||||
if ContainsOrIncl(ids, id.id):
|
if ContainsOrIncl(ids, id.id):
|
||||||
localError(n.sons[i].info, errFieldInitTwice, id.s)
|
localError(n.sons[i].info, errFieldInitTwice, id.s)
|
||||||
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
|
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1],
|
||||||
|
flags*{efAllowDestructor})
|
||||||
var f = newSymS(skField, n.sons[i].sons[0], c)
|
var f = newSymS(skField, n.sons[i].sons[0], c)
|
||||||
f.typ = skipIntLit(n.sons[i].sons[1].typ)
|
f.typ = skipIntLit(n.sons[i].sons[1].typ)
|
||||||
rawAddSon(typ, f.typ)
|
rawAddSon(typ, f.typ)
|
||||||
|
|
@ -1554,14 +1594,56 @@ proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
||||||
addSon(result, n.sons[i])
|
addSon(result, n.sons[i])
|
||||||
result.typ = typ
|
result.typ = typ
|
||||||
|
|
||||||
proc semTuplePositionsConstr(c: PContext, n: PNode): PNode =
|
proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result = n # we don't modify n, but compute the type:
|
result = n # we don't modify n, but compute the type:
|
||||||
var typ = newTypeS(tyTuple, c) # leave typ.n nil!
|
var typ = newTypeS(tyTuple, c) # leave typ.n nil!
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
n.sons[i] = semExprWithType(c, n.sons[i])
|
n.sons[i] = semExprWithType(c, n.sons[i], flags*{efAllowDestructor})
|
||||||
addSonSkipIntLit(typ, n.sons[i].typ)
|
addSonSkipIntLit(typ, n.sons[i].typ)
|
||||||
result.typ = typ
|
result.typ = typ
|
||||||
|
|
||||||
|
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
|
var t = semTypeNode(c, n.sons[0], nil)
|
||||||
|
result = n
|
||||||
|
result.typ = t
|
||||||
|
result.kind = nkObjConstr
|
||||||
|
t = skipTypes(t, abstractInst)
|
||||||
|
if t.kind == tyRef: t = skipTypes(t.sons[0], abstractInst)
|
||||||
|
if t.kind != tyObject:
|
||||||
|
localError(n.info, errGenerated, "object constructor needs an object type")
|
||||||
|
return
|
||||||
|
var ids = initIntSet()
|
||||||
|
for i in 1.. <n.len:
|
||||||
|
let it = n.sons[i]
|
||||||
|
if it.kind != nkExprColonExpr or it.sons[0].kind notin {nkSym, nkIdent}:
|
||||||
|
localError(n.info, errNamedExprExpected)
|
||||||
|
break
|
||||||
|
var id: PIdent
|
||||||
|
if it.sons[0].kind == nkIdent: id = it.sons[0].ident
|
||||||
|
else: id = it.sons[0].sym.name
|
||||||
|
if ContainsOrIncl(ids, id.id):
|
||||||
|
localError(it.info, errFieldInitTwice, id.s)
|
||||||
|
var e = semExprWithType(c, it.sons[1], flags*{efAllowDestructor})
|
||||||
|
var
|
||||||
|
check: PNode = nil
|
||||||
|
f: PSym
|
||||||
|
while true:
|
||||||
|
check = nil
|
||||||
|
f = lookupInRecordAndBuildCheck(c, it, t.n, id, check)
|
||||||
|
if f != nil: break
|
||||||
|
if t.sons[0] == nil: break
|
||||||
|
t = skipTypes(t.sons[0], {tyGenericInst})
|
||||||
|
if f != nil and fieldVisible(c, f):
|
||||||
|
it.sons[0] = newSymNode(f)
|
||||||
|
e = fitNode(c, f.typ, e)
|
||||||
|
# small hack here in a nkObjConstr the ``nkExprColonExpr`` node can have
|
||||||
|
# 3 childen the last being the field check
|
||||||
|
if check != nil: it.add(check)
|
||||||
|
else:
|
||||||
|
localError(it.info, errUndeclaredFieldX, id.s)
|
||||||
|
it.sons[1] = e
|
||||||
|
# XXX object field name check for 'case objects' if the kind is static?
|
||||||
|
|
||||||
proc semStmtListExpr(c: PContext, n: PNode): PNode =
|
proc semStmtListExpr(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
|
|
@ -1655,7 +1737,7 @@ proc semCaseExpr(c: PContext, caseStmt: PNode): PNode =
|
||||||
proc fixImmediateParams(n: PNode): PNode =
|
proc fixImmediateParams(n: PNode): PNode =
|
||||||
# XXX: Temporary work-around until we carry out
|
# XXX: Temporary work-around until we carry out
|
||||||
# the planned overload resolution reforms
|
# the planned overload resolution reforms
|
||||||
for i in 1 .. <n.len:
|
for i in 1 .. <safeLen(n):
|
||||||
if n[i].kind == nkDo: n.sons[i] = n[i][bodyPos]
|
if n[i].kind == nkDo: n.sons[i] = n[i][bodyPos]
|
||||||
|
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -1690,7 +1772,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
semCaptureSym(s, c.p.owner)
|
semCaptureSym(s, c.p.owner)
|
||||||
result = semSym(c, n, s, flags)
|
result = semSym(c, n, s, flags)
|
||||||
if s.kind in {skProc, skMethod, skIterator, skConverter}:
|
if s.kind in {skProc, skMethod, skIterator, skConverter}:
|
||||||
performProcvarCheck(c, n, s)
|
#performProcvarCheck(c, n, s)
|
||||||
result = symChoice(c, n, s, scClosed)
|
result = symChoice(c, n, s, scClosed)
|
||||||
if result.kind == nkSym:
|
if result.kind == nkSym:
|
||||||
markIndirect(c, result.sym)
|
markIndirect(c, result.sym)
|
||||||
|
|
@ -1769,6 +1851,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
# XXX think about this more (``set`` procs)
|
# XXX think about this more (``set`` procs)
|
||||||
if n.len == 2:
|
if n.len == 2:
|
||||||
result = semConv(c, n, s)
|
result = semConv(c, n, s)
|
||||||
|
elif n.len == 1:
|
||||||
|
result = semObjConstr(c, n, flags)
|
||||||
elif Contains(c.AmbiguousSymbols, s.id):
|
elif Contains(c.AmbiguousSymbols, s.id):
|
||||||
LocalError(n.info, errUseQualifier, s.name.s)
|
LocalError(n.info, errUseQualifier, s.name.s)
|
||||||
elif s.magic == mNone: result = semDirectOp(c, n, flags)
|
elif s.magic == mNone: result = semDirectOp(c, n, flags)
|
||||||
|
|
@ -1807,11 +1891,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
of nkPar:
|
of nkPar:
|
||||||
case checkPar(n)
|
case checkPar(n)
|
||||||
of paNone: result = errorNode(c, n)
|
of paNone: result = errorNode(c, n)
|
||||||
of paTuplePositions: result = semTuplePositionsConstr(c, n)
|
of paTuplePositions: result = semTuplePositionsConstr(c, n, flags)
|
||||||
of paTupleFields: result = semTupleFieldsConstr(c, n)
|
of paTupleFields: result = semTupleFieldsConstr(c, n, flags)
|
||||||
of paSingle: result = semExpr(c, n.sons[0], flags)
|
of paSingle: result = semExpr(c, n.sons[0], flags)
|
||||||
of nkCurly: result = semSetConstr(c, n)
|
of nkCurly: result = semSetConstr(c, n)
|
||||||
of nkBracket: result = semArrayConstr(c, n)
|
of nkBracket: result = semArrayConstr(c, n, flags)
|
||||||
|
of nkObjConstr: result = semObjConstr(c, n, flags)
|
||||||
of nkLambdaKinds: result = semLambda(c, n, flags)
|
of nkLambdaKinds: result = semLambda(c, n, flags)
|
||||||
of nkDerefExpr: result = semDeref(c, n)
|
of nkDerefExpr: result = semDeref(c, n)
|
||||||
of nkAddr:
|
of nkAddr:
|
||||||
|
|
|
||||||
55
compiler/semfold.nim
Executable file → Normal file
55
compiler/semfold.nim
Executable file → Normal file
|
|
@ -458,21 +458,28 @@ proc getAppType(n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
result = newStrNodeT("console", n)
|
result = newStrNodeT("console", n)
|
||||||
|
|
||||||
proc foldConv*(n, a: PNode): PNode =
|
proc rangeCheck(n: PNode, value: biggestInt) =
|
||||||
|
if value < firstOrd(n.typ) or value > lastOrd(n.typ):
|
||||||
|
LocalError(n.info, errGenerated, "cannot convert " & $value &
|
||||||
|
" to " & typeToString(n.typ))
|
||||||
|
|
||||||
|
proc foldConv*(n, a: PNode; check = false): PNode =
|
||||||
# XXX range checks?
|
# XXX range checks?
|
||||||
case skipTypes(n.typ, abstractRange).kind
|
case skipTypes(n.typ, abstractRange).kind
|
||||||
of tyInt..tyInt64:
|
of tyInt..tyInt64:
|
||||||
case skipTypes(a.typ, abstractRange).kind
|
case skipTypes(a.typ, abstractRange).kind
|
||||||
of tyFloat..tyFloat64: result = newIntNodeT(system.toInt(getFloat(a)), n)
|
of tyFloat..tyFloat64:
|
||||||
|
result = newIntNodeT(system.toInt(getFloat(a)), n)
|
||||||
of tyChar: result = newIntNodeT(getOrdValue(a), n)
|
of tyChar: result = newIntNodeT(getOrdValue(a), n)
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
of tyFloat..tyFloat64:
|
if check: rangeCheck(n, result.intVal)
|
||||||
|
of tyFloat..tyFloat64:
|
||||||
case skipTypes(a.typ, abstractRange).kind
|
case skipTypes(a.typ, abstractRange).kind
|
||||||
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
|
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
|
||||||
result = newFloatNodeT(toFloat(int(getOrdValue(a))), n)
|
result = newFloatNodeT(toFloat(int(getOrdValue(a))), n)
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
of tyOpenArray, tyVarargs, tyProc:
|
of tyOpenArray, tyVarargs, tyProc:
|
||||||
|
|
@ -490,7 +497,7 @@ proc getArrayConstr(m: PSym, n: PNode): PNode =
|
||||||
|
|
||||||
proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
||||||
var x = getConstExpr(m, n.sons[0])
|
var x = getConstExpr(m, n.sons[0])
|
||||||
if x == nil: return
|
if x == nil or x.typ.skipTypes({tyGenericInst}).kind == tyTypeDesc: return
|
||||||
|
|
||||||
var y = getConstExpr(m, n.sons[1])
|
var y = getConstExpr(m, n.sons[1])
|
||||||
if y == nil: return
|
if y == nil: return
|
||||||
|
|
@ -516,13 +523,13 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
||||||
LocalError(n.info, errIndexOutOfBounds)
|
LocalError(n.info, errIndexOutOfBounds)
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc foldFieldAccess(m: PSym, n: PNode): PNode =
|
proc foldFieldAccess(m: PSym, n: PNode): PNode =
|
||||||
# a real field access; proc calls have already been transformed
|
# a real field access; proc calls have already been transformed
|
||||||
var x = getConstExpr(m, n.sons[0])
|
var x = getConstExpr(m, n.sons[0])
|
||||||
if x == nil or x.kind != nkPar: return
|
if x == nil or x.kind notin {nkObjConstr, nkPar}: return
|
||||||
|
|
||||||
var field = n.sons[1].sym
|
var field = n.sons[1].sym
|
||||||
for i in countup(0, sonsLen(x) - 1):
|
for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1):
|
||||||
var it = x.sons[i]
|
var it = x.sons[i]
|
||||||
if it.kind != nkExprColonExpr:
|
if it.kind != nkExprColonExpr:
|
||||||
# lookup per index:
|
# lookup per index:
|
||||||
|
|
@ -541,7 +548,12 @@ proc foldConStrStr(m: PSym, n: PNode): PNode =
|
||||||
let a = getConstExpr(m, n.sons[i])
|
let a = getConstExpr(m, n.sons[i])
|
||||||
if a == nil: return nil
|
if a == nil: return nil
|
||||||
result.strVal.add(getStrOrChar(a))
|
result.strVal.add(getStrOrChar(a))
|
||||||
|
|
||||||
|
proc newSymNodeTypeDesc*(s: PSym; info: TLineInfo): PNode =
|
||||||
|
result = newSymNode(s, info)
|
||||||
|
result.typ = newType(tyTypeDesc, s.owner)
|
||||||
|
result.typ.addSonSkipIntLit(s.typ)
|
||||||
|
|
||||||
proc getConstExpr(m: PSym, n: PNode): PNode =
|
proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
@ -569,6 +581,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
if sfFakeConst notin s.flags: result = copyTree(s.ast)
|
if sfFakeConst notin s.flags: result = copyTree(s.ast)
|
||||||
elif s.kind in {skProc, skMethod}: # BUGFIX
|
elif s.kind in {skProc, skMethod}: # BUGFIX
|
||||||
result = n
|
result = n
|
||||||
|
elif s.kind in {skType, skGenericParam}:
|
||||||
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
of nkCharLit..nkNilLit:
|
of nkCharLit..nkNilLit:
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
of nkIfExpr:
|
of nkIfExpr:
|
||||||
|
|
@ -587,16 +601,18 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
LocalError(a.info, errCannotEvalXBecauseIncompletelyDefined,
|
LocalError(a.info, errCannotEvalXBecauseIncompletelyDefined,
|
||||||
"sizeof")
|
"sizeof")
|
||||||
result = nil
|
result = nil
|
||||||
elif skipTypes(a.typ, abstractInst).kind in {tyArray,tyObject,tyTuple}:
|
elif skipTypes(a.typ, typedescInst).kind in
|
||||||
|
IntegralTypes+NilableTypes+{tySet}:
|
||||||
|
#{tyArray,tyObject,tyTuple}:
|
||||||
|
result = newIntNodeT(getSize(a.typ), n)
|
||||||
|
else:
|
||||||
result = nil
|
result = nil
|
||||||
# XXX: size computation for complex types is still wrong
|
# XXX: size computation for complex types is still wrong
|
||||||
else:
|
|
||||||
result = newIntNodeT(getSize(a.typ), n)
|
|
||||||
of mLow:
|
of mLow:
|
||||||
result = newIntNodeT(firstOrd(n.sons[1].typ), n)
|
result = newIntNodeT(firstOrd(n.sons[1].typ), n)
|
||||||
of mHigh:
|
of mHigh:
|
||||||
if skipTypes(n.sons[1].typ, abstractVar).kind notin
|
if skipTypes(n.sons[1].typ, abstractVar).kind notin
|
||||||
{tyOpenArray, tyVarargs, tySequence, tyString}:
|
{tyOpenArray, tyVarargs, tySequence, tyString}:
|
||||||
result = newIntNodeT(lastOrd(skipTypes(n[1].typ, abstractVar)), n)
|
result = newIntNodeT(lastOrd(skipTypes(n[1].typ, abstractVar)), n)
|
||||||
else:
|
else:
|
||||||
var a = getArrayConstr(m, n.sons[1])
|
var a = getArrayConstr(m, n.sons[1])
|
||||||
|
|
@ -647,7 +663,14 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
if a == nil: return nil
|
if a == nil: return nil
|
||||||
result.sons[i] = a
|
result.sons[i] = a
|
||||||
incl(result.flags, nfAllConst)
|
incl(result.flags, nfAllConst)
|
||||||
of nkPar:
|
of nkObjConstr:
|
||||||
|
result = copyTree(n)
|
||||||
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
var a = getConstExpr(m, n.sons[i].sons[1])
|
||||||
|
if a == nil: return nil
|
||||||
|
result.sons[i].sons[1] = a
|
||||||
|
incl(result.flags, nfAllConst)
|
||||||
|
of nkPar:
|
||||||
# tuple constructor
|
# tuple constructor
|
||||||
result = copyTree(n)
|
result = copyTree(n)
|
||||||
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
|
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
|
||||||
|
|
@ -678,8 +701,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast:
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast:
|
||||||
var a = getConstExpr(m, n.sons[1])
|
var a = getConstExpr(m, n.sons[1])
|
||||||
if a == nil: return
|
if a == nil: return
|
||||||
result = foldConv(n, a)
|
result = foldConv(n, a, check=n.kind == nkHiddenStdConv)
|
||||||
of nkBracketExpr: result = foldArrayAccess(m, n)
|
of nkBracketExpr: result = foldArrayAccess(m, n)
|
||||||
of nkDotExpr: result = foldFieldAccess(m, n)
|
of nkDotExpr: result = foldFieldAccess(m, n)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
12
compiler/semgnrc.nim
Executable file → Normal file
12
compiler/semgnrc.nim
Executable file → Normal file
|
|
@ -30,7 +30,7 @@ proc getIdentNode(n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
illFormedAst(n)
|
illFormedAst(n)
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags,
|
proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags,
|
||||||
ctx: var TIntSet): PNode
|
ctx: var TIntSet): PNode
|
||||||
proc semGenericStmtScope(c: PContext, n: PNode,
|
proc semGenericStmtScope(c: PContext, n: PNode,
|
||||||
|
|
@ -63,12 +63,12 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
else:
|
else:
|
||||||
result = symChoice(c, n, s, scOpen)
|
result = symChoice(c, n, s, scOpen)
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
of skParam:
|
of skParam:
|
||||||
result = n
|
result = n
|
||||||
of skType:
|
of skType:
|
||||||
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
else: result = newSymNode(s, n.info)
|
else: result = newSymNode(s, n.info)
|
||||||
|
|
@ -156,13 +156,13 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
of skProc, skMethod, skIterator, skConverter:
|
of skProc, skMethod, skIterator, skConverter:
|
||||||
result.sons[0] = symChoice(c, n.sons[0], s, scOption)
|
result.sons[0] = symChoice(c, n.sons[0], s, scOption)
|
||||||
first = 1
|
first = 1
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
result.sons[0] = newSymNode(s, n.sons[0].info)
|
result.sons[0] = newSymNodeTypeDesc(s, n.sons[0].info)
|
||||||
first = 1
|
first = 1
|
||||||
of skType:
|
of skType:
|
||||||
# bad hack for generics:
|
# bad hack for generics:
|
||||||
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
||||||
result.sons[0] = newSymNode(s, n.sons[0].info)
|
result.sons[0] = newSymNodeTypeDesc(s, n.sons[0].info)
|
||||||
first = 1
|
first = 1
|
||||||
else:
|
else:
|
||||||
result.sons[0] = newSymNode(s, n.sons[0].info)
|
result.sons[0] = newSymNode(s, n.sons[0].info)
|
||||||
|
|
|
||||||
0
compiler/seminst.nim
Executable file → Normal file
0
compiler/seminst.nim
Executable file → Normal file
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -23,9 +23,10 @@ proc expectIntLit(c: PContext, n: PNode): int =
|
||||||
proc semInstantiationInfo(c: PContext, n: PNode): PNode =
|
proc semInstantiationInfo(c: PContext, n: PNode): PNode =
|
||||||
result = newNodeIT(nkPar, n.info, n.typ)
|
result = newNodeIT(nkPar, n.info, n.typ)
|
||||||
let idx = expectIntLit(c, n.sons[1])
|
let idx = expectIntLit(c, n.sons[1])
|
||||||
|
let useFullPaths = expectIntLit(c, n.sons[2])
|
||||||
let info = getInfoContext(idx)
|
let info = getInfoContext(idx)
|
||||||
var filename = newNodeIT(nkStrLit, n.info, getSysType(tyString))
|
var filename = newNodeIT(nkStrLit, n.info, getSysType(tyString))
|
||||||
filename.strVal = ToFilename(info)
|
filename.strVal = if useFullPaths != 0: info.toFullPath else: info.ToFilename
|
||||||
var line = newNodeIT(nkIntLit, n.info, getSysType(tyInt))
|
var line = newNodeIT(nkIntLit, n.info, getSysType(tyInt))
|
||||||
line.intVal = ToLinenumber(info)
|
line.intVal = ToLinenumber(info)
|
||||||
result.add(filename)
|
result.add(filename)
|
||||||
|
|
@ -73,6 +74,33 @@ proc semBindSym(c: PContext, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
LocalError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
|
LocalError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
|
||||||
|
|
||||||
|
proc semLocals(c: PContext, n: PNode): PNode =
|
||||||
|
var counter = 0
|
||||||
|
var tupleType = newTypeS(tyTuple, c)
|
||||||
|
result = newNodeIT(nkPar, n.info, tupleType)
|
||||||
|
tupleType.n = newNodeI(nkRecList, n.info)
|
||||||
|
# for now we skip openarrays ...
|
||||||
|
for i in countdown(c.tab.tos-1, ModuleTablePos+1):
|
||||||
|
for it in items(c.tab.stack[i]):
|
||||||
|
# XXX parameters' owners are wrong for generics; this caused some pain
|
||||||
|
# for closures too; we should finally fix it.
|
||||||
|
#if it.owner != c.p.owner: return result
|
||||||
|
if it.kind in skLocalVars and
|
||||||
|
it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
|
||||||
|
{tyVarargs, tyOpenArray, tyTypeDesc, tyExpr, tyStmt, tyEmpty}:
|
||||||
|
|
||||||
|
var field = newSym(skField, it.name, getCurrOwner(), n.info)
|
||||||
|
field.typ = it.typ.skipTypes({tyGenericInst, tyVar})
|
||||||
|
field.position = counter
|
||||||
|
inc(counter)
|
||||||
|
|
||||||
|
addSon(tupleType.n, newSymNode(field))
|
||||||
|
addSonSkipIntLit(tupleType, field.typ)
|
||||||
|
|
||||||
|
var a = newSymNode(it, result.info)
|
||||||
|
if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)
|
||||||
|
result.add(a)
|
||||||
|
|
||||||
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
|
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||||
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||||
flags: TExprFlags): PNode =
|
flags: TExprFlags): PNode =
|
||||||
|
|
@ -86,5 +114,6 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||||
of mOrd: result = semOrd(c, n)
|
of mOrd: result = semOrd(c, n)
|
||||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||||
of mNBindSym: result = semBindSym(c, n)
|
of mNBindSym: result = semBindSym(c, n)
|
||||||
|
of mLocals: result = semLocals(c, n)
|
||||||
else: result = n
|
else: result = n
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ import
|
||||||
# Second semantic checking pass over the AST. Necessary because the old
|
# Second semantic checking pass over the AST. Necessary because the old
|
||||||
# way had some inherent problems. Performs:
|
# way had some inherent problems. Performs:
|
||||||
#
|
#
|
||||||
# * procvar checks
|
|
||||||
# * effect+exception tracking
|
# * effect+exception tracking
|
||||||
# * closure analysis
|
|
||||||
# * checks for invalid usages of compiletime magics (not implemented)
|
# * checks for invalid usages of compiletime magics (not implemented)
|
||||||
# * checks for invalid usages of PNimNode (not implemented)
|
# * checks for invalid usages of PNimNode (not implemented)
|
||||||
# * later: will do an escape analysis for closures at least
|
# * later: will do an escape analysis for closures at least
|
||||||
|
|
|
||||||
178
compiler/semstmts.nim
Executable file → Normal file
178
compiler/semstmts.nim
Executable file → Normal file
|
|
@ -119,11 +119,11 @@ proc semWhile(c: PContext, n: PNode): PNode =
|
||||||
closeScope(c.tab)
|
closeScope(c.tab)
|
||||||
|
|
||||||
proc toCover(t: PType): biggestInt =
|
proc toCover(t: PType): biggestInt =
|
||||||
var t2 = skipTypes(t, abstractVarRange)
|
var t2 = skipTypes(t, abstractVarRange-{tyTypeDesc})
|
||||||
if t2.kind == tyEnum and enumHasHoles(t2):
|
if t2.kind == tyEnum and enumHasHoles(t2):
|
||||||
result = sonsLen(t2.n)
|
result = sonsLen(t2.n)
|
||||||
else:
|
else:
|
||||||
result = lengthOrd(skipTypes(t, abstractVar))
|
result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc}))
|
||||||
|
|
||||||
proc semCase(c: PContext, n: PNode): PNode =
|
proc semCase(c: PContext, n: PNode): PNode =
|
||||||
# check selector:
|
# check selector:
|
||||||
|
|
@ -133,7 +133,7 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||||
var chckCovered = false
|
var chckCovered = false
|
||||||
var covered: biggestint = 0
|
var covered: biggestint = 0
|
||||||
case skipTypes(n.sons[0].Typ, abstractVarRange).Kind
|
case skipTypes(n.sons[0].Typ, abstractVarRange-{tyTypeDesc}).Kind
|
||||||
of tyInt..tyInt64, tyChar, tyEnum:
|
of tyInt..tyInt64, tyChar, tyEnum:
|
||||||
chckCovered = true
|
chckCovered = true
|
||||||
of tyFloat..tyFloat128, tyString, tyError:
|
of tyFloat..tyFloat128, tyString, tyError:
|
||||||
|
|
@ -166,10 +166,10 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||||
proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
|
proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
|
||||||
result = fitNode(c, typ, n)
|
result = fitNode(c, typ, n)
|
||||||
if result.kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
if result.kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
||||||
changeType(result.sons[1], typ)
|
changeType(result.sons[1], typ, check=true)
|
||||||
result = result.sons[1]
|
result = result.sons[1]
|
||||||
elif not sameType(result.typ, typ):
|
elif not sameType(result.typ, typ):
|
||||||
changeType(result, typ)
|
changeType(result, typ, check=false)
|
||||||
|
|
||||||
proc findShadowedVar(c: PContext, v: PSym): PSym =
|
proc findShadowedVar(c: PContext, v: PSym): PSym =
|
||||||
for i in countdown(c.tab.tos - 2, ModuleTablePos+1):
|
for i in countdown(c.tab.tos - 2, ModuleTablePos+1):
|
||||||
|
|
@ -203,11 +203,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
var typ: PType
|
var typ: PType
|
||||||
if a.sons[length-2].kind != nkEmpty:
|
if a.sons[length-2].kind != nkEmpty:
|
||||||
typ = semTypeNode(c, a.sons[length-2], nil)
|
typ = semTypeNode(c, a.sons[length-2], nil)
|
||||||
else:
|
else:
|
||||||
typ = nil
|
typ = nil
|
||||||
var def: PNode
|
var def: PNode
|
||||||
if a.sons[length-1].kind != nkEmpty:
|
if a.sons[length-1].kind != nkEmpty:
|
||||||
def = semExprWithType(c, a.sons[length-1])
|
def = semExprWithType(c, a.sons[length-1], {efAllowDestructor})
|
||||||
# BUGFIX: ``fitNode`` is needed here!
|
# BUGFIX: ``fitNode`` is needed here!
|
||||||
# check type compability between def.typ and typ:
|
# check type compability between def.typ and typ:
|
||||||
if typ != nil: def = fitNode(c, typ, def)
|
if typ != nil: def = fitNode(c, typ, def)
|
||||||
|
|
@ -301,52 +301,109 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||||
addSon(b, copyTree(def))
|
addSon(b, copyTree(def))
|
||||||
addSon(result, b)
|
addSon(result, b)
|
||||||
|
|
||||||
proc transfFieldLoopBody(n: PNode, forLoop: PNode,
|
type
|
||||||
tupleType: PType,
|
TFieldInstCtx = object # either 'tup[i]' or 'field' is valid
|
||||||
tupleIndex, first: int): PNode =
|
tupleType: PType # if != nil we're traversing a tuple
|
||||||
|
tupleIndex: int
|
||||||
|
field: PSym
|
||||||
|
replaceByFieldName: bool
|
||||||
|
|
||||||
|
proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkEmpty..pred(nkIdent), succ(nkIdent)..nkNilLit: result = n
|
of nkEmpty..pred(nkIdent), succ(nkIdent)..nkNilLit: result = n
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
result = n
|
result = n
|
||||||
var L = sonsLen(forLoop)
|
var L = sonsLen(forLoop)
|
||||||
# field name:
|
if c.replaceByFieldName:
|
||||||
if first > 0:
|
|
||||||
if n.ident.id == forLoop[0].ident.id:
|
if n.ident.id == forLoop[0].ident.id:
|
||||||
if tupleType.n == nil:
|
let fieldName = if c.tupleType.isNil: c.field.name.s
|
||||||
# ugh, there are no field names:
|
elif c.tupleType.n.isNil: "Field" & $c.tupleIndex
|
||||||
result = newStrNode(nkStrLit, "")
|
else: c.tupleType.n.sons[c.tupleIndex].sym.name.s
|
||||||
else:
|
result = newStrNode(nkStrLit, fieldName)
|
||||||
result = newStrNode(nkStrLit, tupleType.n.sons[tupleIndex].sym.name.s)
|
|
||||||
return
|
return
|
||||||
# other fields:
|
# other fields:
|
||||||
for i in first..L-3:
|
for i in ord(c.replaceByFieldName)..L-3:
|
||||||
if n.ident.id == forLoop[i].ident.id:
|
if n.ident.id == forLoop[i].ident.id:
|
||||||
var call = forLoop.sons[L-2]
|
var call = forLoop.sons[L-2]
|
||||||
var tupl = call.sons[i+1-first]
|
var tupl = call.sons[i+1-ord(c.replaceByFieldName)]
|
||||||
result = newNodeI(nkBracketExpr, n.info)
|
if c.field.isNil:
|
||||||
result.add(tupl)
|
result = newNodeI(nkBracketExpr, n.info)
|
||||||
result.add(newIntNode(nkIntLit, tupleIndex))
|
result.add(tupl)
|
||||||
|
result.add(newIntNode(nkIntLit, c.tupleIndex))
|
||||||
|
else:
|
||||||
|
result = newNodeI(nkDotExpr, n.info)
|
||||||
|
result.add(tupl)
|
||||||
|
result.add(newSymNode(c.field, n.info))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
if n.kind == nkContinueStmt:
|
||||||
|
localError(n.info, errGenerated,
|
||||||
|
"'continue' not supported in a 'fields' loop")
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
newSons(result, sonsLen(n))
|
newSons(result, sonsLen(n))
|
||||||
for i in countup(0, sonsLen(n)-1):
|
for i in countup(0, sonsLen(n)-1):
|
||||||
result.sons[i] = transfFieldLoopBody(n.sons[i], forLoop,
|
result.sons[i] = instFieldLoopBody(c, n.sons[i], forLoop)
|
||||||
tupleType, tupleIndex, first)
|
|
||||||
|
|
||||||
proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
type
|
||||||
# so that 'break' etc. work as expected, we produce
|
TFieldsCtx = object
|
||||||
|
c: PContext
|
||||||
|
m: TMagic
|
||||||
|
|
||||||
|
proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) =
|
||||||
|
case typ.kind
|
||||||
|
of nkSym:
|
||||||
|
var fc: TFieldInstCtx # either 'tup[i]' or 'field' is valid
|
||||||
|
fc.field = typ.sym
|
||||||
|
fc.replaceByFieldName = c.m == mFieldPairs
|
||||||
|
openScope(c.c.tab)
|
||||||
|
inc c.c.InUnrolledContext
|
||||||
|
let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop)
|
||||||
|
father.add(SemStmt(c.c, body))
|
||||||
|
dec c.c.InUnrolledContext
|
||||||
|
closeScope(c.c.tab)
|
||||||
|
of nkNilLit: nil
|
||||||
|
of nkRecCase:
|
||||||
|
let L = forLoop.len
|
||||||
|
let call = forLoop.sons[L-2]
|
||||||
|
if call.len > 2:
|
||||||
|
LocalError(forLoop.info, errGenerated,
|
||||||
|
"parallel 'fields' iterator does not work for 'case' objects")
|
||||||
|
return
|
||||||
|
# iterate over the selector:
|
||||||
|
semForObjectFields(c, typ[0], forLoop, father)
|
||||||
|
# we need to generate a case statement:
|
||||||
|
var caseStmt = newNodeI(nkCaseStmt, forLoop.info)
|
||||||
|
# generate selector:
|
||||||
|
var access = newNodeI(nkDotExpr, forLoop.info, 2)
|
||||||
|
access.sons[0] = call.sons[1]
|
||||||
|
access.sons[1] = newSymNode(typ.sons[0].sym, forLoop.info)
|
||||||
|
caseStmt.add(semExprWithType(c.c, access))
|
||||||
|
# copy the branches over, but replace the fields with the for loop body:
|
||||||
|
for i in 1 .. <typ.len:
|
||||||
|
var branch = copyTree(typ[i])
|
||||||
|
let L = branch.len
|
||||||
|
branch.sons[L-1] = newNodeI(nkStmtList, forLoop.info)
|
||||||
|
semForObjectFields(c, typ[i].lastSon, forLoop, branch[L-1])
|
||||||
|
caseStmt.add(branch)
|
||||||
|
father.add(caseStmt)
|
||||||
|
of nkRecList:
|
||||||
|
for t in items(typ): semForObjectFields(c, t, forLoop, father)
|
||||||
|
else:
|
||||||
|
illFormedAst(typ)
|
||||||
|
|
||||||
|
proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
|
# so that 'break' etc. work as expected, we produce
|
||||||
# a 'while true: stmt; break' loop ...
|
# a 'while true: stmt; break' loop ...
|
||||||
result = newNodeI(nkWhileStmt, n.info)
|
result = newNodeI(nkWhileStmt, n.info, 2)
|
||||||
var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true")
|
var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true")
|
||||||
if trueSymbol == nil:
|
if trueSymbol == nil:
|
||||||
LocalError(n.info, errSystemNeeds, "true")
|
LocalError(n.info, errSystemNeeds, "true")
|
||||||
trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(), n.info)
|
trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(), n.info)
|
||||||
trueSymbol.typ = getSysType(tyBool)
|
trueSymbol.typ = getSysType(tyBool)
|
||||||
|
|
||||||
result.add(newSymNode(trueSymbol, n.info))
|
result.sons[0] = newSymNode(trueSymbol, n.info)
|
||||||
var stmts = newNodeI(nkStmtList, n.info)
|
var stmts = newNodeI(nkStmtList, n.info)
|
||||||
result.add(stmts)
|
result.sons[1] = stmts
|
||||||
|
|
||||||
var length = sonsLen(n)
|
var length = sonsLen(n)
|
||||||
var call = n.sons[length-2]
|
var call = n.sons[length-2]
|
||||||
|
|
@ -354,23 +411,34 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
LocalError(n.info, errWrongNumberOfVariables)
|
LocalError(n.info, errWrongNumberOfVariables)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar)
|
var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar-{tyTypeDesc})
|
||||||
if tupleTypeA.kind != tyTuple: InternalError(n.info, "no tuple type!")
|
if tupleTypeA.kind notin {tyTuple, tyObject}:
|
||||||
|
localError(n.info, errGenerated, "no object or tuple type")
|
||||||
|
return result
|
||||||
for i in 1..call.len-1:
|
for i in 1..call.len-1:
|
||||||
var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar)
|
var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar-{tyTypeDesc})
|
||||||
if not SameType(tupleTypeA, tupleTypeB):
|
if not SameType(tupleTypeA, tupleTypeB):
|
||||||
typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
|
typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
|
||||||
|
|
||||||
Inc(c.p.nestedLoopCounter)
|
Inc(c.p.nestedLoopCounter)
|
||||||
var loopBody = n.sons[length-1]
|
if tupleTypeA.kind == tyTuple:
|
||||||
for i in 0..sonsLen(tupleTypeA)-1:
|
var loopBody = n.sons[length-1]
|
||||||
openScope(c.tab)
|
for i in 0..sonsLen(tupleTypeA)-1:
|
||||||
var body = transfFieldLoopBody(loopBody, n, tupleTypeA, i,
|
openScope(c.tab)
|
||||||
ord(m==mFieldPairs))
|
var fc: TFieldInstCtx
|
||||||
inc c.InUnrolledContext
|
fc.tupleType = tupleTypeA
|
||||||
stmts.add(SemStmt(c, body))
|
fc.tupleIndex = i
|
||||||
dec c.InUnrolledContext
|
fc.replaceByFieldName = m == mFieldPairs
|
||||||
closeScope(c.tab)
|
var body = instFieldLoopBody(fc, loopBody, n)
|
||||||
|
inc c.InUnrolledContext
|
||||||
|
stmts.add(SemStmt(c, body))
|
||||||
|
dec c.InUnrolledContext
|
||||||
|
closeScope(c.tab)
|
||||||
|
else:
|
||||||
|
var fc: TFieldsCtx
|
||||||
|
fc.m = m
|
||||||
|
fc.c = c
|
||||||
|
semForObjectFields(fc, tupleTypeA.n, n, stmts)
|
||||||
Dec(c.p.nestedLoopCounter)
|
Dec(c.p.nestedLoopCounter)
|
||||||
var b = newNodeI(nkBreakStmt, n.info)
|
var b = newNodeI(nkBreakStmt, n.info)
|
||||||
b.add(ast.emptyNode)
|
b.add(ast.emptyNode)
|
||||||
|
|
@ -416,10 +484,17 @@ proc semForVars(c: PContext, n: PNode): PNode =
|
||||||
n.sons[length-1] = SemStmt(c, n.sons[length-1])
|
n.sons[length-1] = SemStmt(c, n.sons[length-1])
|
||||||
Dec(c.p.nestedLoopCounter)
|
Dec(c.p.nestedLoopCounter)
|
||||||
|
|
||||||
|
proc newDeref(n: PNode): PNode {.inline.} =
|
||||||
|
result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0])
|
||||||
|
addSon(result, n)
|
||||||
|
|
||||||
proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =
|
proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =
|
||||||
result = newNodeI(nkCall, arg.info)
|
result = newNodeI(nkCall, arg.info)
|
||||||
result.add(newIdentNode(it.getIdent, arg.info))
|
result.add(newIdentNode(it.getIdent, arg.info))
|
||||||
result.add(arg)
|
if arg.typ != nil and arg.typ.kind == tyVar:
|
||||||
|
result.add newDeref(arg)
|
||||||
|
else:
|
||||||
|
result.add arg
|
||||||
result = semExprNoDeref(c, result, {efWantIterator})
|
result = semExprNoDeref(c, result, {efWantIterator})
|
||||||
|
|
||||||
proc semFor(c: PContext, n: PNode): PNode =
|
proc semFor(c: PContext, n: PNode): PNode =
|
||||||
|
|
@ -705,8 +780,7 @@ proc activate(c: PContext, n: PNode) =
|
||||||
# XXX: This proc is part of my plan for getting rid of
|
# XXX: This proc is part of my plan for getting rid of
|
||||||
# forward declarations. stay tuned.
|
# forward declarations. stay tuned.
|
||||||
when false:
|
when false:
|
||||||
# well for now it breaks code ... I added the test case in main.nim of the
|
# well for now it breaks code ...
|
||||||
# compiler itself to break bootstrapping :P
|
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkLambdaKinds:
|
of nkLambdaKinds:
|
||||||
discard semLambda(c, n, {})
|
discard semLambda(c, n, {})
|
||||||
|
|
@ -994,7 +1068,7 @@ proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
proc generateDestructor(c: PContext, t: PType): PNode =
|
proc generateDestructor(c: PContext, t: PType): PNode =
|
||||||
## generate a destructor for a user-defined object ot tuple type
|
## generate a destructor for a user-defined object or tuple type
|
||||||
## returns nil if the destructor turns out to be trivial
|
## returns nil if the destructor turns out to be trivial
|
||||||
|
|
||||||
template addLine(e: expr): stmt =
|
template addLine(e: expr): stmt =
|
||||||
|
|
@ -1029,7 +1103,7 @@ proc instantiateDestructor*(c: PContext, typ: PType): bool =
|
||||||
|
|
||||||
if t.destructor != nil:
|
if t.destructor != nil:
|
||||||
# XXX: This is not entirely correct for recursive types, but we need
|
# XXX: This is not entirely correct for recursive types, but we need
|
||||||
# it temporarily to hide the "destroy is alrady defined" problem
|
# it temporarily to hide the "destroy is already defined" problem
|
||||||
return t.destructor notin [AnalyzingDestructor, DestructorIsTrivial]
|
return t.destructor notin [AnalyzingDestructor, DestructorIsTrivial]
|
||||||
|
|
||||||
case t.kind
|
case t.kind
|
||||||
|
|
@ -1071,8 +1145,8 @@ proc instantiateDestructor*(c: PContext, typ: PType): bool =
|
||||||
else:
|
else:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc insertDestructors(c: PContext, varSection: PNode):
|
proc insertDestructors(c: PContext,
|
||||||
tuple[outer: PNode, inner: PNode] =
|
varSection: PNode): tuple[outer, inner: PNode] =
|
||||||
# Accepts a var or let section.
|
# Accepts a var or let section.
|
||||||
#
|
#
|
||||||
# When a var section has variables with destructors
|
# When a var section has variables with destructors
|
||||||
|
|
@ -1128,7 +1202,7 @@ proc insertDestructors(c: PContext, varSection: PNode):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
proc ImplicitelyDiscardable(n: PNode): bool =
|
proc ImplicitlyDiscardable(n: PNode): bool =
|
||||||
result = isCallExpr(n) and n.sons[0].kind == nkSym and
|
result = isCallExpr(n) and n.sons[0].kind == nkSym and
|
||||||
sfDiscardable in n.sons[0].sym.flags
|
sfDiscardable in n.sons[0].sym.flags
|
||||||
|
|
||||||
|
|
@ -1179,7 +1253,7 @@ proc semStmtList(c: PContext, n: PNode): PNode =
|
||||||
# a statement list (s; e) has the type 'e':
|
# a statement list (s; e) has the type 'e':
|
||||||
if result.kind == nkStmtList and result.len > 0:
|
if result.kind == nkStmtList and result.len > 0:
|
||||||
var lastStmt = lastSon(result)
|
var lastStmt = lastSon(result)
|
||||||
if lastStmt.kind != nkNilLit and not ImplicitelyDiscardable(lastStmt):
|
if lastStmt.kind != nkNilLit and not ImplicitlyDiscardable(lastStmt):
|
||||||
result.typ = lastStmt.typ
|
result.typ = lastStmt.typ
|
||||||
#localError(lastStmt.info, errGenerated,
|
#localError(lastStmt.info, errGenerated,
|
||||||
# "Last expression must be explicitly returned if it " &
|
# "Last expression must be explicitly returned if it " &
|
||||||
|
|
|
||||||
0
compiler/semtempl.nim
Executable file → Normal file
0
compiler/semtempl.nim
Executable file → Normal file
6
compiler/semthreads.nim
Executable file → Normal file
6
compiler/semthreads.nim
Executable file → Normal file
|
|
@ -311,6 +311,12 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
|
||||||
# container construction:
|
# container construction:
|
||||||
result = toNil # nothing until later
|
result = toNil # nothing until later
|
||||||
for i in 0..n.len-1: aggregateOwner(result, analyse(c, n[i]))
|
for i in 0..n.len-1: aggregateOwner(result, analyse(c, n[i]))
|
||||||
|
of nkObjConstr:
|
||||||
|
if n.typ != nil and containsGarbageCollectedRef(n.typ):
|
||||||
|
result = toMine
|
||||||
|
else:
|
||||||
|
result = toNil # nothing until later
|
||||||
|
for i in 1..n.len-1: aggregateOwner(result, analyse(c, n[i]))
|
||||||
of nkAddr, nkHiddenAddr:
|
of nkAddr, nkHiddenAddr:
|
||||||
var a = lvalueSym(n)
|
var a = lvalueSym(n)
|
||||||
if a.kind == nkSym:
|
if a.kind == nkSym:
|
||||||
|
|
|
||||||
21
compiler/semtypes.nim
Executable file → Normal file
21
compiler/semtypes.nim
Executable file → Normal file
|
|
@ -45,7 +45,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||||
e = newSymS(skEnumField, n.sons[i].sons[0], c)
|
e = newSymS(skEnumField, n.sons[i].sons[0], c)
|
||||||
var v = semConstExpr(c, n.sons[i].sons[1])
|
var v = semConstExpr(c, n.sons[i].sons[1])
|
||||||
var strVal: PNode = nil
|
var strVal: PNode = nil
|
||||||
case skipTypes(v.typ, abstractInst).kind
|
case skipTypes(v.typ, abstractInst-{tyTypeDesc}).kind
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
if sonsLen(v) == 2:
|
if sonsLen(v) == 2:
|
||||||
strVal = v.sons[1] # second tuple part is the string value
|
strVal = v.sons[1] # second tuple part is the string value
|
||||||
|
|
@ -222,10 +222,11 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||||
let bound = result.typ.sons[0].sym
|
let bound = result.typ.sons[0].sym
|
||||||
if bound != nil:
|
if bound != nil:
|
||||||
return bound
|
return bound
|
||||||
else:
|
return result
|
||||||
return result.typ.sym
|
if result.typ.sym == nil:
|
||||||
else:
|
LocalError(n.info, errTypeExpected)
|
||||||
return result.typ.sym
|
return errorSym(c, n)
|
||||||
|
return result.typ.sym
|
||||||
if result.kind != skType:
|
if result.kind != skType:
|
||||||
# this implements the wanted ``var v: V, x: V`` feature ...
|
# this implements the wanted ``var v: V, x: V`` feature ...
|
||||||
var ov: TOverloadIter
|
var ov: TOverloadIter
|
||||||
|
|
@ -323,8 +324,8 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var biggestInt): PNode
|
||||||
checkMinSonsLen(t, 1)
|
checkMinSonsLen(t, 1)
|
||||||
let ac = semConstExpr(c, a)
|
let ac = semConstExpr(c, a)
|
||||||
let bc = semConstExpr(c, b)
|
let bc = semConstExpr(c, b)
|
||||||
let at = fitNode(c, t.sons[0].typ, ac)
|
let at = fitNode(c, t.sons[0].typ, ac).skipConvTakeType
|
||||||
let bt = fitNode(c, t.sons[0].typ, bc)
|
let bt = fitNode(c, t.sons[0].typ, bc).skipConvTakeType
|
||||||
|
|
||||||
result = newNodeI(nkRange, a.info)
|
result = newNodeI(nkRange, a.info)
|
||||||
result.add(at)
|
result.add(at)
|
||||||
|
|
@ -388,7 +389,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||||
return
|
return
|
||||||
incl(a.sons[0].sym.flags, sfDiscriminant)
|
incl(a.sons[0].sym.flags, sfDiscriminant)
|
||||||
var covered: biggestInt = 0
|
var covered: biggestInt = 0
|
||||||
var typ = skipTypes(a.sons[0].Typ, abstractVar)
|
var typ = skipTypes(a.sons[0].Typ, abstractVar-{tyTypeDesc})
|
||||||
if not isOrdinalType(typ):
|
if not isOrdinalType(typ):
|
||||||
LocalError(n.info, errSelectorMustBeOrdinal)
|
LocalError(n.info, errSelectorMustBeOrdinal)
|
||||||
elif firstOrd(typ) < 0:
|
elif firstOrd(typ) < 0:
|
||||||
|
|
@ -873,6 +874,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
if s.typ == nil:
|
if s.typ == nil:
|
||||||
if s.kind != skError: LocalError(n.info, errTypeExpected)
|
if s.kind != skError: LocalError(n.info, errTypeExpected)
|
||||||
result = newOrPrevType(tyError, prev, c)
|
result = newOrPrevType(tyError, prev, c)
|
||||||
|
elif s.kind == skParam and s.typ.kind == tyTypeDesc:
|
||||||
|
assert s.typ.len > 0
|
||||||
|
InternalAssert prev == nil
|
||||||
|
result = s.typ.sons[0]
|
||||||
elif prev == nil:
|
elif prev == nil:
|
||||||
result = s.typ
|
result = s.typ
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
0
compiler/semtypinst.nim
Executable file → Normal file
0
compiler/semtypinst.nim
Executable file → Normal file
|
|
@ -73,6 +73,9 @@ proc serve*(action: proc (){.nimcall.}) =
|
||||||
var line = stdin.readLine.string
|
var line = stdin.readLine.string
|
||||||
if line == "quit": quit()
|
if line == "quit": quit()
|
||||||
execute line
|
execute line
|
||||||
|
echo ""
|
||||||
|
FlushFile(stdout)
|
||||||
|
|
||||||
of "tcp", "":
|
of "tcp", "":
|
||||||
var server = Socket()
|
var server = Socket()
|
||||||
let p = getConfigVar("server.port")
|
let p = getConfigVar("server.port")
|
||||||
|
|
@ -83,11 +86,10 @@ proc serve*(action: proc (){.nimcall.}) =
|
||||||
new(stdoutSocket)
|
new(stdoutSocket)
|
||||||
while true:
|
while true:
|
||||||
accept(server, stdoutSocket)
|
accept(server, stdoutSocket)
|
||||||
discard stdoutSocket.recvLine(inp)
|
stdoutSocket.readLine(inp)
|
||||||
execute inp.string
|
execute inp.string
|
||||||
stdoutSocket.send("\c\L")
|
stdoutSocket.send("\c\L")
|
||||||
stdoutSocket.close()
|
stdoutSocket.close()
|
||||||
else:
|
else:
|
||||||
echo "Invalid server.type:", typ
|
echo "Invalid server.type:", typ
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
|
|
|
||||||
146
compiler/sigmatch.nim
Executable file → Normal file
146
compiler/sigmatch.nim
Executable file → Normal file
|
|
@ -97,6 +97,45 @@ proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
||||||
a.baseTypeMatch = b.baseTypeMatch
|
a.baseTypeMatch = b.baseTypeMatch
|
||||||
copyIdTable(a.bindings, b.bindings)
|
copyIdTable(a.bindings, b.bindings)
|
||||||
|
|
||||||
|
proc sumGeneric(t: PType): int =
|
||||||
|
var t = t
|
||||||
|
while true:
|
||||||
|
case t.kind
|
||||||
|
of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyArrayConstr,
|
||||||
|
tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody:
|
||||||
|
t = t.lastSon
|
||||||
|
inc result
|
||||||
|
of tyVar:
|
||||||
|
# but do not make 'var T' more specific than 'T'!
|
||||||
|
t = t.sons[0]
|
||||||
|
of tyGenericInvokation, tyTuple:
|
||||||
|
result = ord(t.kind == tyGenericInvokation)
|
||||||
|
for i in 0 .. <t.len: result += t.sons[i].sumGeneric
|
||||||
|
break
|
||||||
|
of tyGenericParam, tyExpr, tyStmt, tyTypeDesc, tyTypeClass: break
|
||||||
|
else: return 0
|
||||||
|
|
||||||
|
proc complexDisambiguation(a, b: PType): int =
|
||||||
|
var x, y: int
|
||||||
|
for i in 1 .. <a.len: x += a.sons[i].sumGeneric
|
||||||
|
for i in 1 .. <b.len: y += b.sons[i].sumGeneric
|
||||||
|
result = x - y
|
||||||
|
when false:
|
||||||
|
proc betterThan(a, b: PType): bool {.inline.} = a.sumGeneric > b.sumGeneric
|
||||||
|
|
||||||
|
if a.len > 1 and b.len > 1:
|
||||||
|
let aa = a.sons[1].sumGeneric
|
||||||
|
let bb = b.sons[1].sumGeneric
|
||||||
|
var a = a
|
||||||
|
var b = b
|
||||||
|
|
||||||
|
if aa < bb: swap(a, b)
|
||||||
|
# all must be better
|
||||||
|
for i in 2 .. <min(a.len, b.len):
|
||||||
|
if not a.sons[i].betterThan(b.sons[i]): return 0
|
||||||
|
# a must be longer or of the same length as b:
|
||||||
|
result = a.len - b.len
|
||||||
|
|
||||||
proc cmpCandidates*(a, b: TCandidate): int =
|
proc cmpCandidates*(a, b: TCandidate): int =
|
||||||
result = a.exactMatches - b.exactMatches
|
result = a.exactMatches - b.exactMatches
|
||||||
if result != 0: return
|
if result != 0: return
|
||||||
|
|
@ -110,9 +149,12 @@ proc cmpCandidates*(a, b: TCandidate): int =
|
||||||
if result != 0: return
|
if result != 0: return
|
||||||
if (a.calleeScope != -1) and (b.calleeScope != -1):
|
if (a.calleeScope != -1) and (b.calleeScope != -1):
|
||||||
result = a.calleeScope - b.calleeScope
|
result = a.calleeScope - b.calleeScope
|
||||||
if result != 0: return
|
if result != 0: return
|
||||||
# the other way round because of other semantics:
|
# the other way round because of other semantics:
|
||||||
result = b.inheritancePenalty - a.inheritancePenalty
|
result = b.inheritancePenalty - a.inheritancePenalty
|
||||||
|
if result != 0: return
|
||||||
|
# prefer more specialized generic over more general generic:
|
||||||
|
result = complexDisambiguation(a.callee, b.callee)
|
||||||
|
|
||||||
proc writeMatches*(c: TCandidate) =
|
proc writeMatches*(c: TCandidate) =
|
||||||
Writeln(stdout, "exact matches: " & $c.exactMatches)
|
Writeln(stdout, "exact matches: " & $c.exactMatches)
|
||||||
|
|
@ -129,12 +171,19 @@ proc NotFoundError*(c: PContext, n: PNode) =
|
||||||
# fail fast:
|
# fail fast:
|
||||||
GlobalError(n.info, errTypeMismatch, "")
|
GlobalError(n.info, errTypeMismatch, "")
|
||||||
var result = msgKindToString(errTypeMismatch)
|
var result = msgKindToString(errTypeMismatch)
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
#debug(n.sons[i].typ)
|
var nt = n.sons[i].typ
|
||||||
if n.sons[i].kind == nkExprEqExpr:
|
if n.sons[i].kind == nkExprEqExpr:
|
||||||
add(result, renderTree(n.sons[i].sons[0]))
|
add(result, renderTree(n.sons[i].sons[0]))
|
||||||
add(result, ": ")
|
add(result, ": ")
|
||||||
let nt = n.sons[i].typ
|
if nt.isNil:
|
||||||
|
n.sons[i].sons[1] = c.semOperand(c, n.sons[i].sons[1])
|
||||||
|
nt = n.sons[i].sons[1].typ
|
||||||
|
n.sons[i].typ = nt
|
||||||
|
else:
|
||||||
|
if nt.isNil:
|
||||||
|
n.sons[i] = c.semOperand(c, n.sons[i])
|
||||||
|
nt = n.sons[i].typ
|
||||||
if nt.kind == tyError: return
|
if nt.kind == tyError: return
|
||||||
add(result, typeToString(nt))
|
add(result, typeToString(nt))
|
||||||
if i != sonsLen(n) - 1: add(result, ", ")
|
if i != sonsLen(n) - 1: add(result, ", ")
|
||||||
|
|
@ -146,7 +195,6 @@ proc NotFoundError*(c: PContext, n: PNode) =
|
||||||
if sym.kind in RoutineKinds:
|
if sym.kind in RoutineKinds:
|
||||||
add(candidates, getProcHeader(sym))
|
add(candidates, getProcHeader(sym))
|
||||||
add(candidates, "\n")
|
add(candidates, "\n")
|
||||||
#debug(sym.typ)
|
|
||||||
sym = nextOverloadIter(o, c, n.sons[0])
|
sym = nextOverloadIter(o, c, n.sons[0])
|
||||||
if candidates != "":
|
if candidates != "":
|
||||||
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
|
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
|
||||||
|
|
@ -314,6 +362,22 @@ proc matchTypeClass(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
result = if matchTypeClass(c.bindings, f, a): isGeneric
|
result = if matchTypeClass(c.bindings, f, a): isGeneric
|
||||||
else: isNone
|
else: isNone
|
||||||
|
|
||||||
|
proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
|
||||||
|
let
|
||||||
|
a0 = firstOrd(a)
|
||||||
|
a1 = lastOrd(a)
|
||||||
|
f0 = firstOrd(f)
|
||||||
|
f1 = lastOrd(f)
|
||||||
|
if a0 == f0 and a1 == f1:
|
||||||
|
result = isEqual
|
||||||
|
elif a0 >= f0 and a1 <= f1:
|
||||||
|
result = isConvertible
|
||||||
|
elif a0 <= f1 and f0 <= a1:
|
||||||
|
# X..Y and C..D overlap iff (X <= D and C <= Y)
|
||||||
|
result = isConvertible
|
||||||
|
else:
|
||||||
|
result = isNone
|
||||||
|
|
||||||
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
# is a subtype of f?
|
# is a subtype of f?
|
||||||
result = isNone
|
result = isNone
|
||||||
|
|
@ -338,6 +402,8 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
result = typeRel(c, base(f), base(a))
|
result = typeRel(c, base(f), base(a))
|
||||||
# bugfix: accept integer conversions here
|
# bugfix: accept integer conversions here
|
||||||
#if result < isGeneric: result = isNone
|
#if result < isGeneric: result = isNone
|
||||||
|
if result notin {isNone, isGeneric}:
|
||||||
|
result = typeRangeRel(f, a)
|
||||||
elif skipTypes(f, {tyRange}).kind == a.kind:
|
elif skipTypes(f, {tyRange}).kind == a.kind:
|
||||||
result = isIntConv
|
result = isIntConv
|
||||||
elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
|
elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
|
||||||
|
|
@ -655,7 +721,8 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
|
||||||
of isSubrange:
|
of isSubrange:
|
||||||
inc(m.subtypeMatches)
|
inc(m.subtypeMatches)
|
||||||
result = copyTree(arg)
|
#result = copyTree(arg)
|
||||||
|
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
||||||
of isGeneric:
|
of isGeneric:
|
||||||
inc(m.genericMatches)
|
inc(m.genericMatches)
|
||||||
if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}:
|
if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}:
|
||||||
|
|
@ -669,7 +736,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
result = copyTree(arg)
|
result = copyTree(arg)
|
||||||
result.typ = getInstantiatedType(c, arg, m, f)
|
result.typ = getInstantiatedType(c, arg, m, f)
|
||||||
# BUG: f may not be the right key!
|
# BUG: f may not be the right key!
|
||||||
if skipTypes(result.typ, abstractVar).kind in {tyTuple}:
|
if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
||||||
# BUGFIX: use ``result.typ`` and not `f` here
|
# BUGFIX: use ``result.typ`` and not `f` here
|
||||||
of isFromIntLit:
|
of isFromIntLit:
|
||||||
|
|
@ -680,7 +747,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
of isEqual:
|
of isEqual:
|
||||||
inc(m.exactMatches)
|
inc(m.exactMatches)
|
||||||
result = copyTree(arg)
|
result = copyTree(arg)
|
||||||
if skipTypes(f, abstractVar).kind in {tyTuple}:
|
if skipTypes(f, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
||||||
of isNone:
|
of isNone:
|
||||||
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
|
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
|
||||||
|
|
@ -756,6 +823,28 @@ proc setSon(father: PNode, at: int, son: PNode) =
|
||||||
if sonsLen(father) <= at: setlen(father.sons, at + 1)
|
if sonsLen(father) <= at: setlen(father.sons, at + 1)
|
||||||
father.sons[at] = son
|
father.sons[at] = son
|
||||||
|
|
||||||
|
# we are allowed to modify the calling node in the 'prepare*' procs:
|
||||||
|
proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
|
||||||
|
if formal.kind == tyExpr and formal.len != 1:
|
||||||
|
# {tyTypeDesc, tyExpr, tyStmt, tyProxy}:
|
||||||
|
# a.typ == nil is valid
|
||||||
|
result = a
|
||||||
|
elif a.typ.isNil:
|
||||||
|
result = c.semOperand(c, a, {efDetermineType})
|
||||||
|
else:
|
||||||
|
result = a
|
||||||
|
|
||||||
|
proc prepareOperand(c: PContext; a: PNode): PNode =
|
||||||
|
if a.typ.isNil:
|
||||||
|
result = c.semOperand(c, a, {efDetermineType})
|
||||||
|
else:
|
||||||
|
result = a
|
||||||
|
|
||||||
|
proc prepareNamedParam(a: PNode) =
|
||||||
|
if a.sons[0].kind != nkIdent:
|
||||||
|
var info = a.sons[0].info
|
||||||
|
a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info)
|
||||||
|
|
||||||
proc matchesAux(c: PContext, n, nOrig: PNode,
|
proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
m: var TCandidate, marker: var TIntSet) =
|
m: var TCandidate, marker: var TIntSet) =
|
||||||
template checkConstraint(n: expr) {.immediate, dirty.} =
|
template checkConstraint(n: expr) {.immediate, dirty.} =
|
||||||
|
|
@ -780,6 +869,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
if n.sons[a].kind == nkExprEqExpr:
|
if n.sons[a].kind == nkExprEqExpr:
|
||||||
# named param
|
# named param
|
||||||
# check if m.callee has such a param:
|
# check if m.callee has such a param:
|
||||||
|
prepareNamedParam(n.sons[a])
|
||||||
if n.sons[a].sons[0].kind != nkIdent:
|
if n.sons[a].sons[0].kind != nkIdent:
|
||||||
LocalError(n.sons[a].info, errNamedParamHasToBeIdent)
|
LocalError(n.sons[a].info, errNamedParamHasToBeIdent)
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
|
|
@ -795,9 +885,11 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
return
|
return
|
||||||
m.baseTypeMatch = false
|
m.baseTypeMatch = false
|
||||||
|
n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1])
|
||||||
|
n.sons[a].typ = n.sons[a].sons[1].typ
|
||||||
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
||||||
n.sons[a].sons[1], nOrig.sons[a].sons[1])
|
n.sons[a].sons[1], nOrig.sons[a].sons[1])
|
||||||
if arg == nil:
|
if arg == nil:
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
return
|
return
|
||||||
checkConstraint(n.sons[a].sons[1])
|
checkConstraint(n.sons[a].sons[1])
|
||||||
|
|
@ -809,30 +901,33 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
if f != formalLen - 1: container = nil
|
if f != formalLen - 1: container = nil
|
||||||
else:
|
else:
|
||||||
setSon(m.call, formal.position + 1, arg)
|
setSon(m.call, formal.position + 1, arg)
|
||||||
else:
|
else:
|
||||||
# unnamed param
|
# unnamed param
|
||||||
if f >= formalLen:
|
if f >= formalLen:
|
||||||
# too many arguments?
|
# too many arguments?
|
||||||
if tfVarArgs in m.callee.flags:
|
if tfVarArgs in m.callee.flags:
|
||||||
# is ok... but don't increment any counters...
|
# is ok... but don't increment any counters...
|
||||||
if skipTypes(n.sons[a].typ, abstractVar).kind == tyString:
|
# we have no formal here to snoop at:
|
||||||
addSon(m.call, implicitConv(nkHiddenStdConv, getSysType(tyCString),
|
n.sons[a] = prepareOperand(c, n.sons[a])
|
||||||
|
if skipTypes(n.sons[a].typ, abstractVar-{tyTypeDesc}).kind==tyString:
|
||||||
|
addSon(m.call, implicitConv(nkHiddenStdConv, getSysType(tyCString),
|
||||||
copyTree(n.sons[a]), m, c))
|
copyTree(n.sons[a]), m, c))
|
||||||
else:
|
else:
|
||||||
addSon(m.call, copyTree(n.sons[a]))
|
addSon(m.call, copyTree(n.sons[a]))
|
||||||
elif formal != nil:
|
elif formal != nil:
|
||||||
m.baseTypeMatch = false
|
m.baseTypeMatch = false
|
||||||
|
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
|
||||||
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
||||||
n.sons[a], nOrig.sons[a])
|
n.sons[a], nOrig.sons[a])
|
||||||
if (arg != nil) and m.baseTypeMatch and (container != nil):
|
if (arg != nil) and m.baseTypeMatch and (container != nil):
|
||||||
addSon(container, arg)
|
addSon(container, arg)
|
||||||
else:
|
else:
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
if m.callee.n.sons[f].kind != nkSym:
|
if m.callee.n.sons[f].kind != nkSym:
|
||||||
InternalError(n.sons[a].info, "matches")
|
InternalError(n.sons[a].info, "matches")
|
||||||
return
|
return
|
||||||
|
|
@ -843,6 +938,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
return
|
return
|
||||||
m.baseTypeMatch = false
|
m.baseTypeMatch = false
|
||||||
|
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
|
||||||
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
|
||||||
n.sons[a], nOrig.sons[a])
|
n.sons[a], nOrig.sons[a])
|
||||||
if arg == nil:
|
if arg == nil:
|
||||||
|
|
@ -855,12 +951,18 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
setSon(m.call, formal.position + 1,
|
setSon(m.call, formal.position + 1,
|
||||||
implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
|
implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
|
||||||
if f != formalLen - 1: container = nil
|
if f != formalLen - 1: container = nil
|
||||||
else:
|
else:
|
||||||
setSon(m.call, formal.position + 1, arg)
|
setSon(m.call, formal.position + 1, arg)
|
||||||
checkConstraint(n.sons[a])
|
checkConstraint(n.sons[a])
|
||||||
inc(a)
|
inc(a)
|
||||||
inc(f)
|
inc(f)
|
||||||
|
|
||||||
|
proc semFinishOperands*(c: PContext, n: PNode) =
|
||||||
|
# this needs to be called to ensure that after overloading resolution every
|
||||||
|
# argument has been sem'checked:
|
||||||
|
for i in 1 .. <n.len:
|
||||||
|
n.sons[i] = prepareOperand(c, n.sons[i])
|
||||||
|
|
||||||
proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||||
# for 'suggest' support:
|
# for 'suggest' support:
|
||||||
var marker = initIntSet()
|
var marker = initIntSet()
|
||||||
|
|
|
||||||
0
compiler/suggest.nim
Executable file → Normal file
0
compiler/suggest.nim
Executable file → Normal file
0
compiler/syntaxes.nim
Executable file → Normal file
0
compiler/syntaxes.nim
Executable file → Normal file
0
compiler/tccgen.nim
Executable file → Normal file
0
compiler/tccgen.nim
Executable file → Normal file
11
compiler/transf.nim
Executable file → Normal file
11
compiler/transf.nim
Executable file → Normal file
|
|
@ -323,10 +323,10 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
|
||||||
of tyInt..tyInt64, tyEnum, tyChar, tyBool, tyUInt8..tyUInt32:
|
of tyInt..tyInt64, tyEnum, tyChar, tyBool, tyUInt8..tyUInt32:
|
||||||
# we don't include uint and uint64 here as these are no ordinal types ;-)
|
# we don't include uint and uint64 here as these are no ordinal types ;-)
|
||||||
if not isOrdinalType(source):
|
if not isOrdinalType(source):
|
||||||
# XXX int64 -> float conversion?
|
# float -> int conversions. ugh.
|
||||||
result = transformSons(c, n)
|
result = transformSons(c, n)
|
||||||
elif firstOrd(dest) <= firstOrd(source) and
|
elif firstOrd(n.typ) <= firstOrd(n.sons[1].typ) and
|
||||||
lastOrd(source) <= lastOrd(dest):
|
lastOrd(n.sons[1].typ) <= lastOrd(n.typ):
|
||||||
# BUGFIX: simply leave n as it is; we need a nkConv node,
|
# BUGFIX: simply leave n as it is; we need a nkConv node,
|
||||||
# but no range check:
|
# but no range check:
|
||||||
result = transformSons(c, n)
|
result = transformSons(c, n)
|
||||||
|
|
@ -334,13 +334,14 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
|
||||||
# generate a range check:
|
# generate a range check:
|
||||||
if dest.kind == tyInt64 or source.kind == tyInt64:
|
if dest.kind == tyInt64 or source.kind == tyInt64:
|
||||||
result = newTransNode(nkChckRange64, n, 3)
|
result = newTransNode(nkChckRange64, n, 3)
|
||||||
else:
|
else:
|
||||||
result = newTransNode(nkChckRange, n, 3)
|
result = newTransNode(nkChckRange, n, 3)
|
||||||
dest = skipTypes(n.typ, abstractVar)
|
dest = skipTypes(n.typ, abstractVar)
|
||||||
result[0] = transform(c, n.sons[1])
|
result[0] = transform(c, n.sons[1])
|
||||||
result[1] = newIntTypeNode(nkIntLit, firstOrd(dest), source).PTransNode
|
result[1] = newIntTypeNode(nkIntLit, firstOrd(dest), source).PTransNode
|
||||||
result[2] = newIntTypeNode(nkIntLit, lastOrd(dest), source).PTransNode
|
result[2] = newIntTypeNode(nkIntLit, lastOrd(dest), source).PTransNode
|
||||||
of tyFloat..tyFloat128:
|
of tyFloat..tyFloat128:
|
||||||
|
# XXX int64 -> float conversion?
|
||||||
if skipTypes(n.typ, abstractVar).kind == tyRange:
|
if skipTypes(n.typ, abstractVar).kind == tyRange:
|
||||||
result = newTransNode(nkChckRangeF, n, 3)
|
result = newTransNode(nkChckRangeF, n, 3)
|
||||||
dest = skipTypes(n.typ, abstractVar)
|
dest = skipTypes(n.typ, abstractVar)
|
||||||
|
|
|
||||||
2
compiler/trees.nim
Executable file → Normal file
2
compiler/trees.nim
Executable file → Normal file
|
|
@ -115,7 +115,7 @@ proc isDeepConstExpr*(n: PNode): bool =
|
||||||
result = true
|
result = true
|
||||||
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
|
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
|
||||||
result = isDeepConstExpr(n.sons[1])
|
result = isDeepConstExpr(n.sons[1])
|
||||||
of nkCurly, nkBracket, nkPar, nkClosure:
|
of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure:
|
||||||
for i in 0 .. <n.len:
|
for i in 0 .. <n.len:
|
||||||
if not isDeepConstExpr(n.sons[i]): return false
|
if not isDeepConstExpr(n.sons[i]): return false
|
||||||
result = true
|
result = true
|
||||||
|
|
|
||||||
0
compiler/treetab.nim
Executable file → Normal file
0
compiler/treetab.nim
Executable file → Normal file
88
compiler/types.nim
Executable file → Normal file
88
compiler/types.nim
Executable file → Normal file
|
|
@ -49,16 +49,18 @@ proc isOrdinalType*(t: PType): bool
|
||||||
proc enumHasHoles*(t: PType): bool
|
proc enumHasHoles*(t: PType): bool
|
||||||
const
|
const
|
||||||
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
|
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
|
||||||
tyConst, tyMutable}
|
tyConst, tyMutable, tyTypeDesc}
|
||||||
abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal,
|
abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal,
|
||||||
tyConst, tyMutable}
|
tyConst, tyMutable, tyTypeDesc}
|
||||||
abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal,
|
abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal,
|
||||||
tyConst, tyMutable}
|
tyConst, tyMutable, tyTypeDesc}
|
||||||
abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
|
abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
|
||||||
tyConst, tyMutable}
|
tyConst, tyMutable, tyTypeDesc}
|
||||||
abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal}
|
abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal,
|
||||||
|
tyTypeDesc}
|
||||||
|
|
||||||
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable}
|
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable,
|
||||||
|
tyTypeDesc}
|
||||||
typedescPtrs* = abstractPtrs + {tyTypeDesc}
|
typedescPtrs* = abstractPtrs + {tyTypeDesc}
|
||||||
typedescInst* = abstractInst + {tyTypeDesc}
|
typedescInst* = abstractInst + {tyTypeDesc}
|
||||||
|
|
||||||
|
|
@ -327,7 +329,7 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
|
||||||
result = false
|
result = false
|
||||||
if typ == nil: return
|
if typ == nil: return
|
||||||
if tfAcyclic in typ.flags: return
|
if tfAcyclic in typ.flags: return
|
||||||
var t = skipTypes(typ, abstractInst)
|
var t = skipTypes(typ, abstractInst-{tyTypeDesc})
|
||||||
if tfAcyclic in t.flags: return
|
if tfAcyclic in t.flags: return
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray,
|
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray,
|
||||||
|
|
@ -344,11 +346,10 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
|
||||||
#if t.kind == tyObject and tfFinal notin t.flags:
|
#if t.kind == tyObject and tfFinal notin t.flags:
|
||||||
# # damn inheritance may introduce cycles:
|
# # damn inheritance may introduce cycles:
|
||||||
# result = true
|
# result = true
|
||||||
|
of tyProc: result = typ.callConv == ccClosure
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc canFormAcycle(typ: PType): bool =
|
proc canFormAcycle(typ: PType): bool =
|
||||||
# XXX as I expect cycles introduced by closures are very rare, we pretend
|
|
||||||
# they can't happen here.
|
|
||||||
var marker = InitIntSet()
|
var marker = InitIntSet()
|
||||||
result = canFormAcycleAux(marker, typ, typ.id)
|
result = canFormAcycleAux(marker, typ, typ.id)
|
||||||
|
|
||||||
|
|
@ -393,26 +394,31 @@ proc rangeToStr(n: PNode): string =
|
||||||
assert(n.kind == nkRange)
|
assert(n.kind == nkRange)
|
||||||
result = ValueToString(n.sons[0]) & ".." & ValueToString(n.sons[1])
|
result = ValueToString(n.sons[0]) & ".." & ValueToString(n.sons[1])
|
||||||
|
|
||||||
|
const
|
||||||
|
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
||||||
|
"Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
|
||||||
|
"GenericInvokation", "GenericBody", "GenericInst", "GenericParam",
|
||||||
|
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
||||||
|
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
||||||
|
"pointer", "OpenArray[$1]", "string", "CString", "Forward",
|
||||||
|
"int", "int8", "int16", "int32", "int64",
|
||||||
|
"float", "float32", "float64", "float128",
|
||||||
|
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||||
|
"bignum", "const ",
|
||||||
|
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass"]
|
||||||
|
|
||||||
|
proc consToStr(t: PType): string =
|
||||||
|
if t.len > 0: result = t.typeToString
|
||||||
|
else: result = typeToStr[t.kind].strip
|
||||||
|
|
||||||
proc constraintsToStr(t: PType): string =
|
proc constraintsToStr(t: PType): string =
|
||||||
let sep = if tfAny in t.flags: " or " else: " and "
|
let sep = if tfAny in t.flags: " or " else: " and "
|
||||||
result = ""
|
result = ""
|
||||||
for i in countup(0, t.sons.len - 1):
|
for i in countup(0, t.len - 1):
|
||||||
if i > 0: result.add(sep)
|
if i > 0: result.add(sep)
|
||||||
result.add(t.sons[i].typeToString)
|
result.add(t.sons[i].consToStr)
|
||||||
|
|
||||||
proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
const
|
|
||||||
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
|
||||||
"Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
|
|
||||||
"GenericInvokation", "GenericBody", "GenericInst", "GenericParam",
|
|
||||||
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
|
||||||
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
|
||||||
"pointer", "OpenArray[$1]", "string", "CString", "Forward",
|
|
||||||
"int", "int8", "int16", "int32", "int64",
|
|
||||||
"float", "float32", "float64", "float128",
|
|
||||||
"uint", "uint8", "uint16", "uint32", "uint64",
|
|
||||||
"bignum", "const ",
|
|
||||||
"!", "varargs[$1]", "iter[$1]", "Error Type", "TypeClass"]
|
|
||||||
var t = typ
|
var t = typ
|
||||||
result = ""
|
result = ""
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
|
|
@ -433,12 +439,15 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
add(result, typeToString(t.sons[i]))
|
add(result, typeToString(t.sons[i]))
|
||||||
add(result, ']')
|
add(result, ']')
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
if t.sons == nil or t.sons.len == 0: result = "typedesc"
|
if t.len == 0: result = "typedesc"
|
||||||
else: result = "typedesc[" & constraintsToStr(t) & "]"
|
else: result = "typedesc[" & constraintsToStr(t) & "]"
|
||||||
of tyTypeClass:
|
of tyTypeClass:
|
||||||
result = constraintsToStr(t)
|
case t.len
|
||||||
|
of 0: result = "typeclass[]"
|
||||||
|
of 1: result = "typeclass[" & consToStr(t.sons[0]) & "]"
|
||||||
|
else: result = constraintsToStr(t)
|
||||||
of tyExpr:
|
of tyExpr:
|
||||||
if t.sons.len == 0: result = "expr"
|
if t.len == 0: result = "expr"
|
||||||
else: result = "expr[" & constraintsToStr(t) & "]"
|
else: result = "expr[" & constraintsToStr(t) & "]"
|
||||||
of tyArray:
|
of tyArray:
|
||||||
if t.sons[0].kind == tyRange:
|
if t.sons[0].kind == tyRange:
|
||||||
|
|
@ -476,8 +485,8 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
add(result, ']')
|
add(result, ']')
|
||||||
of tyPtr, tyRef, tyVar, tyMutable, tyConst:
|
of tyPtr, tyRef, tyVar, tyMutable, tyConst:
|
||||||
result = typeToStr[t.kind] & typeToString(t.sons[0])
|
result = typeToStr[t.kind] & typeToString(t.sons[0])
|
||||||
of tyRange:
|
of tyRange:
|
||||||
result = "range " & rangeToStr(t.n)
|
result = "range " & rangeToStr(t.n) & "(" & typeToString(t.sons[0]) & ")"
|
||||||
of tyProc:
|
of tyProc:
|
||||||
result = if tfIterator in t.flags: "iterator (" else: "proc ("
|
result = if tfIterator in t.flags: "iterator (" else: "proc ("
|
||||||
for i in countup(1, sonsLen(t) - 1):
|
for i in countup(1, sonsLen(t) - 1):
|
||||||
|
|
@ -534,7 +543,7 @@ proc firstOrd(t: PType): biggestInt =
|
||||||
else:
|
else:
|
||||||
assert(t.n.sons[0].kind == nkSym)
|
assert(t.n.sons[0].kind == nkSym)
|
||||||
result = t.n.sons[0].sym.position
|
result = t.n.sons[0].sym.position
|
||||||
of tyGenericInst, tyDistinct, tyConst, tyMutable:
|
of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc:
|
||||||
result = firstOrd(lastSon(t))
|
result = firstOrd(lastSon(t))
|
||||||
else:
|
else:
|
||||||
InternalError("invalid kind for first(" & $t.kind & ')')
|
InternalError("invalid kind for first(" & $t.kind & ')')
|
||||||
|
|
@ -567,7 +576,7 @@ proc lastOrd(t: PType): biggestInt =
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
|
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
|
||||||
result = t.n.sons[sonsLen(t.n) - 1].sym.position
|
result = t.n.sons[sonsLen(t.n) - 1].sym.position
|
||||||
of tyGenericInst, tyDistinct, tyConst, tyMutable:
|
of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc:
|
||||||
result = lastOrd(lastSon(t))
|
result = lastOrd(lastSon(t))
|
||||||
of tyProxy: result = 0
|
of tyProxy: result = 0
|
||||||
else:
|
else:
|
||||||
|
|
@ -833,7 +842,8 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
||||||
of tyGenericInst:
|
of tyGenericInst:
|
||||||
result = sameTypeAux(lastSon(a), lastSon(b), c)
|
result = sameTypeAux(lastSon(a), lastSon(b), c)
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
if TypeDescExactMatch in c.flags:
|
if c.cmp == dcEqIgnoreDistinct: result = false
|
||||||
|
elif TypeDescExactMatch in c.flags:
|
||||||
CycleCheck()
|
CycleCheck()
|
||||||
result = sameChildrenAux(x, y, c) and sameFlags(a, b)
|
result = sameChildrenAux(x, y, c) and sameFlags(a, b)
|
||||||
else:
|
else:
|
||||||
|
|
@ -938,7 +948,8 @@ proc matchTypeClass*(bindings: var TIdTable, typeClass, t: PType): bool =
|
||||||
of tyTypeClass:
|
of tyTypeClass:
|
||||||
match = matchTypeClass(bindings, req, t)
|
match = matchTypeClass(bindings, req, t)
|
||||||
else: nil
|
else: nil
|
||||||
elif t.kind in {tyObject}:
|
elif t.kind in {tyObject} and req.len != 0:
|
||||||
|
# empty 'object' is fine as constraint in a type class
|
||||||
match = sameType(t, req)
|
match = sameType(t, req)
|
||||||
|
|
||||||
if tfAny in typeClass.flags:
|
if tfAny in typeClass.flags:
|
||||||
|
|
@ -962,11 +973,11 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
||||||
result = true
|
result = true
|
||||||
if typ == nil: return
|
if typ == nil: return
|
||||||
if ContainsOrIncl(marker, typ.id): return
|
if ContainsOrIncl(marker, typ.id): return
|
||||||
var t = skipTypes(typ, abstractInst)
|
var t = skipTypes(typ, abstractInst-{tyTypeDesc})
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyVar:
|
of tyVar:
|
||||||
if kind == skConst: return false
|
if kind == skConst: return false
|
||||||
var t2 = skipTypes(t.sons[0], abstractInst)
|
var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc})
|
||||||
case t2.kind
|
case t2.kind
|
||||||
of tyVar:
|
of tyVar:
|
||||||
result = false # ``var var`` is always an invalid type:
|
result = false # ``var var`` is always an invalid type:
|
||||||
|
|
@ -980,8 +991,9 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
||||||
if not result: break
|
if not result: break
|
||||||
if result and t.sons[0] != nil:
|
if result and t.sons[0] != nil:
|
||||||
result = typeAllowedAux(marker, t.sons[0], skResult)
|
result = typeAllowedAux(marker, t.sons[0], skResult)
|
||||||
of tyExpr, tyStmt, tyTypeDesc:
|
of tyExpr, tyStmt, tyTypeDesc:
|
||||||
result = true
|
result = true
|
||||||
|
# XXX er ... no? these should not be allowed!
|
||||||
of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation,
|
of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation,
|
||||||
tyTypeClass:
|
tyTypeClass:
|
||||||
result = false
|
result = false
|
||||||
|
|
@ -994,7 +1006,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
||||||
of tyGenericInst, tyDistinct:
|
of tyGenericInst, tyDistinct:
|
||||||
result = typeAllowedAux(marker, lastSon(t), kind)
|
result = typeAllowedAux(marker, lastSon(t), kind)
|
||||||
of tyRange:
|
of tyRange:
|
||||||
result = skipTypes(t.sons[0], abstractInst).kind in
|
result = skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind in
|
||||||
{tyChar, tyEnum, tyInt..tyFloat128}
|
{tyChar, tyEnum, tyInt..tyFloat128}
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
result = (kind == skParam) and typeAllowedAux(marker, t.sons[0], skVar)
|
result = (kind == skParam) and typeAllowedAux(marker, t.sons[0], skVar)
|
||||||
|
|
@ -1162,6 +1174,8 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
|
||||||
result = align(result, a)
|
result = align(result, a)
|
||||||
of tyGenericInst, tyDistinct, tyGenericBody, tyMutable, tyConst, tyIter:
|
of tyGenericInst, tyDistinct, tyGenericBody, tyMutable, tyConst, tyIter:
|
||||||
result = computeSizeAux(lastSon(typ), a)
|
result = computeSizeAux(lastSon(typ), a)
|
||||||
|
of tyTypeDesc:
|
||||||
|
result = (if typ.len == 1: computeSizeAux(typ.sons[0], a) else: -1)
|
||||||
of tyProxy: result = 1
|
of tyProxy: result = 1
|
||||||
else:
|
else:
|
||||||
#internalError("computeSizeAux()")
|
#internalError("computeSizeAux()")
|
||||||
|
|
|
||||||
0
compiler/wordrecg.nim
Executable file → Normal file
0
compiler/wordrecg.nim
Executable file → Normal file
0
config/nimdoc.cfg
Executable file → Normal file
0
config/nimdoc.cfg
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue