Merge branch 'master' of github.com:Araq/Nimrod

This commit is contained in:
Araq 2012-06-19 22:38:48 +02:00
commit e0092cfae6
54 changed files with 1980 additions and 1251 deletions

View file

@ -52,9 +52,15 @@ type
nkInt16Lit,
nkInt32Lit,
nkInt64Lit,
nkUIntLit, # an unsigned integer literal
nkUInt8Lit,
nkUInt16Lit,
nkUInt32Lit,
nkUInt64Lit,
nkFloatLit, # a floating point literal
nkFloat32Lit,
nkFloat64Lit,
nkFloat128Lit,
nkStrLit, # a string literal ""
nkRStrLit, # a raw string literal r""
nkTripleStrLit, # a triple string literal """
@ -237,6 +243,7 @@ type
sfNamedParamCall, # symbol needs named parameter call syntax in target
# language; for interfacing with Objective C
sfDiscardable # returned value may be discarded implicitely
sfDestructor # proc is destructor
TSymFlags* = set[TSymFlag]
@ -325,6 +332,8 @@ type
tfEnumHasHoles, # enum cannot be mapped into a range
tfShallow, # type can be shallow copied on assignment
tfThread, # proc type is marked as ``thread``
tfUniIntLit # type represents literal value that could be either
# singed or unsigned integer (e.g. 100)
tfFromGeneric # type is an instantiation of a generic; this is needed
# because for instantiations of objects, structural
# type equality has to be used
@ -408,8 +417,11 @@ type
mNewString, mNewStringOfCap,
mReset,
mArray, mOpenArray, mRange, mSet, mSeq,
mOrdinal, mInt, mInt8, mInt16, mInt32,
mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring,
mOrdinal,
mInt, mInt8, mInt16, mInt32, mInt64,
mUInt, mUInt8, mUInt16, mUInt32, mUInt64,
mFloat, mFloat32, mFloat64, mFloat128,
mBool, mChar, mString, mCstring,
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
mVoidType, mPNimrodNode,
mIsMainModule, mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor,
@ -464,11 +476,11 @@ type
info*: TLineInfo
flags*: TNodeFlags
case Kind*: TNodeKind
of nkCharLit..nkInt64Lit:
of nkCharLit..nkUInt64Lit:
intVal*: biggestInt
of nkFloatLit..nkFloat64Lit:
of nkFloatLit..nkFloat128Lit:
floatVal*: biggestFloat
of nkStrLit..nkTripleStrLit:
of nkStrLit..nkTripleStrLit:
strVal*: string
of nkSym:
sym*: PSym
@ -765,8 +777,8 @@ const # for all kind of hash tables:
proc ValueToString*(a: PNode): string =
case a.kind
of nkCharLit..nkInt64Lit: result = $(a.intVal)
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result = $(a.floatVal)
of nkCharLit..nkUInt64Lit: result = $(a.intVal)
of nkFloatLit..nkFloat128Lit: result = $(a.floatVal)
of nkStrLit..nkTripleStrLit: result = a.strVal
else:
InternalError(a.info, "valueToString")
@ -888,6 +900,7 @@ proc assignType(dest, src: PType) =
dest.size = src.size
dest.align = src.align
dest.containerID = src.containerID
dest.destructor = src.destructor
# this fixes 'type TLock = TSysLock':
if src.sym != nil:
if dest.sym != nil:
@ -1020,8 +1033,8 @@ proc copyNode(src: PNode): PNode =
result.typ = src.typ
result.flags = src.flags * PersistentNodeFlags
case src.Kind
of nkCharLit..nkInt64Lit: result.intVal = src.intVal
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal
of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
of nkSym: result.sym = src.sym
of nkIdent: result.ident = src.ident
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
@ -1035,8 +1048,8 @@ proc shallowCopy*(src: PNode): PNode =
result.typ = src.typ
result.flags = src.flags * PersistentNodeFlags
case src.Kind
of nkCharLit..nkInt64Lit: result.intVal = src.intVal
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal
of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
of nkSym: result.sym = src.sym
of nkIdent: result.ident = src.ident
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
@ -1051,8 +1064,8 @@ proc copyTree(src: PNode): PNode =
result.typ = src.typ
result.flags = src.flags * PersistentNodeFlags
case src.Kind
of nkCharLit..nkInt64Lit: result.intVal = src.intVal
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: result.floatVal = src.floatVal
of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
of nkSym: result.sym = src.sym
of nkIdent: result.ident = src.ident
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
@ -1102,14 +1115,14 @@ proc sonsNotNil(n: PNode): bool =
proc getInt*(a: PNode): biggestInt =
case a.kind
of nkIntLit..nkInt64Lit: result = a.intVal
of nkIntLit..nkUInt64Lit: result = a.intVal
else:
internalError(a.info, "getInt")
result = 0
proc getFloat*(a: PNode): biggestFloat =
case a.kind
of nkFloatLit..nkFloat64Lit: result = a.floatVal
of nkFloatLit..nkFloat128Lit: result = a.floatVal
else:
internalError(a.info, "getFloat")
result = 0.0

View file

@ -274,10 +274,10 @@ proc strTableToYaml(n: TStrTable, marker: var TIntSet, indent: int,
for i in countup(0, high(n.data)):
if n.data[i] != nil:
if mycount > 0: app(result, ",")
appf(result, "$n$1$2",
appf(result, "$N$1$2",
[istr, symToYamlAux(n.data[i], marker, indent + 2, maxRecDepth - 1)])
inc(mycount)
if mycount > 0: appf(result, "$n$1", [spaces(indent)])
if mycount > 0: appf(result, "$N$1", [spaces(indent)])
app(result, "]")
assert(mycount == n.counter)
@ -288,9 +288,9 @@ proc ropeConstr(indent: int, c: openarray[PRope]): PRope =
var i = 0
while i <= high(c):
if i > 0: app(result, ",")
appf(result, "$n$1\"$2\": $3", [istr, c[i], c[i + 1]])
appf(result, "$N$1\"$2\": $3", [istr, c[i], c[i + 1]])
inc(i, 2)
appf(result, "$n$1}", [spaces(indent)])
appf(result, "$N$1}", [spaces(indent)])
proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int,
maxRecDepth: int): PRope =
@ -325,9 +325,9 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int,
result = toRope("[")
for i in countup(0, sonsLen(n) - 1):
if i > 0: app(result, ",")
appf(result, "$n$1$2", [spaces(indent + 4), typeToYamlAux(n.sons[i],
appf(result, "$N$1$2", [spaces(indent + 4), typeToYamlAux(n.sons[i],
marker, indent + 4, maxRecDepth - 1)])
appf(result, "$n$1]", [spaces(indent + 2)])
appf(result, "$N$1]", [spaces(indent + 2)])
else:
result = toRope("null")
result = ropeConstr(indent, [toRope("kind"),
@ -347,36 +347,36 @@ proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int,
result = toRope("null")
else:
var istr = spaces(indent + 2)
result = ropef("{$n$1\"kind\": $2", [istr, makeYamlString($n.kind)])
result = ropef("{$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
if maxRecDepth != 0:
appf(result, ",$n$1\"info\": $2", [istr, lineInfoToStr(n.info)])
appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
case n.kind
of nkCharLit..nkInt64Lit:
appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)])
appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)])
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
appf(result, ",$n$1\"floatVal\": $2",
appf(result, ",$N$1\"floatVal\": $2",
[istr, toRope(n.floatVal.ToStrMaxPrecision)])
of nkStrLit..nkTripleStrLit:
appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym:
appf(result, ",$n$1\"sym\": $2",
appf(result, ",$N$1\"sym\": $2",
[istr, symToYamlAux(n.sym, marker, indent + 2, maxRecDepth)])
of nkIdent:
if n.ident != nil:
appf(result, ",$n$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
else:
appf(result, ",$n$1\"ident\": null", [istr])
appf(result, ",$N$1\"ident\": null", [istr])
else:
if sonsLen(n) > 0:
appf(result, ",$n$1\"sons\": [", [istr])
appf(result, ",$N$1\"sons\": [", [istr])
for i in countup(0, sonsLen(n) - 1):
if i > 0: app(result, ",")
appf(result, "$n$1$2", [spaces(indent + 4), treeToYamlAux(n.sons[i],
appf(result, "$N$1$2", [spaces(indent + 4), treeToYamlAux(n.sons[i],
marker, indent + 4, maxRecDepth - 1)])
appf(result, "$n$1]", [istr])
appf(result, ",$n$1\"typ\": $2",
appf(result, "$N$1]", [istr])
appf(result, ",$N$1\"typ\": $2",
[istr, typeToYamlAux(n.typ, marker, indent + 2, maxRecDepth)])
appf(result, "$n$1}", [spaces(indent)])
appf(result, "$N$1}", [spaces(indent)])
proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope =
var marker = InitIntSet()
@ -413,34 +413,34 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
result = toRope("null")
else:
var istr = spaces(indent + 2)
result = ropef("{$n$1\"kind\": $2",
result = ropef("{$N$1\"kind\": $2",
[istr, makeYamlString($n.kind)])
if maxRecDepth != 0:
case n.kind
of nkCharLit..nkInt64Lit:
appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)])
appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)])
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
appf(result, ",$n$1\"floatVal\": $2",
appf(result, ",$N$1\"floatVal\": $2",
[istr, toRope(n.floatVal.ToStrMaxPrecision)])
of nkStrLit..nkTripleStrLit:
appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym:
appf(result, ",$n$1\"sym\": $2_$3",
appf(result, ",$N$1\"sym\": $2_$3",
[istr, toRope(n.sym.name.s), toRope(n.sym.id)])
of nkIdent:
if n.ident != nil:
appf(result, ",$n$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
else:
appf(result, ",$n$1\"ident\": null", [istr])
appf(result, ",$N$1\"ident\": null", [istr])
else:
if sonsLen(n) > 0:
appf(result, ",$n$1\"sons\": [", [istr])
appf(result, ",$N$1\"sons\": [", [istr])
for i in countup(0, sonsLen(n) - 1):
if i > 0: app(result, ",")
appf(result, "$n$1$2", [spaces(indent + 4), debugTree(n.sons[i],
appf(result, "$N$1$2", [spaces(indent + 4), debugTree(n.sons[i],
indent + 4, maxRecDepth - 1)])
appf(result, "$n$1]", [istr])
appf(result, "$n$1}", [spaces(indent)])
appf(result, "$N$1]", [istr])
appf(result, "$N$1}", [spaces(indent)])
proc debug(n: PSym) =
#writeln(stdout, ropeToStr(symToYaml(n, 0, 1)))

View file

@ -33,16 +33,14 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
# reset before pass as 'result' var:
resetLoc(p, d)
app(pl, addrLoc(d))
app(pl, ")")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
appf(pl, ");$n")
line(p, cpsStmts, pl)
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp)
app(pl, addrLoc(tmp))
app(pl, ")")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
appf(pl, ");$n")
line(p, cpsStmts, pl)
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
app(pl, ")")
@ -53,9 +51,8 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
else:
app(pl, ")")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
appf(pl, ");$n")
line(p, cpsStmts, pl)
proc isInCurrentFrame(p: BProc, n: PNode): bool =
# checks if `n` is an expression that refers to the current frame;
@ -148,7 +145,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
proc addComma(r: PRope): PRope =
result = if r == nil: r else: con(r, ", ")
const CallPattern = "$1.ClEnv? $1.ClPrc($3$1.ClEnv) : (($4)($1.ClPrc))($2)"
const CallPattern = "$1.ClEnv? $1.ClPrc($3$1.ClEnv) : (($4)($1.ClPrc))($2);$n"
var op: TLoc
initLocExpr(p, ri.sons[0], op)
var pl: PRope
@ -166,7 +163,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
if i < length - 1: app(pl, ", ")
template genCallPattern =
appf(p.s(cpsStmts), CallPattern, op.r, pl, pl.addComma, rawProc)
lineF(p, cpsStmts, CallPattern, op.r, pl, pl.addComma, rawProc)
let rawProc = getRawProcType(p, typ)
if typ.sons[0] != nil:
@ -181,13 +178,11 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
resetLoc(p, d)
app(pl, addrLoc(d))
genCallPattern()
appf(p.s(cpsStmts), ";$n")
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp)
app(pl, addrLoc(tmp))
app(pl, addrLoc(tmp))
genCallPattern()
appf(p.s(cpsStmts), ";$n")
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
@ -198,7 +193,6 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
genAssignment(p, d, list, {}) # no need for deep copying
else:
genCallPattern()
appf(p.s(cpsStmts), ";$n")
proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op, a: TLoc
@ -264,16 +258,14 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
if d.k == locNone: getTemp(p, typ.sons[0], d)
app(pl, "Result: ")
app(pl, addrLoc(d))
app(pl, "]")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
appf(pl, "];$n")
line(p, cpsStmts, pl)
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp)
app(pl, addrLoc(tmp))
app(pl, "]")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
appf(pl, "];$n")
line(p, cpsStmts, pl)
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
app(pl, "]")
@ -284,9 +276,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
else:
app(pl, "]")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
appf(pl, "];$n")
line(p, cpsStmts, pl)
proc genCall(p: BProc, e: PNode, d: var TLoc) =
if e.sons[0].typ.callConv == ccClosure:

View file

@ -34,7 +34,7 @@ proc int32Literal(i: Int): PRope =
proc genHexLiteral(v: PNode): PRope =
# hex literals are unsigned in C
# so we don't generate hex literals any longer.
if not (v.kind in {nkIntLit..nkInt64Lit}):
if not (v.kind in {nkIntLit..nkUInt64Lit}):
internalError(v.info, "genHexLiteral")
result = intLiteral(v.intVal)
@ -47,7 +47,7 @@ proc getStrLit(m: BModule, s: string): PRope =
proc genLiteral(p: BProc, v: PNode, ty: PType): PRope =
if ty == nil: internalError(v.info, "genLiteral: ty is nil")
case v.kind
of nkCharLit..nkInt64Lit:
of nkCharLit..nkUInt64Lit:
case skipTypes(ty, abstractVarRange).kind
of tyChar, tyInt64, tyNil:
result = intLiteral(v.intVal)
@ -160,7 +160,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
appf(p.s(cpsStmts), "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
lineF(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
if needToKeepAlive in flags: keepAlive(p, dest)
elif dest.s == OnHeap:
# location is on heap
@ -168,25 +168,25 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
#
# if afSrcIsNotNil in flags:
# UseMagic(p.module, 'nimGCref')
# appf(p.s[cpsStmts], 'nimGCref($1);$n', [rdLoc(src)])
# lineF(p, cpsStmts, 'nimGCref($1);$n', [rdLoc(src)])
# elif afSrcIsNil notin flags:
# UseMagic(p.module, 'nimGCref')
# appf(p.s[cpsStmts], 'if ($1) nimGCref($1);$n', [rdLoc(src)])
# lineF(p, cpsStmts, 'if ($1) nimGCref($1);$n', [rdLoc(src)])
# if afDestIsNotNil in flags:
# UseMagic(p.module, 'nimGCunref')
# appf(p.s[cpsStmts], 'nimGCunref($1);$n', [rdLoc(dest)])
# lineF(p, cpsStmts, 'nimGCunref($1);$n', [rdLoc(dest)])
# elif afDestIsNil notin flags:
# UseMagic(p.module, 'nimGCunref')
# appf(p.s[cpsStmts], 'if ($1) nimGCunref($1);$n', [rdLoc(dest)])
# appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)])
# lineF(p, cpsStmts, 'if ($1) nimGCunref($1);$n', [rdLoc(dest)])
# lineF(p, cpsStmts, '$1 = $2;$n', [rdLoc(dest), rdLoc(src)])
if canFormAcycle(dest.t):
appcg(p.module, p.s(cpsStmts), "#asgnRef((void**) $1, $2);$n",
lineCg(p, cpsStmts, "#asgnRef((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)])
else:
appcg(p.module, p.s(cpsStmts), "#asgnRefNoCycle((void**) $1, $2);$n",
lineCg(p, cpsStmts, "#asgnRefNoCycle((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)])
else:
appcg(p.module, p.s(cpsStmts), "#unsureAsgnRef((void**) $1, $2);$n",
lineCg(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)])
if needToKeepAlive in flags: keepAlive(p, dest)
@ -200,15 +200,15 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if needToCopy notin flags or
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
appcg(p, cpsStmts,
lineCg(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
[addrLoc(dest), addrLoc(src), rdLoc(dest)])
if needToKeepAlive in flags: keepAlive(p, dest)
else:
appcg(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
lineCg(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else:
appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
lineCg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
@ -216,7 +216,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# the assignment operation in C.
if src.t != nil and src.t.kind == tyPtr:
# little HACK to support the new 'var T' as return type:
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
return
var ty = skipTypes(dest.t, abstractVarRange)
case ty.kind
@ -226,24 +226,24 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if needToCopy notin flags:
genRefAssign(p, dest, src, flags)
else:
appcg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
lineCg(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
[addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t)])
of tyString:
if needToCopy notin flags:
genRefAssign(p, dest, src, flags)
else:
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
appcg(p, cpsStmts, "$1 = #copyString($2);$n", [dest.rdLoc, src.rdLoc])
lineCg(p, cpsStmts, "$1 = #copyString($2);$n", [dest.rdLoc, src.rdLoc])
if needToKeepAlive in flags: keepAlive(p, dest)
elif dest.s == OnHeap:
# we use a temporary to care for the dreaded self assignment:
var tmp: TLoc
getTemp(p, ty, tmp)
appcg(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n",
lineCg(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n",
[dest.rdLoc, src.rdLoc, tmp.rdLoc])
appcg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", tmp.rdLoc)
lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", tmp.rdLoc)
else:
appcg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
lineCg(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
[addrLoc(dest), rdLoc(src)])
if needToKeepAlive in flags: keepAlive(p, dest)
of tyTuple, tyObject, tyProc:
@ -251,34 +251,34 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if needsComplexAssignment(dest.t):
genGenericAsgn(p, dest, src, flags)
else:
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
of tyArray, tyArrayConstr:
if needsComplexAssignment(dest.t):
genGenericAsgn(p, dest, src, flags)
else:
appcg(p, cpsStmts,
lineCg(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
[rdLoc(dest), rdLoc(src)])
of tyOpenArray:
# open arrays are always on the stack - really? What if a sequence is
# passed to an open array?
if needsComplexAssignment(dest.t):
appcg(p, cpsStmts, # XXX: is this correct for arrays?
lineCg(p, cpsStmts, # XXX: is this correct for arrays?
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
[addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)])
else:
appcg(p, cpsStmts,
lineCg(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n",
[rdLoc(dest), rdLoc(src)])
of tySet:
if mapType(ty) == ctArray:
appcg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
lineCg(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
[rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))])
else:
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString,
tyInt..tyFloat128, tyRange:
appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
tyInt..tyUInt64, tyRange:
lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
else: InternalError("genAssignment(" & $ty.kind & ')')
proc expr(p: BProc, e: PNode, d: var TLoc)
@ -317,20 +317,20 @@ proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
if d.k != locNone: InternalError(e.info, "binaryStmt")
InitLocExpr(p, e.sons[1], d)
InitLocExpr(p, e.sons[2], b)
appcg(p, cpsStmts, frmt, [rdLoc(d), rdLoc(b)])
lineCg(p, cpsStmts, frmt, [rdLoc(d), rdLoc(b)])
proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a: TLoc
if (d.k != locNone): InternalError(e.info, "unaryStmt")
InitLocExpr(p, e.sons[1], a)
appcg(p, cpsStmts, frmt, [rdLoc(a)])
lineCg(p, cpsStmts, frmt, [rdLoc(a)])
proc binaryStmtChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a, b: TLoc
if (d.k != locNone): InternalError(e.info, "binaryStmtChar")
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
appcg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)])
lineCg(p, cpsStmts, frmt, [rdCharLoc(a), rdCharLoc(b)])
proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) =
var a, b: TLoc
@ -382,11 +382,11 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
else:
storage = getTypeDesc(p.module, t)
var tmp = getTempName()
appcg(p, cpsLocals, "$1 $2;$n", [storage, tmp])
appcg(p, cpsStmts, "$1 = #$2($3, $4);$n", [tmp, toRope(prc[m]),
lineCg(p, cpsLocals, "$1 $2;$n", [storage, tmp])
lineCg(p, cpsStmts, "$1 = #$2($3, $4);$n", [tmp, toRope(prc[m]),
rdLoc(a), rdLoc(b)])
if size < platform.IntSize or t.kind in {tyRange, tyEnum, tySet}:
appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
lineCg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n",
[tmp, intLiteral(firstOrd(t)), intLiteral(lastOrd(t))])
putIntoDest(p, d, e.typ, ropef("(NI$1)($2)", [toRope(getSize(t)*8), tmp]))
@ -404,7 +404,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
InitLocExpr(p, e.sons[1], a)
t = skipTypes(e.typ, abstractRange)
if optOverflowCheck in p.options:
appcg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
lineCg(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
[rdLoc(a), intLiteral(firstOrd(t))])
putIntoDest(p, d, e.typ, ropef(opr[m], [rdLoc(a), toRope(getSize(t) * 8)]))
@ -582,7 +582,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
var ty = a.t
var r = rdLoc(a)
case e.sons[1].kind
of nkIntLit..nkInt64Lit: i = int(e.sons[1].intVal)
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
else: internalError(e.info, "genTupleElem")
when false:
if ty.n != nil:
@ -634,11 +634,11 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
if id == gBackendId: strLit = getStrLit(p.module, field.name.s)
else: strLit = con("TMP", toRope(id))
if op.magic == mNot:
appcg(p, cpsStmts,
lineCg(p, cpsStmts,
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
[rdLoc(test), strLit])
else:
appcg(p, cpsStmts,
lineCg(p, cpsStmts,
"if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n",
[rdLoc(test), strLit])
appf(r, ".$1", [field.loc.r])
@ -658,10 +658,10 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
# semantic pass has already checked for const index expressions
if firstOrd(ty) == 0:
if (firstOrd(b.t) < firstOrd(ty)) or (lastOrd(b.t) > lastOrd(ty)):
appcg(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n",
lineCg(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n",
[rdCharLoc(b), intLiteral(lastOrd(ty))])
else:
appcg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
lineCg(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
[rdCharLoc(b), first, intLiteral(lastOrd(ty))])
if d.k == locNone: d.s = a.s
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
@ -681,7 +681,7 @@ proc genOpenArrayElem(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[0], a)
initLocExpr(p, e.sons[1], b) # emit range check:
if optBoundsCheck in p.options:
appcg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n",
lineCg(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len0)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``!
if d.k == locNone: d.s = a.s
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
@ -696,11 +696,11 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
ty = skipTypes(ty.sons[0], abstractVarRange) # emit range check:
if optBoundsCheck in p.options:
if ty.kind == tyString:
appcg(p, cpsStmts,
lineCg(p, cpsStmts,
"if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a), lenField()])
else:
appcg(p, cpsStmts,
lineCg(p, cpsStmts,
"if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a), lenField()])
if d.k == locNone: d.s = OnHeap
@ -737,9 +737,9 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
expr(p, e.sons[1], tmp)
L = getLabel(p)
if m == mOr:
appf(p.s(cpsStmts), "if ($1) goto $2;$n", [rdLoc(tmp), L])
lineF(p, cpsStmts, "if ($1) goto $2;$n", [rdLoc(tmp), L])
else:
appf(p.s(cpsStmts), "if (!($1)) goto $2;$n", [rdLoc(tmp), L])
lineF(p, cpsStmts, "if (!($1)) goto $2;$n", [rdLoc(tmp), L])
expr(p, e.sons[2], tmp)
fixLabel(p, L)
if d.k == locNone:
@ -772,9 +772,9 @@ proc genIfExpr(p: BProc, n: PNode, d: var TLoc) =
of nkElifExpr:
initLocExpr(p, it.sons[0], a)
Lelse = getLabel(p)
appf(p.s(cpsStmts), "if (!$1) goto $2;$n", [rdLoc(a), Lelse])
lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), Lelse])
expr(p, it.sons[1], tmp)
appf(p.s(cpsStmts), "goto $1;$n", [Lend])
lineF(p, cpsStmts, "goto $1;$n", [Lend])
fixLabel(p, Lelse)
of nkElseExpr:
expr(p, it.sons[0], tmp)
@ -793,7 +793,7 @@ proc genEcho(p: BProc, n: PNode) =
for i in countup(1, n.len-1):
initLocExpr(p, n.sons[i], a)
appf(args, ", ($1)->data", [rdLoc(a)])
appcg(p, cpsStmts, "printf($1$2);$n", [
lineCg(p, cpsStmts, "printf($1$2);$n", [
makeCString(repeatStr(n.len-1, "%s") & tnl), args])
include ccgcalls
@ -825,14 +825,14 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[i + 1], a)
if skipTypes(e.sons[i + 1].Typ, abstractVarRange).kind == tyChar:
Inc(L)
appcg(p.module, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
appLineCg(p, appends, "#appendChar($1, $2);$n", [tmp.r, rdLoc(a)])
else:
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
Inc(L, len(e.sons[i + 1].strVal))
else:
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
appLineCg(p, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
lineCg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
app(p.s(cpsStmts), appends)
if d.k == locNone:
d = tmp
@ -863,16 +863,16 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[i + 2], a)
if skipTypes(e.sons[i + 2].Typ, abstractVarRange).kind == tyChar:
Inc(L)
appcg(p.module, appends, "#appendChar($1, $2);$n",
appLineCg(p, appends, "#appendChar($1, $2);$n",
[rdLoc(dest), rdLoc(a)])
else:
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
Inc(L, len(e.sons[i + 2].strVal))
else:
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
appcg(p.module, appends, "#appendString($1, $2);$n",
appLineCg(p, appends, "#appendString($1, $2);$n",
[rdLoc(dest), rdLoc(a)])
appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
lineCg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
[rdLoc(dest), lens, toRope(L)])
keepAlive(p, dest)
app(p.s(cpsStmts), appends)
@ -881,10 +881,15 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
# seq &= x -->
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
# seq->data[seq->len-1] = x;
let seqAppendPattern = if gCmd != cmdCompileToCpp:
"$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n"
else:
"$1 = ($2) #incrSeq($1, sizeof($3));$n"
var a, b, dest: TLoc
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
appcg(p, cpsStmts, "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n", [
lineCg(p, cpsStmts, seqAppendPattern, [
rdLoc(a),
getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))])
@ -896,7 +901,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
proc genReset(p: BProc, n: PNode) =
var a: TLoc
InitLocExpr(p, n.sons[1], a)
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
lineCg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
[addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange))])
proc genNew(p: BProc, e: PNode) =
@ -912,11 +917,11 @@ proc genNew(p: BProc, e: PNode) =
if a.s == OnHeap and optRefcGc in gGlobalOptions:
# use newObjRC1 as an optimization; and we don't need 'keepAlive' either
if canFormAcycle(a.t):
appcg(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc)
lineCg(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc)
else:
appcg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc)
lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc)
b.r = ropecg(p.module, "($1) #newObjRC1($2, sizeof($3))", args)
appcg(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc)
lineCg(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc)
else:
b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", args)
genAssignment(p, a, b, {needToKeepAlive}) # set the object type:
@ -930,9 +935,9 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
var call: TLoc
initLoc(call, locExpr, dest.t, OnHeap)
if dest.s == OnHeap and optRefcGc in gGlobalOptions:
appcg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
lineCg(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
appcg(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
lineCg(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
else:
call.r = ropecg(p.module, "($1) #newSeq($2, $3)", args)
genAssignment(p, dest, call, {needToKeepAlive})
@ -1114,8 +1119,12 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
var t = skipTypes(e.sons[1].typ, abstractVar)
appcg(p, cpsStmts,
"$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n", [
let setLenPattern = if gCmd != cmdCompileToCpp:
"$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n"
else:
"$1 = ($3) #setLengthSeq($1, sizeof($4), $2);$n"
lineCg(p, cpsStmts, setLenPattern, [
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
getTypeDesc(p.module, t.sons[0])])
keepAlive(p, a)
@ -1172,7 +1181,7 @@ proc binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) =
assert(d.k == locNone)
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
appf(p.s(cpsStmts), frmt, [rdLoc(a), rdSetElemLoc(b, a.t)])
lineF(p, cpsStmts, frmt, [rdLoc(a), rdSetElemLoc(b, a.t)])
proc genInOp(p: BProc, e: PNode, d: var TLoc) =
var a, b, x, y: TLoc
@ -1248,7 +1257,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b)
if d.k == locNone: getTemp(p, a.t, d)
appf(p.s(cpsStmts), lookupOpr[op],
lineF(p, cpsStmts, lookupOpr[op],
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
of mEqSet:
binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
@ -1258,7 +1267,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b)
if d.k == locNone: getTemp(p, a.t, d)
appf(p.s(cpsStmts),
lineF(p, cpsStmts,
"for ($1 = 0; $1 < $2; $1++) $n" &
" $3[$1] = $4[$1] $6 $5[$1];$n", [
rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b),
@ -1347,9 +1356,9 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
putIntoDest(p, d, e.typ, ropef("($2 $1 $3)", [
toRope(opr[m]), rdLoc(a), rdLoc(b)]))
if optNanCheck in p.options:
appcg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)])
lineCg(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)])
if optInfCheck in p.options:
appcg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)])
lineCg(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)])
else:
binaryArith(p, e, d, m)
@ -1470,35 +1479,35 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
if d.k == locNone: getTemp(p, e.typ, d)
if getSize(e.typ) > 8:
# big set:
appf(p.s(cpsStmts), "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
lineF(p, cpsStmts, "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
for i in countup(0, sonsLen(e) - 1):
if e.sons[i].kind == nkRange:
getTemp(p, getSysType(tyInt), idx) # our counter
initLocExpr(p, e.sons[i].sons[0], a)
initLocExpr(p, e.sons[i].sons[1], b)
appf(p.s(cpsStmts), "for ($1 = $3; $1 <= $4; $1++) $n" &
lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" &
"$2[$1/8] |=(1<<($1%8));$n", [rdLoc(idx), rdLoc(d),
rdSetElemLoc(a, e.typ), rdSetElemLoc(b, e.typ)])
else:
initLocExpr(p, e.sons[i], a)
appf(p.s(cpsStmts), "$1[$2/8] |=(1<<($2%8));$n",
lineF(p, cpsStmts, "$1[$2/8] |=(1<<($2%8));$n",
[rdLoc(d), rdSetElemLoc(a, e.typ)])
else:
# small set
var ts = "NI" & $(getSize(e.typ) * 8)
appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(d)])
lineF(p, cpsStmts, "$1 = 0;$n", [rdLoc(d)])
for i in countup(0, sonsLen(e) - 1):
if e.sons[i].kind == nkRange:
getTemp(p, getSysType(tyInt), idx) # our counter
initLocExpr(p, e.sons[i].sons[0], a)
initLocExpr(p, e.sons[i].sons[1], b)
appf(p.s(cpsStmts), "for ($1 = $3; $1 <= $4; $1++) $n" &
lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" &
"$2 |=(1<<((" & ts & ")($1)%(sizeof(" & ts & ")*8)));$n", [
rdLoc(idx), rdLoc(d), rdSetElemLoc(a, e.typ),
rdSetElemLoc(b, e.typ)])
else:
initLocExpr(p, e.sons[i], a)
appf(p.s(cpsStmts),
lineF(p, cpsStmts,
"$1 |=(1<<((" & ts & ")($2)%(sizeof(" & ts & ")*8)));$n",
[rdLoc(d), rdSetElemLoc(a, e.typ)])
@ -1539,7 +1548,7 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
initLocExpr(p, n.sons[0], a)
initLocExpr(p, n.sons[1], b)
getTemp(p, n.typ, tmp)
appcg(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
lineCg(p, cpsStmts, "$1.ClPrc = $2; $1.ClEnv = $3;$n",
tmp.rdLoc, a.rdLoc, b.rdLoc)
putLocIntoDest(p, d, tmp)
@ -1579,10 +1588,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
app(r, ".Sup")
t = skipTypes(t.sons[0], abstractInst)
if nilCheck != nil:
appcg(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
lineCg(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
[nilCheck, r, genTypeInfo(p.module, dest)])
else:
appcg(p, cpsStmts, "#chckObj($1.m_type, $2);$n",
lineCg(p, cpsStmts, "#chckObj($1.m_type, $2);$n",
[r, genTypeInfo(p.module, dest)])
if n.sons[0].typ.kind != tyObject:
putIntoDest(p, d, n.typ,
@ -1675,8 +1684,8 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
InternalError(e.info, "expr: param not init " & sym.name.s)
putLocIntoDest(p, d, sym.loc)
else: InternalError(e.info, "expr(" & $sym.kind & "); unknown symbol")
of nkStrLit..nkTripleStrLit, nkIntLit..nkInt64Lit, nkFloatLit..nkFloat64Lit,
nkNilLit, nkCharLit:
of nkStrLit..nkTripleStrLit, nkIntLit..nkUInt64Lit,
nkFloatLit..nkFloat128Lit, nkNilLit, nkCharLit:
putIntoDest(p, d, e.typ, genLiteral(p, e))
of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand,
nkCallStrLit:

View file

@ -49,12 +49,12 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
proc startBlock(p: BProc, start: TFormatStr = "{$n",
args: openarray[PRope]): int {.discardable.} =
lineCg(p, cpsStmts, start, args)
inc(p.labels)
result = len(p.blocks)
setlen(p.blocks, result + 1)
p.blocks[result].id = p.labels
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len
appcg(p, cpsLocals, start, args)
proc assignLabel(b: var TBlock): PRope {.inline.} =
b.label = con("LA", b.id.toRope)
@ -70,7 +70,7 @@ proc endBlock(p: BProc, blockEnd: PRope) =
setlen(p.blocks, topBlock)
# this is done after the block is popped so $n is
# properly indented when pretty printing is enabled
app(p.s(cpsStmts), blockEnd)
line(p, cpsStmts, blockEnd)
var gBlockEndBracket = ropef("}$n")
@ -184,12 +184,12 @@ proc genIfStmt(p: BProc, n: PNode) =
initLocExpr(p, it.sons[0], a)
Lelse = getLabel(p)
inc(p.labels)
appff(p.s(cpsStmts), "if (!$1) goto $2;$n",
"br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n",
lineFF(p, cpsStmts, "if (!$1) goto $2;$n",
"br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n",
[rdLoc(a), Lelse, toRope(p.labels)])
genSimpleBlock(p, it.sons[1])
if sonsLen(n) > 1:
appff(p.s(cpsStmts), "goto $1;$n", "br label %$1$n", [Lend])
lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [Lend])
fixLabel(p, Lelse)
of nkElse:
genSimpleBlock(p, it.sons[0])
@ -205,23 +205,29 @@ proc blockLeaveActions(p: BProc, howMany: int) =
stack[i-1] = p.nestedTryStmts[L-i]
setLen(p.nestedTryStmts, L-howMany)
var alreadyPoppedCnt = p.inExceptBlock
for tryStmt in items(stack):
appcg(p, cpsStmts, "#popSafePoint();$n", [])
if gCmd != cmdCompileToCpp:
if alreadyPoppedCnt > 0:
dec alreadyPoppedCnt
else:
lineCg(p, cpsStmts, "#popSafePoint();$n", [])
var finallyStmt = lastSon(tryStmt)
if finallyStmt.kind == nkFinally:
genStmts(p, finallyStmt.sons[0])
# push old elements again:
for i in countdown(howMany-1, 0):
p.nestedTryStmts.add(stack[i])
for i in countdown(p.popCurrExc-1, 0):
appcg(p, cpsStmts, "#popCurrentException();$n", [])
if gCmd != cmdCompileToCpp:
for i in countdown(p.inExceptBlock-1, 0):
lineCg(p, cpsStmts, "#popCurrentException();$n", [])
proc genReturnStmt(p: BProc, t: PNode) =
p.beforeRetNeeded = true
genLineDir(p, t)
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
blockLeaveActions(p, min(1, p.nestedTryStmts.len))
appff(p.s(cpsStmts), "goto BeforeRet;$n", "br label %BeforeRet$n", [])
lineFF(p, cpsStmts, "goto BeforeRet;$n", "br label %BeforeRet$n", [])
proc genWhileStmt(p: BProc, t: PNode) =
# we don't generate labels here as for example GCC would produce
@ -239,7 +245,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
initLocExpr(p, t.sons[0], a)
if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
let label = assignLabel(p.blocks[p.breakIdx])
appf(p.s(cpsStmts), "if (!$1) goto $2;$n", [rdLoc(a), label])
lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label])
genStmts(p, t.sons[1])
endBlock(p)
@ -273,7 +279,7 @@ proc genParForStmt(p: BProc, t: PNode) =
initLocExpr(p, call.sons[1], rangeA)
initLocExpr(p, call.sons[2], rangeB)
appf(p.s(cpsStmts), "#pragma omp parallel for $4$n" &
lineF(p, cpsStmts, "#pragma omp parallel for $4$n" &
"for ($1 = $2; $1 <= $3; ++$1)",
forLoopVar.loc.rdLoc,
rangeA.rdLoc, rangeB.rdLoc,
@ -302,29 +308,35 @@ proc genBreakStmt(p: BProc, t: PNode) =
let label = assignLabel(p.blocks[idx])
blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts)
genLineDir(p, t)
appf(p.s(cpsStmts), "goto $1;$n", [label])
lineF(p, cpsStmts, "goto $1;$n", [label])
proc getRaiseFrmt(p: BProc): string =
#if gCmd == cmdCompileToCpp:
# result = "throw #nimException($1, $2);$n"
#else:
result = "#raiseException((#E_Base*)$1, $2);$n"
if gCmd == cmdCompileToCpp:
result = "throw NimException($1, $2);$n"
else:
result = "#raiseException((#E_Base*)$1, $2);$n"
proc genRaiseStmt(p: BProc, t: PNode) =
proc genRaiseStmt(p: BProc, t: PNode) =
if p.inExceptBlock > 0:
# if the current try stmt have a finally block,
# we must execute it before reraising
var finallyBlock = p.nestedTryStmts[p.nestedTryStmts.len - 1].lastSon
if finallyBlock.kind == nkFinally:
genSimpleBlock(p, finallyBlock.sons[0])
if t.sons[0].kind != nkEmpty:
var a: TLoc
InitLocExpr(p, t.sons[0], a)
var e = rdLoc(a)
var typ = skipTypes(t.sons[0].typ, abstractPtrs)
genLineDir(p, t)
appcg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
lineCg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
else:
genLineDir(p, t)
# reraise the last exception:
#if gCmd == cmdCompileToCpp:
# appcg(p, cpsStmts, "throw;$n")
#else:
appcg(p, cpsStmts, "#reraiseException();$n")
if gCmd == cmdCompileToCpp:
lineCg(p, cpsStmts, "throw;$n")
else:
lineCg(p, cpsStmts, "#reraiseException();$n")
proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
rangeFormat, eqFormat: TFormatStr, labl: TLabel) =
@ -335,20 +347,20 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
if b.sons[i].kind == nkRange:
initLocExpr(p, b.sons[i].sons[0], x)
initLocExpr(p, b.sons[i].sons[1], y)
appcg(p, cpsStmts, rangeFormat,
lineCg(p, cpsStmts, rangeFormat,
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
else:
initLocExpr(p, b.sons[i], x)
appcg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
lineCg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
proc genCaseSecondPass(p: BProc, t: PNode, labId, until: int): TLabel =
var Lend = getLabel(p)
for i in 1..until:
appf(p.s(cpsStmts), "LA$1: ;$n", [toRope(labId + i)])
lineF(p, cpsStmts, "LA$1: ;$n", [toRope(labId + i)])
if t.sons[i].kind == nkOfBranch:
var length = sonsLen(t.sons[i])
genSimpleBlock(p, t.sons[i].sons[length - 1])
appf(p.s(cpsStmts), "goto $1;$n", [Lend])
lineF(p, cpsStmts, "goto $1;$n", [Lend])
else:
genSimpleBlock(p, t.sons[i].sons[0])
result = Lend
@ -363,13 +375,13 @@ proc genIfForCaseUntil(p: BProc, t: PNode, rangeFormat, eqFormat: TFormatStr,
genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
con("LA", toRope(p.labels)))
else:
appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(p.labels)])
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)])
if until < t.len-1:
inc(p.labels)
var gotoTarget = p.labels
appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(gotoTarget)])
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(gotoTarget)])
result = genCaseSecondPass(p, t, labId, until)
appf(p.s(cpsStmts), "LA$1: ;$n", [toRope(gotoTarget)])
lineF(p, cpsStmts, "LA$1: ;$n", [toRope(gotoTarget)])
else:
result = genCaseSecondPass(p, t, labId, until)
@ -411,7 +423,7 @@ proc genStringCase(p: BProc, t: PNode) =
else:
# else statement: nothing to do yet
# but we reserved a label, which we use later
appcg(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
lineCg(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
[rdLoc(a), toRope(bitMask)])
for j in countup(0, high(branches)):
when false:
@ -421,11 +433,11 @@ proc genStringCase(p: BProc, t: PNode) =
if interior != brn:
echo "BUG! ", interior, "-", brn
if branches[j] != nil:
appf(p.s(cpsStmts), "case $1: $n$2break;$n",
lineF(p, cpsStmts, "case $1: $n$2break;$n",
[intLiteral(j), branches[j]])
appf(p.s(cpsStmts), "}$n") # else statement:
lineF(p, cpsStmts, "}$n") # else statement:
if t.sons[sonsLen(t) - 1].kind != nkOfBranch:
appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(p.labels)])
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)])
# third pass: generate statements
var Lend = genCaseSecondPass(p, t, labId, sonsLen(t)-1)
fixLabel(p, Lend)
@ -454,16 +466,16 @@ proc genCaseRange(p: BProc, branch: PNode) =
for j in 0 .. length-2:
if branch[j].kind == nkRange:
if hasSwitchRange in CC[ccompiler].props:
appf(p.s(cpsStmts), "case $1 ... $2:$n", [
lineF(p, cpsStmts, "case $1 ... $2:$n", [
genLiteral(p, branch[j][0]),
genLiteral(p, branch[j][1])])
else:
var v = copyNode(branch[j][0])
while v.intVal <= branch[j][1].intVal:
appf(p.s(cpsStmts), "case $1:$n", [genLiteral(p, v)])
lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, v)])
Inc(v.intVal)
else:
appf(p.s(cpsStmts), "case $1:$n", [genLiteral(p, branch[j])])
lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, branch[j])])
proc genOrdinalCase(p: BProc, n: PNode) =
# analyse 'case' statement:
@ -479,7 +491,7 @@ proc genOrdinalCase(p: BProc, n: PNode) =
# generate switch part (might be empty):
if splitPoint+1 < n.len:
appf(p.s(cpsStmts), "switch ($1) {$n", [rdCharLoc(a)])
lineF(p, cpsStmts, "switch ($1) {$n", [rdCharLoc(a)])
var hasDefault = false
for i in splitPoint+1 .. < n.len:
var branch = n[i]
@ -488,13 +500,13 @@ proc genOrdinalCase(p: BProc, n: PNode) =
genSimpleBlock(p, branch.lastSon)
else:
# else part of case statement:
appf(p.s(cpsStmts), "default:$n")
lineF(p, cpsStmts, "default:$n")
genSimpleBlock(p, branch[0])
hasDefault = true
appf(p.s(cpsStmts), "break;$n")
lineF(p, cpsStmts, "break;$n")
if (hasAssume in CC[ccompiler].props) and not hasDefault:
appf(p.s(cpsStmts), "default: __assume(0);$n")
appf(p.s(cpsStmts), "}$n")
lineF(p, cpsStmts, "default: __assume(0);$n")
lineF(p, cpsStmts, "}$n")
if Lend != nil: fixLabel(p, Lend)
proc genCaseStmt(p: BProc, t: PNode) =
@ -518,80 +530,86 @@ proc hasGeneralExceptSection(t: PNode): bool =
inc(i)
result = false
proc genTryStmtCpp(p: BProc, t: PNode) =
proc genTryStmtCpp(p: BProc, t: PNode) =
# code to generate:
#
# bool tmpRethrow = false;
# XXX: There should be a standard dispatch algorithm
# that's used both here and with multi-methods
#
# try
# {
# myDiv(4, 9);
# } catch (NimException& tmp) {
# tmpRethrow = true;
# switch (tmp.exc)
# {
# case DIVIDE_BY_ZERO:
# tmpRethrow = false;
# printf("Division by Zero\n");
# break;
# default: // used for general except!
# generalExceptPart();
# tmpRethrow = false;
# } catch (NimException& exp) {
# if (isObj(exp, EIO) {
# ...
# } else if (isObj(exp, ESystem) {
# ...
# finallyPart()
# raise;
# } else {
# // general handler
# }
# }
# excHandler = excHandler->prev; // we handled the exception
# finallyPart();
# if (tmpRethrow) throw;
#
# XXX: push blocks
var
rethrowFlag: PRope
var
exc: PRope
i, length, blen: int
genLineDir(p, t)
rethrowFlag = nil
exc = getTempName()
if not hasGeneralExceptSection(t):
rethrowFlag = getTempName()
appf(p.s(cpsLocals), "volatile NIM_BOOL $1 = NIM_FALSE;$n", [rethrowFlag])
if optStackTrace in p.Options:
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
appf(p.s(cpsStmts), "try {$n")
discard cgsym(p.module, "E_Base")
add(p.nestedTryStmts, t)
startBlock(p, "try {$n")
genStmts(p, t.sons[0])
length = sonsLen(t)
if t.sons[1].kind == nkExceptBranch:
appf(p.s(cpsStmts), "} catch (NimException& $1) {$n", [exc])
if rethrowFlag != nil:
appf(p.s(cpsStmts), "$1 = NIM_TRUE;$n", [rethrowFlag])
appf(p.s(cpsStmts), "if ($1.sp.exc) {$n", [exc])
endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc]))
if optStackTrace in p.Options:
lineCg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
inc p.inExceptBlock
i = 1
while (i < length) and (t.sons[i].kind == nkExceptBranch):
var catchAllPresent = false
while (i < length) and (t.sons[i].kind == nkExceptBranch):
blen = sonsLen(t.sons[i])
if blen == 1:
if i > 1: appf(p.s(cpsStmts), "else ")
if blen == 1:
# general except section:
appf(p.s(cpsStmts), "default:$n")
genStmts(p, t.sons[i].sons[0])
else:
for j in countup(0, blen - 2):
catchAllPresent = true
genSimpleBlock(p, t.sons[i].sons[0])
else:
var orExpr: PRope = nil
for j in countup(0, blen - 2):
assert(t.sons[i].sons[j].kind == nkType)
appf(p.s(cpsStmts), "case $1:$n", [toRope(t.sons[i].sons[j].typ.id)])
genStmts(p, t.sons[i].sons[blen - 1])
if rethrowFlag != nil:
appf(p.s(cpsStmts), "$1 = NIM_FALSE; ", [rethrowFlag])
appf(p.s(cpsStmts), "break;$n")
if orExpr != nil: app(orExpr, "||")
appcg(p.module, orExpr,
"#isObj($1.exp->m_type, $2)",
[exc, genTypeInfo(p.module, t.sons[i].sons[j].typ)])
lineF(p, cpsStmts, "if ($1) ", [orExpr])
genSimpleBlock(p, t.sons[i].sons[blen-1])
inc(i)
if t.sons[1].kind == nkExceptBranch:
appf(p.s(cpsStmts), "}}$n") # end of catch-switch statement
appcg(p, cpsStmts, "#popSafePoint();")
# reraise the exception if there was no catch all
# and none of the handlers matched
if not catchAllPresent:
if i > 1: lineF(p, cpsStmts, "else ")
startBlock(p)
var finallyBlock = t.lastSon
if finallyBlock.kind == nkFinally:
genStmts(p, finallyBlock.sons[0])
lineCg(p, cpsStmts, "throw;$n")
endBlock(p)
lineF(p, cpsStmts, "}$n") # end of catch block
dec p.inExceptBlock
discard pop(p.nestedTryStmts)
if (i < length) and (t.sons[i].kind == nkFinally):
genStmts(p, t.sons[i].sons[0])
if rethrowFlag != nil:
appf(p.s(cpsStmts), "if ($1) { throw; }$n", [rethrowFlag])
if (i < length) and (t.sons[i].kind == nkFinally):
genSimpleBlock(p, t.sons[i].sons[0])
proc genTryStmt(p: BProc, t: PNode) =
# code to generate:
#
# XXX: There should be a standard dispatch algorithm
# that's used both here and with multi-methods
#
# TSafePoint sp;
# pushSafePoint(&sp);
# sp.status = setjmp(sp.context);
@ -618,50 +636,52 @@ proc genTryStmt(p: BProc, t: PNode) =
genLineDir(p, t)
var safePoint = getTempName()
discard cgsym(p.module, "E_Base")
appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
"$1.status = setjmp($1.context);$n", [safePoint])
if optStackTrace in p.Options:
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
lineCg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
lineCg(p, cpsStmts, "#pushSafePoint(&$1);$n", [safePoint])
lineF(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
var length = sonsLen(t)
add(p.nestedTryStmts, t)
genStmts(p, t.sons[0])
endBlock(p, ropecg(p.module, "#popSafePoint();$n } else {$n#popSafePoint();$n"))
discard pop(p.nestedTryStmts)
linecg(p, cpsStmts, "#popSafePoint();$n")
endBlock(p)
startBlock(p, "else {$n")
lineCg(p, cpsStmts, "#popSafePoint();$n")
if optStackTrace in p.Options:
lineCg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
inc p.inExceptBlock
var i = 1
while (i < length) and (t.sons[i].kind == nkExceptBranch):
while (i < length) and (t.sons[i].kind == nkExceptBranch):
var blen = sonsLen(t.sons[i])
if blen == 1:
if blen == 1:
# general except section:
if i > 1: appf(p.s(cpsStmts), "else")
if i > 1: lineF(p, cpsStmts, "else")
startBlock(p)
appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
inc p.popCurrExc
lineCg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
genStmts(p, t.sons[i].sons[0])
dec p.popCurrExc
appcg(p, cpsStmts, "#popCurrentException();$n", [])
lineCg(p, cpsStmts, "#popCurrentException();$n")
endBlock(p)
else:
inc p.popCurrExc
var orExpr: PRope = nil
for j in countup(0, blen - 2):
for j in countup(0, blen - 2):
assert(t.sons[i].sons[j].kind == nkType)
if orExpr != nil: app(orExpr, "||")
appcg(p.module, orExpr,
"#isObj(#getCurrentException()->Sup.m_type, $1)",
appcg(p.module, orExpr,
"#isObj(#getCurrentException()->Sup.m_type, $1)",
[genTypeInfo(p.module, t.sons[i].sons[j].typ)])
if i > 1: app(p.s(cpsStmts), "else ")
if i > 1: line(p, cpsStmts, "else ")
startBlock(p, "if ($1) {$n", [orExpr])
appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
lineCg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
genStmts(p, t.sons[i].sons[blen-1])
dec p.popCurrExc
endBlock(p, ropecg(p.module, "#popCurrentException();}$n"))
lineCg(p, cpsStmts, "#popCurrentException();$n")
endBlock(p)
inc(i)
appf(p.s(cpsStmts), "}$n") # end of else block
dec p.inExceptBlock
discard pop(p.nestedTryStmts)
endBlock(p) # end of else block
if i < length and t.sons[i].kind == nkFinally:
genSimpleBlock(p, t.sons[i].sons[0])
appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
lineCg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
proc genAsmOrEmitStmt(p: BProc, t: PNode): PRope =
for i in countup(0, sonsLen(t) - 1):
@ -688,7 +708,7 @@ proc genAsmStmt(p: BProc, t: PNode) =
assert(t.kind == nkAsmStmt)
genLineDir(p, t)
var s = genAsmOrEmitStmt(p, t)
appf(p.s(cpsStmts), CC[ccompiler].asmStmtFrmt, [s])
lineF(p, cpsStmts, CC[ccompiler].asmStmtFrmt, [s])
proc genEmit(p: BProc, t: PNode) =
genLineDir(p, t)
@ -697,7 +717,7 @@ proc genEmit(p: BProc, t: PNode) =
# top level emit pragma?
app(p.module.s[cfsProcHeaders], s)
else:
app(p.s(cpsStmts), s)
line(p, cpsStmts, s)
var
breakPointId: int = 0
@ -723,7 +743,7 @@ proc genWatchpoint(p: BProc, n: PNode) =
var a: TLoc
initLocExpr(p, n.sons[1], a)
let typ = skipTypes(n.sons[1].typ, abstractVarRange)
appcg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n",
lineCg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n",
[a.addrLoc, makeCString(renderTree(n.sons[1])),
genTypeInfo(p.module, typ)])
@ -763,7 +783,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
if not ContainsOrIncl(p.module.declaredThings, field.id):
appcg(p.module, cfsVars, "extern $1",
discriminatorTableDecl(p.module, t, field))
appcg(p, cpsStmts,
lineCg(p, cpsStmts,
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
intLiteral(L+1)])
@ -820,9 +840,8 @@ proc genStmts(p: BProc, t: PNode) =
initLocExpr(p, t.sons[0], a)
of nkAsmStmt: genAsmStmt(p, t)
of nkTryStmt:
#if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t)
#else:
genTryStmt(p, t)
if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t)
else: genTryStmt(p, t)
of nkRaiseStmt: genRaiseStmt(p, t)
of nkTypeSection:
# we have to emit the type information for object types here to support

View file

@ -19,10 +19,10 @@ proc AccessThreadLocalVar(p: BProc, s: PSym) =
if emulatedThreadVars() and not p.ThreadVarAccessed:
p.ThreadVarAccessed = true
p.module.usesThreadVars = true
appf(p.procSec(cpsLocals), "NimThreadVars* NimTV;$n")
appf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV;$n")
app(p.procSec(cpsInit),
ropecg(p.module, "NimTV=(NimThreadVars*)#GetThreadLocalVars();$n"))
ropecg(p.module, "\tNimTV = (NimThreadVars*) #GetThreadLocalVars();$n"))
var
nimtv: PRope # nimrod thread vars; the struct body
nimtvDeps: seq[PType] = @[] # type deps: every module needs whole struct

View file

@ -31,17 +31,17 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) =
if (n.sons[0].kind != nkSym): InternalError(n.info, "genTraverseProc")
var p = c.p
let disc = n.sons[0].sym
p.s(cpsStmts).appf("switch ($1.$2) {$n", accessor, disc.loc.r)
lineF(p, cpsStmts, "switch ($1.$2) {$n", accessor, disc.loc.r)
for i in countup(1, sonsLen(n) - 1):
let branch = n.sons[i]
assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch:
genCaseRange(c.p, branch)
else:
p.s(cpsStmts).appf("default:$n")
lineF(p, cpsStmts, "default:$n")
genTraverseProc(c, accessor, lastSon(branch))
p.s(cpsStmts).appf("break;$n")
p.s(cpsStmts).appf("} $n")
lineF(p, cpsStmts, "break;$n")
lineF(p, cpsStmts, "} $n")
of nkSym:
let field = n.sym
genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t)
@ -63,10 +63,10 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
let arraySize = lengthOrd(typ.sons[0])
var i: TLoc
getTemp(p, getSysType(tyInt), i)
appf(p.s(cpsStmts), "for ($1 = 0; $1 < $2; $1++) {$n",
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
i.r, arraySize.toRope)
genTraverseProc(c, ropef("$1[$2]", accessor, i.r), typ.sons[1])
appf(p.s(cpsStmts), "}$n")
lineF(p, cpsStmts, "}$n")
of tyObject:
for i in countup(0, sonsLen(typ) - 1):
genTraverseProc(c, accessor.parentObj, typ.sons[i])
@ -79,7 +79,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
for i in countup(0, sonsLen(typ) - 1):
genTraverseProc(c, ropef("$1.Field$2", accessor, i.toRope), typ.sons[i])
of tyRef, tyString, tySequence:
appcg(p, cpsStmts, c.visitorFrmt, accessor)
lineCg(p, cpsStmts, c.visitorFrmt, accessor)
else:
# no marker procs for closures yet
nil
@ -89,10 +89,10 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: PRope, typ: PType) =
assert typ.kind == tySequence
var i: TLoc
getTemp(p, getSysType(tyInt), i)
appf(p.s(cpsStmts), "for ($1 = 0; $1 < $2->$3; $1++) {$n",
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2->$3; $1++) {$n",
i.r, accessor, toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len"))
genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0])
appf(p.s(cpsStmts), "}$n")
lineF(p, cpsStmts, "}$n")
proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
var c: TTraversalClosure
@ -106,8 +106,8 @@ proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
let header = ropef("N_NIMCALL(void, $1)(void* p, NI op)", result)
let t = getTypeDesc(m, typ)
p.s(cpsLocals).appf("$1 a;$n", t)
p.s(cpsInit).appf("a = ($1)p;$n", t)
lineF(p, cpsLocals, "$1 a;$n", t)
lineF(p, cpsInit, "a = ($1)p;$n", t)
c.p = p
if typ.kind == tySequence:

View file

@ -174,7 +174,7 @@ proc mapType(typ: PType): TCTypeKind =
of tyProc: result = if typ.callConv != ccClosure: ctProc else: ctStruct
of tyString: result = ctNimStr
of tyCString: result = ctCString
of tyInt..tyFloat128:
of tyInt..tyUInt64:
result = TCTypeKind(ord(typ.kind) - ord(tyInt) + ord(ctInt))
else: InternalError("mapType")
@ -313,8 +313,10 @@ proc typeNameOrLiteral(t: PType, literal: string): PRope =
proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
const
NumericalTypeToStr: array[tyInt..tyFloat128, string] = ["NI", "NI8",
"NI16", "NI32", "NI64", "NF", "NF32", "NF64", "NF128"]
NumericalTypeToStr: array[tyInt..tyUInt64, string] = [
"NI", "NI8", "NI16", "NI32", "NI64",
"NF", "NF32", "NF64", "NF128",
"NU", "NU8", "NU16", "NU32", "NU64",]
case typ.Kind
of tyPointer:
result = typeNameOrLiteral(typ, "void*")
@ -337,7 +339,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
of tyBool: result = typeNameOrLiteral(typ, "NIM_BOOL")
of tyChar: result = typeNameOrLiteral(typ, "NIM_CHAR")
of tyNil: result = typeNameOrLiteral(typ, "0")
of tyInt..tyFloat128, tyUInt..tyUInt64:
of tyInt..tyUInt64:
result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind])
of tyRange: result = getSimpleTypeDesc(m, typ.sons[0])
else: result = nil
@ -871,7 +873,7 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
if dataGenerated: return
case t.kind
of tyEmpty: result = toRope"0"
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyFloat128, tyVar:
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar:
genTypeInfoAuxBase(gNimDat, t, result, toRope"0")
of tyProc:
if t.callConv != ccClosure:

View file

@ -70,9 +70,7 @@ proc GetUniqueType*(key: PType): PType =
var k = key.kind
case k
of tyBool, tyChar,
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
tyFloat, tyFloat32, tyFloat64, tyFloat128,
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64:
tyInt..tyUInt64:
# no canonicalization for integral types, so that e.g. ``pid_t`` is
# produced instead of ``NI``.
result = key

View file

@ -153,6 +153,34 @@ proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr,
args: openarray[PRope]) =
app(p.s(s), ropecg(p.module, frmt, args))
var indent = "\t".toRope
proc indentLine(p: BProc, r: PRope): PRope =
result = r
for i in countup(0, p.blocks.len-1): prepend(result, indent)
proc line(p: BProc, s: TCProcSection, r: PRope) =
app(p.s(s), indentLine(p, r))
proc line(p: BProc, s: TCProcSection, r: string) =
app(p.s(s), indentLine(p, r.toRope))
proc lineF(p: BProc, s: TCProcSection, frmt: TFormatStr,
args: openarray[PRope]) =
app(p.s(s), indentLine(p, ropef(frmt, args)))
proc lineCg(p: BProc, s: TCProcSection, frmt: TFormatStr,
args: openarray[PRope]) =
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
proc appLineCg(p: BProc, r: var PRope, frmt: TFormatStr,
args: openarray[PRope]) =
app(r, indentLine(p, ropecg(p.module, frmt, args)))
proc lineFF(p: BProc, s: TCProcSection, cformat, llvmformat: string,
args: openarray[PRope]) =
if gCmd == cmdCompileToLLVM: lineF(p, s, llvmformat, args)
else: lineF(p, s, cformat, args)
proc safeLineNm(info: TLineInfo): int =
result = toLinenumber(info)
if result < 0: result = 0 # negative numbers are not allowed in #line
@ -171,11 +199,11 @@ proc genLineDir(p: BProc, t: PNode) =
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
(p.prc == nil or sfPure notin p.prc.flags):
appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
lineCg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
elif ({optLineTrace, optStackTrace} * p.Options ==
{optLineTrace, optStackTrace}) and
(p.prc == nil or sfPure notin p.prc.flags):
appf(p.s(cpsStmts), "F.line = $1;F.filename = $2;$n",
lineF(p, cpsStmts, "F.line = $1;F.filename = $2;$n",
[toRope(line), makeCString(toFilename(t.info).extractFilename)])
include "ccgtypes.nim"
@ -211,11 +239,11 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
while (s.kind == tyObject) and (s.sons[0] != nil):
app(r, ".Sup")
s = skipTypes(s.sons[0], abstractInst)
appcg(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
lineCg(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
of frEmbedded:
# worst case for performance:
var r = if takeAddr: addrLoc(a) else: rdLoc(a)
appcg(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
lineCg(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
type
TAssignmentFlag = enum
@ -238,16 +266,16 @@ proc resetLoc(p: BProc, loc: var TLoc) =
nilLoc.r = toRope("NIM_NIL")
genRefAssign(p, loc, nilLoc, {afSrcIsNil})
else:
appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(loc)])
lineF(p, cpsStmts, "$1 = 0;$n", [rdLoc(loc)])
else:
if loc.s != OnStack:
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
lineCg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
[addrLoc(loc), genTypeInfo(p.module, loc.t)])
# XXX: generated reset procs should not touch the m_type
# field, so disabling this should be safe:
genObjectInit(p, cpsStmts, loc.t, loc, true)
else:
appf(p.s(cpsStmts), "memset((void*)$1, 0, sizeof($2));$n",
lineF(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
[addrLoc(loc), rdLoc(loc)])
# XXX: We can be extra clever here and call memset only
# on the bytes following the m_type field?
@ -255,9 +283,9 @@ proc resetLoc(p: BProc, loc: var TLoc) =
proc constructLoc(p: BProc, loc: TLoc, section = cpsStmts) =
if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
appf(p.s(section), "$1 = 0;$n", [rdLoc(loc)])
lineF(p, section, "$1 = 0;$n", [rdLoc(loc)])
else:
appf(p.s(section), "memset((void*)$1, 0, sizeof($2));$n",
lineF(p, section, "memset((void*)$1, 0, sizeof($2));$n",
[addrLoc(loc), rdLoc(loc)])
genObjectInit(p, section, loc.t, loc, true)
@ -285,7 +313,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc) =
result.r = con("%LOC", toRope(p.labels))
else:
result.r = con("LOC", toRope(p.labels))
appf(p.s(cpsLocals), "$1 $2;$n", [getTypeDesc(p.module, t), result.r])
lineF(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t), result.r])
result.k = locTemp
result.a = - 1
result.t = getUniqueType(t)
@ -311,9 +339,9 @@ proc keepAlive(p: BProc, toKeepAlive: TLoc) =
result.flags = {}
if not isComplexValueType(skipTypes(toKeepAlive.t, abstractVarRange)):
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(result), rdLoc(toKeepAlive)])
lineF(p, cpsStmts, "$1 = $2;$n", [rdLoc(result), rdLoc(toKeepAlive)])
else:
appcg(p, cpsStmts,
lineCg(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
[addrLoc(result), addrLoc(toKeepAlive), rdLoc(result)])
@ -355,7 +383,7 @@ proc allocParam(p: BProc, s: PSym) =
var tmp = con("%LOC", toRope(p.labels))
incl(s.loc.flags, lfParamCopy)
incl(s.loc.flags, lfIndirect)
appf(p.s(cpsInit), "$1 = alloca $3$n" & "store $3 $2, $3* $1$n",
lineF(p, cpsInit, "$1 = alloca $3$n" & "store $3 $2, $3* $1$n",
[tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)])
s.loc.r = tmp
@ -365,7 +393,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
if skipTypes(s.typ, abstractVar).kind == tyOpenArray: return
var a = con("&", s.loc.r)
if (s.kind == skParam) and ccgIntroducedPtr(s): a = s.loc.r
appf(p.s(cpsInit),
lineF(p, cpsInit,
"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,
genTypeInfo(p.module, s.loc.t)])
@ -378,13 +406,14 @@ proc assignLocalVar(p: BProc, s: PSym) =
if s.loc.k == locNone:
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack)
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
app(p.s(cpsLocals), getTypeDesc(p.module, s.loc.t))
if sfRegister in s.flags: app(p.s(cpsLocals), " register")
var decl = getTypeDesc(p.module, s.loc.t)
if sfRegister in s.flags: app(decl, " register")
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
# app(p.s[cpsLocals], " GC_GUARD")
# app(decl, " GC_GUARD")
if (sfVolatile in s.flags) or (p.nestedTryStmts.len > 0):
app(p.s(cpsLocals), " volatile")
appf(p.s(cpsLocals), " $1;$n", [s.loc.r])
app(decl, " volatile")
appf(decl, " $1;$n", [s.loc.r])
line(p, cpsLocals, decl)
localDebugInfo(p, s)
include ccgthreadvars
@ -427,7 +456,7 @@ proc getLabel(p: BProc): TLabel =
result = con("LA", toRope(p.labels))
proc fixLabel(p: BProc, labl: TLabel) =
appf(p.s(cpsStmts), "$1: ;$n", [labl])
lineF(p, cpsStmts, "$1: ;$n", [labl])
proc genVarPrototype(m: BModule, sym: PSym)
proc requestConstImpl(p: BProc, sym: PSym)
@ -545,28 +574,28 @@ proc getFrameDecl(p: BProc) =
[toRope(p.frameLen)])
else:
slots = nil
appff(p.s(cpsLocals), "volatile struct {TFrame* prev;" &
"NCSTRING procname;NI line;NCSTRING filename;" &
"NI len;$n$1} F;$n",
lineFF(p, cpsLocals, "volatile struct {TFrame* prev;" &
"NCSTRING procname;NI line;NCSTRING filename;" &
"NI len;$1} F;$n",
"%TF = type {%TFrame*, i8*, %NI, %NI$1}$n" &
"%F = alloca %TF$n", [slots])
inc(p.labels)
prepend(p.s(cpsInit), ropeff("F.len = $1;$n",
prepend(p.s(cpsInit), indentLine(p, ropeff("F.len = $1;$n",
"%LOC$2 = getelementptr %TF %F, %NI 4$n" &
"store %NI $1, %NI* %LOC$2$n", [toRope(p.frameLen), toRope(p.labels)]))
"store %NI $1, %NI* %LOC$2$n", [toRope(p.frameLen), toRope(p.labels)])))
proc retIsNotVoid(s: PSym): bool =
result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0])
proc initFrame(p: BProc, procname, filename: PRope): PRope =
result = ropecg(p.module,
"F.procname = $1;$n" &
"F.filename = $2;$n" &
"F.line = 0;$n" &
"#pushFrame((TFrame*)&F);$n", [procname, filename])
"\tF.procname = $1;$n" &
"\tF.filename = $2;$n" &
"\tF.line = 0;$n" &
"\t#pushFrame((TFrame*)&F);$n", [procname, filename])
proc deinitFrame(p: BProc): PRope =
result = ropecg(p.module, "#popFrame();$n")
result = ropecg(p.module, "\t#popFrame();$n")
proc closureSetup(p: BProc, prc: PSym) =
if prc.typ.callConv != ccClosure: return
@ -578,8 +607,8 @@ proc closureSetup(p: BProc, prc: PSym) =
#echo "created environment: ", env.id, " for ", prc.name.s
assignLocalVar(p, env)
# generate cast assignment:
appcg(p, cpsStmts, "$1 = ($2) ClEnv;$n", rdLoc(env.loc),
getTypeDesc(p.module, env.typ))
lineCg(p, cpsStmts, "$1 = ($2) ClEnv;$n", rdLoc(env.loc),
getTypeDesc(p.module, env.typ))
proc genProcAux(m: BModule, prc: PSym) =
var p = newProc(prc, m)
@ -593,7 +622,7 @@ proc genProcAux(m: BModule, prc: PSym) =
# declare the result symbol:
assignLocalVar(p, res)
assert(res.loc.r != nil)
returnStmt = ropeff("return $1;$n", "ret $1$n", [rdLoc(res.loc)])
returnStmt = ropeff("\treturn $1;$n", "ret $1$n", [rdLoc(res.loc)])
initLocalVar(p, res, immediateAsgn=false)
else:
fillResult(res)
@ -609,10 +638,10 @@ proc genProcAux(m: BModule, prc: PSym) =
genStmts(p, prc.getBody) # modifies p.locals, p.init, etc.
var generatedProc: PRope
if sfPure in prc.flags:
generatedProc = ropeff("$1 {$n$2$3$4}$n", "define $1 {$n$2$3$4}$n",
generatedProc = ropeff("$N$1 {$n$2$3$4}$N$N", "define $1 {$n$2$3$4}$N",
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)])
else:
generatedProc = ropeff("$1 {$n", "define $1 {$n", [header])
generatedProc = ropeff("$N$1 {$N", "$Ndefine $1 {$N", [header])
app(generatedProc, initGCFrame(p))
if optStackTrace in prc.options:
getFrameDecl(p)
@ -626,25 +655,25 @@ proc genProcAux(m: BModule, prc: PSym) =
if gProcProfile >= 64 * 1024:
InternalError(prc.info, "too many procedures for profiling")
discard cgsym(m, "profileData")
appf(p.s(cpsLocals), "ticks NIM_profilingStart;$n")
appf(p.s(cpsLocals), "\tticks NIM_profilingStart;$n")
if prc.loc.a < 0:
appf(m.s[cfsDebugInit], "profileData[$1].procname = $2;$n", [
appf(m.s[cfsDebugInit], "\tprofileData[$1].procname = $2;$n", [
toRope(gProcProfile),
makeCString(prc.name.s)])
prc.loc.a = gProcProfile
inc(gProcProfile)
prepend(p.s(cpsInit), ropef("NIM_profilingStart = getticks();$n"))
prepend(p.s(cpsInit), ropef("\tNIM_profilingStart = getticks();$n"))
app(generatedProc, p.s(cpsInit))
app(generatedProc, p.s(cpsStmts))
if p.beforeRetNeeded: appf(generatedProc, "BeforeRet: $n;")
if p.beforeRetNeeded: appf(generatedProc, "\tBeforeRet: ;$n")
app(generatedProc, deinitGCFrame(p))
if optStackTrace in prc.options: app(generatedProc, deinitFrame(p))
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
appf(generatedProc,
"profileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n",
"\tprofileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n",
[toRope(prc.loc.a)])
app(generatedProc, returnStmt)
appf(generatedProc, "}$n")
appf(generatedProc, "}$N")
app(m.s[cfsProcs], generatedProc)
proc genProcPrototype(m: BModule, sym: PSym) =

View file

@ -37,9 +37,11 @@ type
cfsDynLibDeinit # section for deinitialization of dynamic
# libraries
TCTypeKind* = enum # describes the type kind of a C type
ctVoid, ctChar, ctBool, ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
ctInt, ctInt8, ctInt16, ctInt32, ctInt64, ctFloat, ctFloat32, ctFloat64,
ctFloat128, ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString
ctVoid, ctChar, ctBool,
ctInt, ctInt8, ctInt16, ctInt32, ctInt64,
ctFloat, ctFloat32, ctFloat64, ctFloat128,
ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
ctArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctCString
TCFileSections* = array[TCFileSection, PRope] # represents a generated C file
TCProcSection* = enum # the sections a generated C proc consists of
cpsLocals, # section of local variables for C proc
@ -62,8 +64,9 @@ type
ThreadVarAccessed*: bool # true if the proc already accessed some threadvar
nestedTryStmts*: seq[PNode] # in how many nested try statements we are
# (the vars must be volatile then)
popCurrExc*: Natural # how often to emit 'popCurrentException()'
# before 'break'|'return'
inExceptBlock*: int # are we currently inside an except block?
# leaving such scopes by raise or by return must
# execute any applicable finally blocks
labels*: Natural # for generating unique labels in the C proc
blocks*: seq[TBlock] # nested blocks
breakIdx*: int # the block that will be exited

View file

@ -206,10 +206,10 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
of tkCharLit:
dispA(result, "<span class=\"CharLit\">$1</span>", "\\spanCharLit{$1}",
[toRope(esc(d.target, literal))])
of tkIntLit..tkInt64Lit:
of tkIntLit..tkUInt64Lit:
dispA(result, "<span class=\"DecNumber\">$1</span>",
"\\spanDecNumber{$1}", [toRope(esc(d.target, literal))])
of tkFloatLit..tkFloat64Lit:
of tkFloatLit..tkFloat128Lit:
dispA(result, "<span class=\"FloatNumber\">$1</span>",
"\\spanFloatNumber{$1}", [toRope(esc(d.target, literal))])
of tkSymbol:

View file

@ -235,6 +235,8 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
case t.kind
of tyBool, tyEnum, tyChar, tyInt..tyInt64:
result = newNodeIT(nkIntLit, info, t)
of tyUInt..tyUInt64:
result = newNodeIT(nkUIntLit, info, t)
of tyFloat..tyFloat128:
result = newNodeIt(nkFloatLit, info, t)
of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,

View file

@ -597,7 +597,7 @@ proc CallCCompiler*(projectfile: string) =
proc genMappingFiles(list: TLinkedList): PRope =
var it = PStrEntry(list.head)
while it != nil:
appf(result, "--file:r\"$1\"$n", [toRope(AddFileExt(it.data, cExt))])
appf(result, "--file:r\"$1\"$N", [toRope(AddFileExt(it.data, cExt))])
it = PStrEntry(it.next)
proc writeMapping*(gSymbolMapping: PRope) =

View file

@ -45,8 +45,10 @@ type
tkTemplate,
tkTry, tkTuple, tkType, tkVar, tkWhen, tkWhile, tkWith, tkWithout, tkXor,
tkYield, # end of keywords
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit, tkFloatLit,
tkFloat32Lit, tkFloat64Lit, tkStrLit, tkRStrLit, tkTripleStrLit,
tkIntLit, tkInt8Lit, tkInt16Lit, tkInt32Lit, tkInt64Lit,
tkUIntLit, tkUInt8Lit, tkUInt16Lit, tkUInt32Lit, tkUInt64Lit,
tkFloatLit, tkFloat32Lit, tkFloat64Lit, tkFloat128Lit,
tkStrLit, tkRStrLit, tkTripleStrLit,
tkGStrLit, tkGTripleStrLit, tkCharLit, tkParLe, tkParRi, tkBracketLe,
tkBracketRi, tkCurlyLe, tkCurlyRi,
tkBracketDotLe, tkBracketDotRi, # [. and .]
@ -77,8 +79,10 @@ const
"template",
"try", "tuple", "type", "var", "when", "while", "with", "without", "xor",
"yield",
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
"tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkStrLit", "tkRStrLit",
"tkIntLit", "tkInt8Lit", "tkInt16Lit", "tkInt32Lit", "tkInt64Lit",
"tkUIntLit", "tkUInt8Lit", "tkUInt16Lit", "tkUInt32Lit", "tkUInt64Lit",
"tkFloatLit", "tkFloat32Lit", "tkFloat64Lit", "tkFloat128Lit",
"tkStrLit", "tkRStrLit",
"tkTripleStrLit", "tkGStrLit", "tkGTripleStrLit", "tkCharLit", "(",
")", "[", "]", "{", "}", "[.", ".]", "{.", ".}", "(.", ".)",
",", ";",
@ -283,12 +287,17 @@ proc GetNumber(L: var TLexer): TToken =
case L.buf[endpos]
of 'f', 'F':
inc(endpos)
if (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'):
result.tokType = tkFloat64Lit
inc(endpos, 2)
elif (L.buf[endpos] == '3') and (L.buf[endpos + 1] == '2'):
if (L.buf[endpos] == '3') and (L.buf[endpos + 1] == '2'):
result.tokType = tkFloat32Lit
inc(endpos, 2)
elif (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'):
result.tokType = tkFloat64Lit
inc(endpos, 2)
elif (L.buf[endpos] == '1') and
(L.buf[endpos + 1] == '2') and
(L.buf[endpos + 2] == '8'):
result.tokType = tkFloat128Lit
inc(endpos, 3)
else:
lexMessage(L, errInvalidNumber, result.literal & "'f" & L.buf[endpos])
of 'i', 'I':
@ -307,6 +316,22 @@ proc GetNumber(L: var TLexer): TToken =
inc(endpos)
else:
lexMessage(L, errInvalidNumber, result.literal & "'i" & L.buf[endpos])
of 'u', 'U':
inc(endpos)
if (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'):
result.tokType = tkUInt64Lit
inc(endpos, 2)
elif (L.buf[endpos] == '3') and (L.buf[endpos + 1] == '2'):
result.tokType = tkUInt32Lit
inc(endpos, 2)
elif (L.buf[endpos] == '1') and (L.buf[endpos + 1] == '6'):
result.tokType = tkUInt16Lit
inc(endpos, 2)
elif (L.buf[endpos] == '8'):
result.tokType = tkUInt8Lit
inc(endpos)
else:
result.tokType = tkUIntLit
else: lexMessage(L, errInvalidNumber, result.literal & "'" & L.buf[endpos])
else:
L.bufpos = pos # restore position
@ -378,6 +403,10 @@ proc GetNumber(L: var TLexer): TToken =
of tkInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi))))
of tkInt16Lit: result.iNumber = biggestInt(toU16(int(xi)))
of tkInt32Lit: result.iNumber = biggestInt(toU32(xi))
of tkUIntLit, tkUInt64Lit: result.iNumber = xi
of tkUInt8Lit: result.iNumber = biggestInt(int8(toU8(int(xi))))
of tkUInt16Lit: result.iNumber = biggestInt(toU16(int(xi)))
of tkUInt32Lit: result.iNumber = biggestInt(toU32(xi))
of tkFloat32Lit:
result.fNumber = (cast[PFloat32](addr(xi)))[]
# note: this code is endian neutral!

View file

@ -53,9 +53,15 @@ proc getSysType(kind: TTypeKind): PType =
of tyInt16: result = sysTypeFromName("int16")
of tyInt32: result = sysTypeFromName("int32")
of tyInt64: result = sysTypeFromName("int64")
of tyUInt: result = sysTypeFromName("uint")
of tyUInt8: result = sysTypeFromName("uint8")
of tyUInt16: result = sysTypeFromName("uint16")
of tyUInt32: result = sysTypeFromName("uint32")
of tyUInt64: result = sysTypeFromName("uint64")
of tyFloat: result = sysTypeFromName("float")
of tyFloat32: result = sysTypeFromName("float32")
of tyFloat64: result = sysTypeFromName("float64")
of tyFloat128: result = sysTypeFromName("float128")
of tyBool: result = sysTypeFromName("bool")
of tyChar: result = sysTypeFromName("char")
of tyString: result = sysTypeFromName("string")

View file

@ -416,6 +416,26 @@ proc identOrLiteral(p: var TParser): PNode =
result = newIntNodeP(nkInt64Lit, p.tok.iNumber, p)
setBaseFlags(result, p.tok.base)
getTok(p)
of tkUIntLit:
result = newIntNodeP(nkUIntLit, p.tok.iNumber, p)
setBaseFlags(result, p.tok.base)
getTok(p)
of tkUInt8Lit:
result = newIntNodeP(nkUInt8Lit, p.tok.iNumber, p)
setBaseFlags(result, p.tok.base)
getTok(p)
of tkUInt16Lit:
result = newIntNodeP(nkUInt16Lit, p.tok.iNumber, p)
setBaseFlags(result, p.tok.base)
getTok(p)
of tkUInt32Lit:
result = newIntNodeP(nkUInt32Lit, p.tok.iNumber, p)
setBaseFlags(result, p.tok.base)
getTok(p)
of tkUInt64Lit:
result = newIntNodeP(nkUInt64Lit, p.tok.iNumber, p)
setBaseFlags(result, p.tok.base)
getTok(p)
of tkFloatLit:
result = newFloatNodeP(nkFloatLit, p.tok.fNumber, p)
setBaseFlags(result, p.tok.base)
@ -428,6 +448,10 @@ proc identOrLiteral(p: var TParser): PNode =
result = newFloatNodeP(nkFloat64Lit, p.tok.fNumber, p)
setBaseFlags(result, p.tok.base)
getTok(p)
of tkFloat128Lit:
result = newFloatNodeP(nkFloat128Lit, p.tok.fNumber, p)
setBaseFlags(result, p.tok.base)
getTok(p)
of tkStrLit:
result = newStrNodeP(nkStrLit, p.tok.literal, p)
getTok(p)

View file

@ -23,7 +23,7 @@ const
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wNoStackFrame, wError, wDiscardable, wNoInit}
wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor}
converterPragmas* = procPragmas
methodPragmas* = procPragmas
templatePragmas* = {wImmediate, wDeprecated, wError}
@ -508,6 +508,11 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
incl(sym.loc.Flags, lfNoDecl)
# implies nodecl, because otherwise header would not make sense
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
of wDestructor:
if sym.typ.sons.len == 2:
sym.flags.incl sfDestructor
else:
invalidPragma(it)
of wNosideeffect:
noVal(it)
incl(sym.flags, sfNoSideEffect)

View file

@ -705,9 +705,15 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
of nkInt16Lit: put(g, tkInt16Lit, atom(n))
of nkInt32Lit: put(g, tkInt32Lit, atom(n))
of nkInt64Lit: put(g, tkInt64Lit, atom(n))
of nkUIntLit: put(g, tkUIntLit, atom(n))
of nkUInt8Lit: put(g, tkUInt8Lit, atom(n))
of nkUInt16Lit: put(g, tkUInt16Lit, atom(n))
of nkUInt32Lit: put(g, tkUInt32Lit, atom(n))
of nkUInt64Lit: put(g, tkUInt64Lit, atom(n))
of nkFloatLit: put(g, tkFloatLit, atom(n))
of nkFloat32Lit: put(g, tkFloat32Lit, atom(n))
of nkFloat64Lit: put(g, tkFloat64Lit, atom(n))
of nkFloat128Lit: put(g, tkFloat128Lit, atom(n))
of nkStrLit: put(g, tkStrLit, atom(n))
of nkRStrLit: put(g, tkRStrLit, atom(n))
of nkCharLit: put(g, tkCharLit, atom(n))

View file

@ -212,7 +212,11 @@ proc markUsed*(n: PNode, s: PSym) =
if {sfDeprecated, sfError} * s.flags != {}:
if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
if sfError in s.flags: LocalError(n.info, errWrongSymbolX, s.name.s)
proc useSym*(sym: PSym): PNode =
result = newSymNode(sym)
markUsed(result, sym)
proc illFormedAst*(n: PNode) =
GlobalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))

View file

@ -132,10 +132,10 @@ proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
proc checkConvertible(info: TLineInfo, castDest, src: PType) =
const
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyFloat128}
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
if sameType(castDest, src) and castDest.sym == src.sym:
# don't annoy conversions that may be needed on another processor:
if not (castDest.kind in {tyInt..tyFloat128, tyNil}):
if not (castDest.kind in {tyInt..tyUInt64, tyNil}):
Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
return
var d = skipTypes(castDest, abstractVar)
@ -143,7 +143,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind):
d = base(d)
s = base(s)
if d == nil:
if d == nil:
GlobalError(info, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [
src.typeToString, castDest.typeToString])
elif d.Kind == tyObject and s.Kind == tyObject:
@ -1283,6 +1283,20 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
GlobalError(n.info, errInvalidExpressionX,
renderTree(a, {renderNoComments}))
proc uniIntType(kind: TTypeKind): PType =
result = getSysType(kind).copyType(getCurrOwner(), true)
result.flags.incl(tfUniIntLit)
template memoize(e: expr): expr =
var `*guard` {.global.} = false
var `*memo` {.global.} : type(e)
if not `*guard`:
`*memo` = e
`*guard` = true
`*memo`
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = n
if gCmd == cmdIdeTools: suggestExpr(c, n)
@ -1303,9 +1317,15 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
if result.typ == nil:
let i = result.intVal
if i >= low(int32) and i <= high(int32):
result.typ = getSysType(tyInt)
if i >= 0:
result.typ = uniIntType(tyInt).memoize
else:
result.typ = getSysType(tyInt)
else:
result.typ = getSysType(tyInt64)
if i >= 0:
result.typ = uniIntType(tyInt64).memoize
else:
result.typ = getSysType(tyInt64)
of nkInt8Lit:
if result.typ == nil: result.typ = getSysType(tyInt8)
of nkInt16Lit:
@ -1314,12 +1334,24 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
if result.typ == nil: result.typ = getSysType(tyInt32)
of nkInt64Lit:
if result.typ == nil: result.typ = getSysType(tyInt64)
of nkUIntLit:
if result.typ == nil: result.typ = getSysType(tyUInt)
of nkUInt8Lit:
if result.typ == nil: result.typ = getSysType(tyUInt8)
of nkUInt16Lit:
if result.typ == nil: result.typ = getSysType(tyUInt16)
of nkUInt32Lit:
if result.typ == nil: result.typ = getSysType(tyUInt32)
of nkUInt64Lit:
if result.typ == nil: result.typ = getSysType(tyUInt64)
of nkFloatLit:
if result.typ == nil: result.typ = getSysType(tyFloat)
of nkFloat32Lit:
if result.typ == nil: result.typ = getSysType(tyFloat32)
of nkFloat64Lit:
if result.typ == nil: result.typ = getSysType(tyFloat64)
of nkFloat128Lit:
if result.typ == nil: result.typ = getSysType(tyFloat128)
of nkStrLit..nkTripleStrLit:
if result.typ == nil: result.typ = getSysType(tyString)
of nkCharLit:

View file

@ -258,15 +258,15 @@ proc partialOrExpr(c: PSym, n: PNode): PNode =
proc leValueConv(a, b: PNode): bool =
result = false
case a.kind
of nkCharLit..nkInt64Lit:
of nkCharLit..nkUInt64Lit:
case b.kind
of nkCharLit..nkInt64Lit: result = a.intVal <= b.intVal
of nkFloatLit..nkFloat64Lit: result = a.intVal <= round(b.floatVal)
of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal
of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal)
else: InternalError(a.info, "leValueConv")
of nkFloatLit..nkFloat64Lit:
of nkFloatLit..nkFloat128Lit:
case b.kind
of nkFloatLit..nkFloat64Lit: result = a.floatVal <= b.floatVal
of nkCharLit..nkInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal
of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
else: InternalError(a.info, "leValueConv")
else: InternalError(a.info, "leValueConv")

View file

@ -681,7 +681,9 @@ proc semLambda(c: PContext, n: PNode): PNode =
closeScope(c.tab) # close scope for parameters
popOwner()
result.typ = s.typ
proc instantiateDestructor*(c: PContext, typ: PType): bool
proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
validPragmas: TSpecialWords): PNode =
result = n
@ -743,6 +745,19 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
popOwner()
pushOwner(s)
s.options = gOptions
if sfDestructor in s.flags:
let t = s.typ.sons[1].skipTypes({tyVar})
t.destructor = s
# automatically insert calls to base classes' destructors
if n.sons[bodyPos].kind != nkEmpty:
for i in countup(0, t.sonsLen - 1):
# when inheriting directly from object
# there will be a single nil son
if t.sons[i] == nil: continue
if instantiateDestructor(c, t.sons[i]):
n.sons[bodyPos].addSon(newNode(nkCall, t.sym.info, @[
useSym(t.sons[i].destructor),
n.sons[paramsPos][1][0]]))
if n.sons[bodyPos].kind != nkEmpty:
# for DLL generation it is annoying to check for sfImportc!
if sfBorrow in s.flags:
@ -772,10 +787,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
incl(s.flags, sfForward)
elif sfBorrow in s.flags: semBorrow(c, n, s)
sideEffectsCheck(c, s)
if result.sons[namePos].sym.name.id == ord(wDestroy):
if s.typ.sons.len == 2:
let typ = s.typ.sons[1].skipTypes({tyVar})
typ.destructor = s
if s.typ.callConv == ccClosure and s.owner.kind == skModule:
localError(s.info, errXCannotBeClosure, s.name.s)
closeScope(c.tab) # close scope for parameters
@ -864,6 +875,134 @@ proc semStaticStmt(c: PContext, n: PNode): PNode =
if result.isNil:
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
# special marker values that indicates that we are
# 1) AnalyzingDestructor: currenlty analyzing the type for destructor
# generation (needed for recursive types)
# 2) DestructorIsTrivial: completed the anlysis before and determined
# that the type has a trivial destructor
var AnalyzingDestructor, DestructorIsTrivial: PSym
new(AnalyzingDestructor)
new(DestructorIsTrivial)
var
destructorName = getIdent"destroy_"
destructorParam = getIdent"this_"
destructorPragma = newIdentNode(getIdent"destructor", UnknownLineInfo())
rangeDestructorProc: PSym
proc destroyField(c: PContext, field: PSym, holder: PNode): PNode =
if instantiateDestructor(c, field.typ):
result = newNode(nkCall, field.info, @[
useSym(field.typ.destructor),
newNode(nkDotExpr, field.info, @[holder, useSym(field)])])
proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode =
var nonTrivialFields = 0
result = newNode(nkCaseStmt, n.info, @[])
# case x.kind
result.addSon(newNode(nkDotExpr, n.info, @[holder, n.sons[0]]))
for i in countup(1, n.len - 1):
# of A, B:
var caseBranch = newNode(n[i].kind, n[i].info, n[i].sons[0 .. -2])
let recList = n[i].lastSon
var destroyRecList = newNode(nkStmtList, n[i].info, @[])
template addField(f: expr): stmt =
let stmt = destroyField(c, f, holder)
if stmt != nil:
destroyRecList.addSon(stmt)
inc nonTrivialFields
case recList.kind
of nkSym:
addField(recList.sym)
of nkRecList:
for j in countup(0, recList.len - 1):
addField(recList[j].sym)
else:
internalAssert false
caseBranch.addSon(destroyRecList)
result.addSon(caseBranch)
# maybe no fields were destroyed?
if nonTrivialFields == 0:
result = nil
proc generateDestructor(c: PContext, t: PType): PNode =
## generate a destructor for a user-defined object ot tuple type
## returns nil if the destructor turns out to be trivial
template addLine(e: expr): stmt =
if result == nil: result = newNode(nkStmtList)
result.addSon(e)
# XXX: This may be true for some C-imported types such as
# Tposix_spawnattr
if t.n == nil or t.n.sons == nil: return
internalAssert t.n.kind == nkRecList
let destructedObj = newIdentNode(destructorParam, UnknownLineInfo())
# call the destructods of all fields
for s in countup(0, t.n.sons.len - 1):
case t.n.sons[s].kind
of nkRecCase:
let stmt = destroyCase(c, t.n.sons[s], destructedObj)
if stmt != nil: addLine(stmt)
of nkSym:
let stmt = destroyField(c, t.n.sons[s].sym, destructedObj)
if stmt != nil: addLine(stmt)
else:
internalAssert false
# base classes' destructors will be automatically called by
# semProcAux for both auto-generated and user-defined destructors
proc instantiateDestructor*(c: PContext, typ: PType): bool =
# returns true if the type already had a user-defined
# destructor or if the compiler generated a default
# member-wise one
var t = skipTypes(typ, {tyConst, tyMutable})
if t.destructor != nil:
# XXX: This is not entirely correct for recursive types, but we need
# it temporarily to hide the "destroy is alrady defined" problem
return t.destructor notin [AnalyzingDestructor, DestructorIsTrivial]
case t.kind
of tySequence, tyArray, tyArrayConstr, tyOpenArray:
if instantiateDestructor(c, t.sons[0]):
if rangeDestructorProc == nil:
rangeDestructorProc = SymtabGet(c.tab, getIdent"nimDestroyRange")
t.destructor = rangeDestructorProc
return true
else:
return false
of tyTuple, tyObject:
t.destructor = AnalyzingDestructor
let generated = generateDestructor(c, t)
if generated != nil:
internalAssert t.sym != nil
var i = t.sym.info
let fullDef = newNode(nkProcDef, i, @[
newIdentNode(destructorName, i),
emptyNode,
newNode(nkFormalParams, i, @[
emptyNode,
newNode(nkIdentDefs, i, @[
newIdentNode(destructorParam, i),
useSym(t.sym),
emptyNode]),
]),
newNode(nkPragma, i, @[destructorPragma]),
generated
])
discard semProc(c, fullDef)
internalAssert t.destructor != nil
return true
else:
t.destructor = DestructorIsTrivial
return false
else:
return false
proc insertDestructors(c: PContext, varSection: PNode):
tuple[outer: PNode, inner: PNode] =
# Accepts a var or let section.
@ -889,7 +1028,7 @@ proc insertDestructors(c: PContext, varSection: PNode):
varTyp = varId.sym.typ
info = varId.info
if varTyp != nil and instantiateDestructor(varTyp):
if varTyp != nil and instantiateDestructor(c, varTyp):
var tryStmt = newNodeI(nkTryStmt, info)
if j < totalVars - 1:
@ -910,8 +1049,8 @@ proc insertDestructors(c: PContext, varSection: PNode):
tryStmt.addSon(
newNode(nkFinally, info, @[
semStmt(c, newNode(nkCall, info, @[
semSym(c, varId, varTyp.destructor, {}),
semSym(c, varId, varId.sym, {})]))]))
useSym(varTyp.destructor),
useSym(varId.sym)]))]))
result.outer = newNodeI(nkStmtList, info)
varSection.sons.setLen(j+1)

View file

@ -306,7 +306,9 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
covered: var biggestInt) =
for i in countup(0, sonsLen(branch) - 2):
var b = branch.sons[i]
if isRange(b):
if b.kind == nkRange:
branch.sons[i] = b
elif isRange(b):
branch.sons[i] = semCaseBranchRange(c, t, b, covered)
else:
var r = semConstExpr(c, b)
@ -825,9 +827,15 @@ proc processMagicType(c: PContext, m: PSym) =
of mInt16: setMagicType(m, tyInt16, 2)
of mInt32: setMagicType(m, tyInt32, 4)
of mInt64: setMagicType(m, tyInt64, 8)
of mUInt: setMagicType(m, tyUInt, intSize)
of mUInt8: setMagicType(m, tyUInt8, 1)
of mUInt16: setMagicType(m, tyUInt16, 2)
of mUInt32: setMagicType(m, tyUInt32, 4)
of mUInt64: setMagicType(m, tyUInt64, 8)
of mFloat: setMagicType(m, tyFloat, floatSize)
of mFloat32: setMagicType(m, tyFloat32, 4)
of mFloat64: setMagicType(m, tyFloat64, 8)
of mFloat128: setMagicType(m, tyFloat128, 16)
of mBool: setMagicType(m, tyBool, 1)
of mChar: setMagicType(m, tyChar, 1)
of mString:

View file

@ -163,6 +163,9 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
var k = skipTypes(a, {tyRange}).kind
if k == f.kind: result = isSubtype
elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv
elif f.kind == tyUInt and k in {tyUInt..tyUInt32}: result = isIntConv
elif f.kind in {tyUInt..tyUInt64} and k == tyInt and tfUniIntLit in a.flags:
result = isIntConv
elif k >= min and k <= max: result = isConvertible
else: result = isNone
@ -306,6 +309,11 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
of tyInt16: result = handleRange(f, a, tyInt8, tyInt16)
of tyInt32: result = handleRange(f, a, tyInt, tyInt32)
of tyInt64: result = handleRange(f, a, tyInt, tyInt64)
of tyUInt: result = handleRange(f, a, tyUInt8, tyUInt32)
of tyUInt8: result = handleRange(f, a, tyUInt8, tyUInt8)
of tyUInt16: result = handleRange(f, a, tyUInt8, tyUInt16)
of tyUInt32: result = handleRange(f, a, tyUInt, tyUInt32)
of tyUInt64: result = handleRange(f, a, tyUInt, tyUInt64)
of tyFloat: result = handleFloatRange(f, a)
of tyFloat32: result = handleFloatRange(f, a)
of tyFloat64: result = handleFloatRange(f, a)

View file

@ -141,7 +141,7 @@ proc skipTypes(t: PType, kinds: TTypeKinds): PType =
proc isOrdinalType(t: PType): bool =
assert(t != nil)
result = (t.Kind in {tyChar, tyInt..tyInt64, tyBool, tyEnum}) or
result = (t.Kind in {tyChar, tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyEnum}) or
(t.Kind in {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst}) and
isOrdinalType(t.sons[0])
@ -386,10 +386,11 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
"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 ",
"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]", "proxy[$1]", "TypeClass" ]
var t = typ
result = ""
@ -494,6 +495,7 @@ proc firstOrd(t: PType): biggestInt =
of tyInt16: result = - 32768
of tyInt32: result = - 2147483646 - 2
of tyInt64: result = 0x8000000000000000'i64
of tyUInt..tyUInt64: result = 0
of tyEnum:
# if basetype <> nil then return firstOrd of basetype
if (sonsLen(t) > 0) and (t.sons[0] != nil):
@ -524,6 +526,13 @@ proc lastOrd(t: PType): biggestInt =
of tyInt16: result = 0x00007FFF
of tyInt32: result = 0x7FFFFFFF
of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64
of tyUInt:
if platform.intSize == 4: result = 0xFFFFFFFF
else: result = 0x7FFFFFFFFFFFFFFF'i64
of tyUInt8: result = 0x7F # XXX: Fix these
of tyUInt16: result = 0x7FFF
of tyUInt32: result = 0x7FFFFFFF
of tyUInt64: result = 0x7FFFFFFFFFFFFFFF'i64
of tyEnum:
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
result = t.n.sons[sonsLen(t.n) - 1].sym.position
@ -980,6 +989,9 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
of tyInt64, tyUInt64, tyFloat64:
result = 8
a = result
of tyFloat128:
result = 16
a = result
of tyFloat:
result = floatSize
a = result
@ -1062,10 +1074,3 @@ proc getSize(typ: PType): biggestInt =
result = computeSize(typ)
if result < 0: InternalError("getSize(" & $typ.kind & ')')
proc instantiateDestructor*(typ: PType): bool =
# return true if the type already had a user-defined
# destructor or if the compiler generated a default
# member-wise one
if typ.destructor != nil: return true
return false

View file

@ -39,7 +39,7 @@ type
wDestroy,
wImmediate, wImportCpp, wImportObjC,
wImmediate, wDestructor, wImportCpp, wImportObjC,
wImportCompilerProc,
wImportc, wExportc, wIncompleteStruct,
wAlign, wNodecl, wPure, wSideeffect, wHeader,
@ -117,7 +117,7 @@ const
"destroy",
"immediate", "importcpp", "importobjc",
"immediate", "destructor", "importcpp", "importobjc",
"importcompilerproc", "importc", "exportc", "incompletestruct",
"align", "nodecl", "pure", "sideeffect",
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",