Merge pull request #2483 from def-/ropes

Get rid of deprecation warnings
This commit is contained in:
Andreas Rumpf 2015-04-08 09:48:55 +02:00
commit 218d5567ed
22 changed files with 1449 additions and 1482 deletions

View file

@ -685,8 +685,8 @@ type
s*: TStorageLoc s*: TStorageLoc
flags*: TLocFlags # location's flags flags*: TLocFlags # location's flags
t*: PType # type of location t*: PType # type of location
r*: PRope # rope value of location (code generators) r*: Rope # rope value of location (code generators)
heapRoot*: PRope # keeps track of the enclosing heap object that heapRoot*: Rope # keeps track of the enclosing heap object that
# owns this location (required by GC algorithms # owns this location (required by GC algorithms
# employing heap snapshots or sliding views) # employing heap snapshots or sliding views)
@ -698,7 +698,7 @@ type
kind*: TLibKind kind*: TLibKind
generated*: bool # needed for the backends: generated*: bool # needed for the backends:
isOverriden*: bool isOverriden*: bool
name*: PRope name*: Rope
path*: PNode # can be a string literal! path*: PNode # can be a string literal!
TInstantiation* = object TInstantiation* = object

View file

@ -15,13 +15,13 @@ import
ast, hashes, intsets, strutils, options, msgs, ropes, idents, rodutils ast, hashes, intsets, strutils, options, msgs, ropes, idents, rodutils
proc hashNode*(p: RootRef): THash proc hashNode*(p: RootRef): THash
proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope
# Convert a tree into its YAML representation; this is used by the # Convert a tree into its YAML representation; this is used by the
# YAML code generator and it is invaluable for debugging purposes. # YAML code generator and it is invaluable for debugging purposes.
# If maxRecDepht <> -1 then it won't print the whole graph. # If maxRecDepht <> -1 then it won't print the whole graph.
proc typeToYaml*(n: PType, indent: int = 0, maxRecDepth: int = - 1): PRope proc typeToYaml*(n: PType, indent: int = 0, maxRecDepth: int = - 1): Rope
proc symToYaml*(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope proc symToYaml*(n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope
proc lineInfoToStr*(info: TLineInfo): PRope proc lineInfoToStr*(info: TLineInfo): Rope
# ----------------------- node sets: --------------------------------------- # ----------------------- node sets: ---------------------------------------
proc objectSetContains*(t: TObjectSet, obj: RootRef): bool proc objectSetContains*(t: TObjectSet, obj: RootRef): bool
@ -203,9 +203,9 @@ proc mustRehash(length, counter: int): bool =
assert(length > counter) assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4) result = (length * 2 < counter * 3) or (length - counter < 4)
proc rspaces(x: int): PRope = proc rspaces(x: int): Rope =
# returns x spaces # returns x spaces
result = toRope(spaces(x)) result = rope(spaces(x))
proc toYamlChar(c: char): string = proc toYamlChar(c: char): string =
case c case c
@ -213,7 +213,7 @@ proc toYamlChar(c: char): string =
of '\'', '\"', '\\': result = '\\' & c of '\'', '\"', '\\': result = '\\' & c
else: result = $c else: result = $c
proc makeYamlString*(s: string): PRope = proc makeYamlString*(s: string): Rope =
# We have to split long strings into many ropes. Otherwise # We have to split long strings into many ropes. Otherwise
# this could trigger InternalError(111). See the ropes module for # this could trigger InternalError(111). See the ropes module for
# further information. # further information.
@ -224,227 +224,227 @@ proc makeYamlString*(s: string): PRope =
if (i + 1) mod MaxLineLength == 0: if (i + 1) mod MaxLineLength == 0:
add(res, '\"') add(res, '\"')
add(res, "\n") add(res, "\n")
app(result, toRope(res)) add(result, rope(res))
res = "\"" # reset res = "\"" # reset
add(res, toYamlChar(s[i])) add(res, toYamlChar(s[i]))
add(res, '\"') add(res, '\"')
app(result, toRope(res)) add(result, rope(res))
proc flagsToStr[T](flags: set[T]): PRope = proc flagsToStr[T](flags: set[T]): Rope =
if flags == {}: if flags == {}:
result = toRope("[]") result = rope("[]")
else: else:
result = nil result = nil
for x in items(flags): for x in items(flags):
if result != nil: app(result, ", ") if result != nil: add(result, ", ")
app(result, makeYamlString($x)) add(result, makeYamlString($x))
result = con("[", con(result, "]")) result = "[" & result & "]"
proc lineInfoToStr(info: TLineInfo): PRope = proc lineInfoToStr(info: TLineInfo): Rope =
result = ropef("[$1, $2, $3]", [makeYamlString(toFilename(info)), result = "[$1, $2, $3]" % [makeYamlString(toFilename(info)),
toRope(toLinenumber(info)), rope(toLinenumber(info)),
toRope(toColumn(info))]) rope(toColumn(info))]
proc treeToYamlAux(n: PNode, marker: var IntSet, proc treeToYamlAux(n: PNode, marker: var IntSet,
indent, maxRecDepth: int): PRope indent, maxRecDepth: int): Rope
proc symToYamlAux(n: PSym, marker: var IntSet, proc symToYamlAux(n: PSym, marker: var IntSet,
indent, maxRecDepth: int): PRope indent, maxRecDepth: int): Rope
proc typeToYamlAux(n: PType, marker: var IntSet, proc typeToYamlAux(n: PType, marker: var IntSet,
indent, maxRecDepth: int): PRope indent, maxRecDepth: int): Rope
proc strTableToYaml(n: TStrTable, marker: var IntSet, indent: int, proc strTableToYaml(n: TStrTable, marker: var IntSet, indent: int,
maxRecDepth: int): PRope = maxRecDepth: int): Rope =
var istr = rspaces(indent + 2) var istr = rspaces(indent + 2)
result = toRope("[") result = rope("[")
var mycount = 0 var mycount = 0
for i in countup(0, high(n.data)): for i in countup(0, high(n.data)):
if n.data[i] != nil: if n.data[i] != nil:
if mycount > 0: app(result, ",") if mycount > 0: add(result, ",")
appf(result, "$N$1$2", addf(result, "$N$1$2",
[istr, symToYamlAux(n.data[i], marker, indent + 2, maxRecDepth - 1)]) [istr, symToYamlAux(n.data[i], marker, indent + 2, maxRecDepth - 1)])
inc(mycount) inc(mycount)
if mycount > 0: appf(result, "$N$1", [rspaces(indent)]) if mycount > 0: addf(result, "$N$1", [rspaces(indent)])
app(result, "]") add(result, "]")
assert(mycount == n.counter) assert(mycount == n.counter)
proc ropeConstr(indent: int, c: openArray[PRope]): PRope = proc ropeConstr(indent: int, c: openArray[Rope]): Rope =
# array of (name, value) pairs # array of (name, value) pairs
var istr = rspaces(indent + 2) var istr = rspaces(indent + 2)
result = toRope("{") result = rope("{")
var i = 0 var i = 0
while i <= high(c): while i <= high(c):
if i > 0: app(result, ",") if i > 0: add(result, ",")
appf(result, "$N$1\"$2\": $3", [istr, c[i], c[i + 1]]) addf(result, "$N$1\"$2\": $3", [istr, c[i], c[i + 1]])
inc(i, 2) inc(i, 2)
appf(result, "$N$1}", [rspaces(indent)]) addf(result, "$N$1}", [rspaces(indent)])
proc symToYamlAux(n: PSym, marker: var IntSet, indent: int, proc symToYamlAux(n: PSym, marker: var IntSet, indent: int,
maxRecDepth: int): PRope = maxRecDepth: int): Rope =
if n == nil: if n == nil:
result = toRope("null") result = rope("null")
elif containsOrIncl(marker, n.id): elif containsOrIncl(marker, n.id):
result = ropef("\"$1 @$2\"", [toRope(n.name.s), toRope( result = "\"$1 @$2\"" % [rope(n.name.s), rope(
strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))]) strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))]
else: else:
var ast = treeToYamlAux(n.ast, marker, indent + 2, maxRecDepth - 1) var ast = treeToYamlAux(n.ast, marker, indent + 2, maxRecDepth - 1)
result = ropeConstr(indent, [toRope("kind"), result = ropeConstr(indent, [rope("kind"),
makeYamlString($n.kind), makeYamlString($n.kind),
toRope("name"), makeYamlString(n.name.s), rope("name"), makeYamlString(n.name.s),
toRope("typ"), typeToYamlAux(n.typ, marker, rope("typ"), typeToYamlAux(n.typ, marker,
indent + 2, maxRecDepth - 1), indent + 2, maxRecDepth - 1),
toRope("info"), lineInfoToStr(n.info), rope("info"), lineInfoToStr(n.info),
toRope("flags"), flagsToStr(n.flags), rope("flags"), flagsToStr(n.flags),
toRope("magic"), makeYamlString($n.magic), rope("magic"), makeYamlString($n.magic),
toRope("ast"), ast, toRope("options"), rope("ast"), ast, rope("options"),
flagsToStr(n.options), toRope("position"), flagsToStr(n.options), rope("position"),
toRope(n.position)]) rope(n.position)])
proc typeToYamlAux(n: PType, marker: var IntSet, indent: int, proc typeToYamlAux(n: PType, marker: var IntSet, indent: int,
maxRecDepth: int): PRope = maxRecDepth: int): Rope =
if n == nil: if n == nil:
result = toRope("null") result = rope("null")
elif containsOrIncl(marker, n.id): elif containsOrIncl(marker, n.id):
result = ropef("\"$1 @$2\"", [toRope($n.kind), toRope( result = "\"$1 @$2\"" % [rope($n.kind), rope(
strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))]) strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))]
else: else:
if sonsLen(n) > 0: if sonsLen(n) > 0:
result = toRope("[") result = rope("[")
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
if i > 0: app(result, ",") if i > 0: add(result, ",")
appf(result, "$N$1$2", [rspaces(indent + 4), typeToYamlAux(n.sons[i], addf(result, "$N$1$2", [rspaces(indent + 4), typeToYamlAux(n.sons[i],
marker, indent + 4, maxRecDepth - 1)]) marker, indent + 4, maxRecDepth - 1)])
appf(result, "$N$1]", [rspaces(indent + 2)]) addf(result, "$N$1]", [rspaces(indent + 2)])
else: else:
result = toRope("null") result = rope("null")
result = ropeConstr(indent, [toRope("kind"), result = ropeConstr(indent, [rope("kind"),
makeYamlString($n.kind), makeYamlString($n.kind),
toRope("sym"), symToYamlAux(n.sym, marker, rope("sym"), symToYamlAux(n.sym, marker,
indent + 2, maxRecDepth - 1), toRope("n"), treeToYamlAux(n.n, marker, indent + 2, maxRecDepth - 1), rope("n"), treeToYamlAux(n.n, marker,
indent + 2, maxRecDepth - 1), toRope("flags"), flagsToStr(n.flags), indent + 2, maxRecDepth - 1), rope("flags"), flagsToStr(n.flags),
toRope("callconv"), rope("callconv"),
makeYamlString(CallingConvToStr[n.callConv]), makeYamlString(CallingConvToStr[n.callConv]),
toRope("size"), toRope(n.size), rope("size"), rope(n.size),
toRope("align"), toRope(n.align), rope("align"), rope(n.align),
toRope("sons"), result]) rope("sons"), result])
proc treeToYamlAux(n: PNode, marker: var IntSet, indent: int, proc treeToYamlAux(n: PNode, marker: var IntSet, indent: int,
maxRecDepth: int): PRope = maxRecDepth: int): Rope =
if n == nil: if n == nil:
result = toRope("null") result = rope("null")
else: else:
var istr = rspaces(indent + 2) var istr = rspaces(indent + 2)
result = ropef("{$N$1\"kind\": $2", [istr, makeYamlString($n.kind)]) result = "{$N$1\"kind\": $2" % [istr, makeYamlString($n.kind)]
if maxRecDepth != 0: if maxRecDepth != 0:
appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)]) addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
case n.kind case n.kind
of nkCharLit..nkInt64Lit: of nkCharLit..nkInt64Lit:
appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)]) addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
appf(result, ",$N$1\"floatVal\": $2", addf(result, ",$N$1\"floatVal\": $2",
[istr, toRope(n.floatVal.toStrMaxPrecision)]) [istr, rope(n.floatVal.toStrMaxPrecision)])
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if n.strVal.isNil: if n.strVal.isNil:
appf(result, ",$N$1\"strVal\": null", [istr]) addf(result, ",$N$1\"strVal\": null", [istr])
else: else:
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)]) addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym: of nkSym:
appf(result, ",$N$1\"sym\": $2", addf(result, ",$N$1\"sym\": $2",
[istr, symToYamlAux(n.sym, marker, indent + 2, maxRecDepth)]) [istr, symToYamlAux(n.sym, marker, indent + 2, maxRecDepth)])
of nkIdent: of nkIdent:
if n.ident != nil: if n.ident != nil:
appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) addf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
else: else:
appf(result, ",$N$1\"ident\": null", [istr]) addf(result, ",$N$1\"ident\": null", [istr])
else: else:
if sonsLen(n) > 0: if sonsLen(n) > 0:
appf(result, ",$N$1\"sons\": [", [istr]) addf(result, ",$N$1\"sons\": [", [istr])
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
if i > 0: app(result, ",") if i > 0: add(result, ",")
appf(result, "$N$1$2", [rspaces(indent + 4), treeToYamlAux(n.sons[i], addf(result, "$N$1$2", [rspaces(indent + 4), treeToYamlAux(n.sons[i],
marker, indent + 4, maxRecDepth - 1)]) marker, indent + 4, maxRecDepth - 1)])
appf(result, "$N$1]", [istr]) addf(result, "$N$1]", [istr])
appf(result, ",$N$1\"typ\": $2", addf(result, ",$N$1\"typ\": $2",
[istr, typeToYamlAux(n.typ, marker, indent + 2, maxRecDepth)]) [istr, typeToYamlAux(n.typ, marker, indent + 2, maxRecDepth)])
appf(result, "$N$1}", [rspaces(indent)]) addf(result, "$N$1}", [rspaces(indent)])
proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope = proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope =
var marker = initIntSet() var marker = initIntSet()
result = treeToYamlAux(n, marker, indent, maxRecDepth) result = treeToYamlAux(n, marker, indent, maxRecDepth)
proc typeToYaml(n: PType, indent: int = 0, maxRecDepth: int = - 1): PRope = proc typeToYaml(n: PType, indent: int = 0, maxRecDepth: int = - 1): Rope =
var marker = initIntSet() var marker = initIntSet()
result = typeToYamlAux(n, marker, indent, maxRecDepth) result = typeToYamlAux(n, marker, indent, maxRecDepth)
proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope = proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope =
var marker = initIntSet() var marker = initIntSet()
result = symToYamlAux(n, marker, indent, maxRecDepth) result = symToYamlAux(n, marker, indent, maxRecDepth)
proc debugTree*(n: PNode, indent: int, maxRecDepth: int; renderType=false): PRope proc debugTree*(n: PNode, indent: int, maxRecDepth: int; renderType=false): Rope
proc debugType(n: PType, maxRecDepth=100): PRope = proc debugType(n: PType, maxRecDepth=100): Rope =
if n == nil: if n == nil:
result = toRope("null") result = rope("null")
else: else:
result = toRope($n.kind) result = rope($n.kind)
if n.sym != nil: if n.sym != nil:
app(result, " ") add(result, " ")
app(result, n.sym.name.s) add(result, n.sym.name.s)
if n.kind in IntegralTypes and n.n != nil: if n.kind in IntegralTypes and n.n != nil:
app(result, ", node: ") add(result, ", node: ")
app(result, debugTree(n.n, 2, maxRecDepth-1, renderType=true)) add(result, debugTree(n.n, 2, maxRecDepth-1, renderType=true))
if (n.kind != tyString) and (sonsLen(n) > 0) and maxRecDepth != 0: if (n.kind != tyString) and (sonsLen(n) > 0) and maxRecDepth != 0:
app(result, "(") add(result, "(")
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
if i > 0: app(result, ", ") if i > 0: add(result, ", ")
if n.sons[i] == nil: if n.sons[i] == nil:
app(result, "null") add(result, "null")
else: else:
app(result, debugType(n.sons[i], maxRecDepth-1)) add(result, debugType(n.sons[i], maxRecDepth-1))
if n.kind == tyObject and n.n != nil: if n.kind == tyObject and n.n != nil:
app(result, ", node: ") add(result, ", node: ")
app(result, debugTree(n.n, 2, maxRecDepth-1, renderType=true)) add(result, debugTree(n.n, 2, maxRecDepth-1, renderType=true))
app(result, ")") add(result, ")")
proc debugTree(n: PNode, indent: int, maxRecDepth: int; proc debugTree(n: PNode, indent: int, maxRecDepth: int;
renderType=false): PRope = renderType=false): Rope =
if n == nil: if n == nil:
result = toRope("null") result = rope("null")
else: else:
var istr = rspaces(indent + 2) var istr = rspaces(indent + 2)
result = ropef("{$N$1\"kind\": $2", result = "{$N$1\"kind\": $2" %
[istr, makeYamlString($n.kind)]) [istr, makeYamlString($n.kind)]
if maxRecDepth != 0: if maxRecDepth != 0:
case n.kind case n.kind
of nkCharLit..nkUInt64Lit: of nkCharLit..nkUInt64Lit:
appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)]) addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
of nkFloatLit, nkFloat32Lit, nkFloat64Lit: of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
appf(result, ",$N$1\"floatVal\": $2", addf(result, ",$N$1\"floatVal\": $2",
[istr, toRope(n.floatVal.toStrMaxPrecision)]) [istr, rope(n.floatVal.toStrMaxPrecision)])
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if n.strVal.isNil: if n.strVal.isNil:
appf(result, ",$N$1\"strVal\": null", [istr]) addf(result, ",$N$1\"strVal\": null", [istr])
else: else:
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)]) addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym: of nkSym:
appf(result, ",$N$1\"sym\": $2_$3", addf(result, ",$N$1\"sym\": $2_$3",
[istr, toRope(n.sym.name.s), toRope(n.sym.id)]) [istr, rope(n.sym.name.s), rope(n.sym.id)])
# [istr, symToYaml(n.sym, indent, maxRecDepth), # [istr, symToYaml(n.sym, indent, maxRecDepth),
# toRope(n.sym.id)]) # rope(n.sym.id)])
if renderType and n.sym.typ != nil: if renderType and n.sym.typ != nil:
appf(result, ",$N$1\"typ\": $2", [istr, debugType(n.sym.typ, 2)]) addf(result, ",$N$1\"typ\": $2", [istr, debugType(n.sym.typ, 2)])
of nkIdent: of nkIdent:
if n.ident != nil: if n.ident != nil:
appf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) addf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
else: else:
appf(result, ",$N$1\"ident\": null", [istr]) addf(result, ",$N$1\"ident\": null", [istr])
else: else:
if sonsLen(n) > 0: if sonsLen(n) > 0:
appf(result, ",$N$1\"sons\": [", [istr]) addf(result, ",$N$1\"sons\": [", [istr])
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
if i > 0: app(result, ",") if i > 0: add(result, ",")
appf(result, "$N$1$2", [rspaces(indent + 4), debugTree(n.sons[i], addf(result, "$N$1$2", [rspaces(indent + 4), debugTree(n.sons[i],
indent + 4, maxRecDepth - 1, renderType)]) indent + 4, maxRecDepth - 1, renderType)])
appf(result, "$N$1]", [istr]) addf(result, "$N$1]", [istr])
appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)]) addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
appf(result, "$N$1}", [rspaces(indent)]) addf(result, "$N$1}", [rspaces(indent)])
proc debug(n: PSym) = proc debug(n: PSym) =
if n == nil: if n == nil:

View file

@ -19,13 +19,13 @@ proc hasNoInit(call: PNode): bool {.inline.} =
result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags
proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
callee, params: PRope) = callee, params: Rope) =
var pl = con(callee, ~"(", params) var pl = callee & ~"(" & params
# getUniqueType() is too expensive here: # getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst) var typ = skipTypes(ri.sons[0].typ, abstractInst)
if typ.sons[0] != nil: if typ.sons[0] != nil:
if isInvalidReturnType(typ.sons[0]): if isInvalidReturnType(typ.sons[0]):
if params != nil: pl.app(~", ") if params != nil: pl.add(~", ")
# beware of 'result = p(result)'. We may need to allocate a temporary: # beware of 'result = p(result)'. We may need to allocate a temporary:
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri): if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
# Great, we can use 'd': # Great, we can use 'd':
@ -33,18 +33,18 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
elif d.k notin {locExpr, locTemp} and not hasNoInit(ri): elif d.k notin {locExpr, locTemp} and not hasNoInit(ri):
# reset before pass as 'result' var: # reset before pass as 'result' var:
resetLoc(p, d) resetLoc(p, d)
app(pl, addrLoc(d)) add(pl, addrLoc(d))
app(pl, ~");$n") add(pl, ~");$n")
line(p, cpsStmts, pl) line(p, cpsStmts, pl)
else: else:
var tmp: TLoc var tmp: TLoc
getTemp(p, typ.sons[0], tmp, needsInit=true) getTemp(p, typ.sons[0], tmp, needsInit=true)
app(pl, addrLoc(tmp)) add(pl, addrLoc(tmp))
app(pl, ~");$n") add(pl, ~");$n")
line(p, cpsStmts, pl) line(p, cpsStmts, pl)
genAssignment(p, d, tmp, {}) # no need for deep copying genAssignment(p, d, tmp, {}) # no need for deep copying
else: else:
app(pl, ~")") add(pl, ~")")
if p.module.compileToCpp and lfSingleUse in d.flags: if p.module.compileToCpp and lfSingleUse in d.flags:
# do not generate spurious temporaries for C++! For C we're better off # do not generate spurious temporaries for C++! For C we're better off
# with them to prevent undefined behaviour and because the codegen # with them to prevent undefined behaviour and because the codegen
@ -60,7 +60,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
list.r = pl list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying genAssignment(p, d, list, {}) # no need for deep copying
else: else:
app(pl, ~");$n") add(pl, ~");$n")
line(p, cpsStmts, pl) line(p, cpsStmts, pl)
proc isInCurrentFrame(p: BProc, n: PNode): bool = proc isInCurrentFrame(p: BProc, n: PNode): bool =
@ -83,7 +83,7 @@ proc isInCurrentFrame(p: BProc, n: PNode): bool =
result = isInCurrentFrame(p, n.sons[0]) result = isInCurrentFrame(p, n.sons[0])
else: discard else: discard
proc openArrayLoc(p: BProc, n: PNode): PRope = proc openArrayLoc(p: BProc, n: PNode): Rope =
var a: TLoc var a: TLoc
let q = skipConv(n) let q = skipConv(n)
@ -104,28 +104,28 @@ proc openArrayLoc(p: BProc, n: PNode): PRope =
else: else:
"$1->data+($2), ($3)-($2)+1" "$1->data+($2), ($3)-($2)+1"
else: (internalError("openArrayLoc: " & typeToString(a.t)); "") else: (internalError("openArrayLoc: " & typeToString(a.t)); "")
result = ropef(fmt, [rdLoc(a), rdLoc(b), rdLoc(c)]) result = fmt % [rdLoc(a), rdLoc(b), rdLoc(c)]
else: else:
initLocExpr(p, n, a) initLocExpr(p, n, a)
case skipTypes(a.t, abstractVar).kind case skipTypes(a.t, abstractVar).kind
of tyOpenArray, tyVarargs: of tyOpenArray, tyVarargs:
result = ropef("$1, $1Len0", [rdLoc(a)]) result = "$1, $1Len0" % [rdLoc(a)]
of tyString, tySequence: of tyString, tySequence:
if skipTypes(n.typ, abstractInst).kind == tyVar and if skipTypes(n.typ, abstractInst).kind == tyVar and
not compileToCpp(p.module): not compileToCpp(p.module):
result = ropef("(*$1)->data, (*$1)->$2", [a.rdLoc, lenField(p)]) result = "(*$1)->data, (*$1)->$2" % [a.rdLoc, lenField(p)]
else: else:
result = ropef("$1->data, $1->$2", [a.rdLoc, lenField(p)]) result = "$1->data, $1->$2" % [a.rdLoc, lenField(p)]
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
result = ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]) result = "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))]
else: internalError("openArrayLoc: " & typeToString(a.t)) else: internalError("openArrayLoc: " & typeToString(a.t))
proc genArgStringToCString(p: BProc, n: PNode): PRope {.inline.} = proc genArgStringToCString(p: BProc, n: PNode): Rope {.inline.} =
var a: TLoc var a: TLoc
initLocExpr(p, n.sons[0], a) initLocExpr(p, n.sons[0], a)
result = ropef("$1->data", [a.rdLoc]) result = "$1->data" % [a.rdLoc]
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): PRope = proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
var a: TLoc var a: TLoc
if n.kind == nkStringToCString: if n.kind == nkStringToCString:
result = genArgStringToCString(p, n) result = genArgStringToCString(p, n)
@ -151,7 +151,7 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): PRope =
initLocExprSingleUse(p, n, a) initLocExprSingleUse(p, n, a)
result = rdLoc(a) result = rdLoc(a)
proc genArgNoParam(p: BProc, n: PNode): PRope = proc genArgNoParam(p: BProc, n: PNode): Rope =
var a: TLoc var a: TLoc
if n.kind == nkStringToCString: if n.kind == nkStringToCString:
result = genArgStringToCString(p, n) result = genArgStringToCString(p, n)
@ -163,7 +163,7 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op: TLoc var op: TLoc
# this is a hotspot in the compiler # this is a hotspot in the compiler
initLocExpr(p, ri.sons[0], op) initLocExpr(p, ri.sons[0], op)
var params: PRope var params: Rope
# getUniqueType() is too expensive here: # getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst) var typ = skipTypes(ri.sons[0].typ, abstractInst)
assert(typ.kind == tyProc) assert(typ.kind == tyProc)
@ -171,27 +171,27 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var length = sonsLen(ri) var length = sonsLen(ri)
for i in countup(1, length - 1): for i in countup(1, length - 1):
if ri.sons[i].typ.isCompileTimeOnly: continue if ri.sons[i].typ.isCompileTimeOnly: continue
if params != nil: app(params, ~", ") if params != nil: add(params, ~", ")
if i < sonsLen(typ): if i < sonsLen(typ):
assert(typ.n.sons[i].kind == nkSym) assert(typ.n.sons[i].kind == nkSym)
app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri)) add(params, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri))
else: else:
app(params, genArgNoParam(p, ri.sons[i])) add(params, genArgNoParam(p, ri.sons[i]))
fixupCall(p, le, ri, d, op.r, params) fixupCall(p, le, ri, d, op.r, params)
proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
proc getRawProcType(p: BProc, t: PType): PRope = proc getRawProcType(p: BProc, t: PType): Rope =
result = getClosureType(p.module, t, clHalf) result = getClosureType(p.module, t, clHalf)
proc addComma(r: PRope): PRope = proc addComma(r: Rope): Rope =
result = if r == nil: r else: con(r, ~", ") result = if r == nil: r else: r & ~", "
const PatProc = "$1.ClEnv? $1.ClPrc($3$1.ClEnv):(($4)($1.ClPrc))($2)" const PatProc = "$1.ClEnv? $1.ClPrc($3$1.ClEnv):(($4)($1.ClPrc))($2)"
const PatIter = "$1.ClPrc($3$1.ClEnv)" # we know the env exists const PatIter = "$1.ClPrc($3$1.ClEnv)" # we know the env exists
var op: TLoc var op: TLoc
initLocExpr(p, ri.sons[0], op) initLocExpr(p, ri.sons[0], op)
var pl: PRope var pl: Rope
var typ = skipTypes(ri.sons[0].typ, abstractInst) var typ = skipTypes(ri.sons[0].typ, abstractInst)
assert(typ.kind == tyProc) assert(typ.kind == tyProc)
@ -201,19 +201,19 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
if ri.sons[i].typ.isCompileTimeOnly: continue if ri.sons[i].typ.isCompileTimeOnly: continue
if i < sonsLen(typ): if i < sonsLen(typ):
assert(typ.n.sons[i].kind == nkSym) assert(typ.n.sons[i].kind == nkSym)
app(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri)) add(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri))
else: else:
app(pl, genArgNoParam(p, ri.sons[i])) add(pl, genArgNoParam(p, ri.sons[i]))
if i < length - 1: app(pl, ~", ") if i < length - 1: add(pl, ~", ")
template genCallPattern {.dirty.} = template genCallPattern {.dirty.} =
lineF(p, cpsStmts, callPattern & ";$n", op.r, pl, pl.addComma, rawProc) lineF(p, cpsStmts, callPattern & ";$n", [op.r, pl, pl.addComma, rawProc])
let rawProc = getRawProcType(p, typ) let rawProc = getRawProcType(p, typ)
let callPattern = if tfIterator in typ.flags: PatIter else: PatProc let callPattern = if tfIterator in typ.flags: PatIter else: PatProc
if typ.sons[0] != nil: if typ.sons[0] != nil:
if isInvalidReturnType(typ.sons[0]): if isInvalidReturnType(typ.sons[0]):
if sonsLen(ri) > 1: app(pl, ~", ") if sonsLen(ri) > 1: add(pl, ~", ")
# beware of 'result = p(result)'. We may need to allocate a temporary: # beware of 'result = p(result)'. We may need to allocate a temporary:
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri): if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
# Great, we can use 'd': # Great, we can use 'd':
@ -222,12 +222,12 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
elif d.k notin {locExpr, locTemp} and not hasNoInit(ri): elif d.k notin {locExpr, locTemp} and not hasNoInit(ri):
# reset before pass as 'result' var: # reset before pass as 'result' var:
resetLoc(p, d) resetLoc(p, d)
app(pl, addrLoc(d)) add(pl, addrLoc(d))
genCallPattern() genCallPattern()
else: else:
var tmp: TLoc var tmp: TLoc
getTemp(p, typ.sons[0], tmp, needsInit=true) getTemp(p, typ.sons[0], tmp, needsInit=true)
app(pl, addrLoc(tmp)) add(pl, addrLoc(tmp))
genCallPattern() genCallPattern()
genAssignment(p, d, tmp, {}) # no need for deep copying genAssignment(p, d, tmp, {}) # no need for deep copying
else: else:
@ -235,12 +235,12 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
assert(d.t != nil) # generate an assignment to d: assert(d.t != nil) # generate an assignment to d:
var list: TLoc var list: TLoc
initLoc(list, locCall, d.t, OnUnknown) initLoc(list, locCall, d.t, OnUnknown)
list.r = ropef(callPattern, op.r, pl, pl.addComma, rawProc) list.r = callPattern % [op.r, pl, pl.addComma, rawProc]
genAssignment(p, d, list, {}) # no need for deep copying genAssignment(p, d, list, {}) # no need for deep copying
else: else:
genCallPattern() genCallPattern()
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): PRope = proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
if ri.sons[i].typ.isCompileTimeOnly: if ri.sons[i].typ.isCompileTimeOnly:
result = nil result = nil
elif i < sonsLen(typ): elif i < sonsLen(typ):
@ -309,7 +309,7 @@ proc skipAddrDeref(node: PNode): PNode =
else: else:
result = node result = node
proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): PRope = proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
# for better or worse c2nim translates the 'this' argument to a 'var T'. # for better or worse c2nim translates the 'this' argument to a 'var T'.
# However manual wrappers may also use 'ptr T'. In any case we support both # However manual wrappers may also use 'ptr T'. In any case we support both
# for convenience. # for convenience.
@ -324,64 +324,64 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): PRope =
let x = if ri.kind == nkHiddenAddr: ri[0] else: ri let x = if ri.kind == nkHiddenAddr: ri[0] else: ri
if x.typ.kind == tyPtr: if x.typ.kind == tyPtr:
result = genArgNoParam(p, x) result = genArgNoParam(p, x)
result.app("->") result.add("->")
elif x.kind in {nkHiddenDeref, nkDerefExpr} and x[0].typ.kind == tyPtr: elif x.kind in {nkHiddenDeref, nkDerefExpr} and x[0].typ.kind == tyPtr:
result = genArgNoParam(p, x[0]) result = genArgNoParam(p, x[0])
result.app("->") result.add("->")
else: else:
result = genArgNoParam(p, x) result = genArgNoParam(p, x)
result.app(".") result.add(".")
elif t.kind == tyPtr: elif t.kind == tyPtr:
if ri.kind in {nkAddr, nkHiddenAddr}: if ri.kind in {nkAddr, nkHiddenAddr}:
result = genArgNoParam(p, ri[0]) result = genArgNoParam(p, ri[0])
result.app(".") result.add(".")
else: else:
result = genArgNoParam(p, ri) result = genArgNoParam(p, ri)
result.app("->") result.add("->")
else: else:
ri = skipAddrDeref(ri) ri = skipAddrDeref(ri)
if ri.kind in {nkAddr, nkHiddenAddr}: ri = ri[0] if ri.kind in {nkAddr, nkHiddenAddr}: ri = ri[0]
result = genArgNoParam(p, ri) #, typ.n.sons[i].sym) result = genArgNoParam(p, ri) #, typ.n.sons[i].sym)
result.app(".") result.add(".")
proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): PRope = proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
var i = 0 var i = 0
var j = 1 var j = 1
while i < pat.len: while i < pat.len:
case pat[i] case pat[i]
of '@': of '@':
if j < ri.len: if j < ri.len:
result.app genOtherArg(p, ri, j, typ) result.add genOtherArg(p, ri, j, typ)
for k in j+1 .. < ri.len: for k in j+1 .. < ri.len:
result.app(~", ") result.add(~", ")
result.app genOtherArg(p, ri, k, typ) result.add genOtherArg(p, ri, k, typ)
inc i inc i
of '#': of '#':
if pat[i+1] in {'+', '@'}: if pat[i+1] in {'+', '@'}:
let ri = ri[j] let ri = ri[j]
if ri.kind in nkCallKinds: if ri.kind in nkCallKinds:
let typ = skipTypes(ri.sons[0].typ, abstractInst) let typ = skipTypes(ri.sons[0].typ, abstractInst)
if pat[i+1] == '+': result.app genArgNoParam(p, ri.sons[0]) if pat[i+1] == '+': result.add genArgNoParam(p, ri.sons[0])
result.app(~"(") result.add(~"(")
if 1 < ri.len: if 1 < ri.len:
result.app genOtherArg(p, ri, 1, typ) result.add genOtherArg(p, ri, 1, typ)
for k in j+1 .. < ri.len: for k in j+1 .. < ri.len:
result.app(~", ") result.add(~", ")
result.app genOtherArg(p, ri, k, typ) result.add genOtherArg(p, ri, k, typ)
result.app(~")") result.add(~")")
else: else:
localError(ri.info, "call expression expected for C++ pattern") localError(ri.info, "call expression expected for C++ pattern")
inc i inc i
elif pat[i+1] == '.': elif pat[i+1] == '.':
result.app genThisArg(p, ri, j, typ) result.add genThisArg(p, ri, j, typ)
inc i inc i
elif pat[i+1] == '[': elif pat[i+1] == '[':
var arg = ri.sons[j].skipAddrDeref var arg = ri.sons[j].skipAddrDeref
while arg.kind in {nkAddr, nkHiddenAddr, nkObjDownConv}: arg = arg[0] while arg.kind in {nkAddr, nkHiddenAddr, nkObjDownConv}: arg = arg[0]
result.app genArgNoParam(p, arg) result.add genArgNoParam(p, arg)
#result.app debugTree(arg, 0, 10) #result.add debugTree(arg, 0, 10)
else: else:
result.app genOtherArg(p, ri, j, typ) result.add genOtherArg(p, ri, j, typ)
inc j inc j
inc i inc i
of '\'': of '\'':
@ -394,8 +394,8 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): PRope =
for k in 1..i-stars: for k in 1..i-stars:
if t != nil and t.len > 0: if t != nil and t.len > 0:
t = if t.kind == tyGenericInst: t.sons[1] else: t.elemType t = if t.kind == tyGenericInst: t.sons[1] else: t.elemType
if t == nil: result.app(~"void") if t == nil: result.add(~"void")
else: result.app(getTypeDesc(p.module, t)) else: result.add(getTypeDesc(p.module, t))
inc i inc i
else: else:
let start = i let start = i
@ -403,7 +403,7 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): PRope =
if pat[i] notin {'@', '#', '\''}: inc(i) if pat[i] notin {'@', '#', '\''}: inc(i)
else: break else: break
if i - 1 >= start: if i - 1 >= start:
app(result, substr(pat, start, i - 1)) add(result, substr(pat, start, i - 1))
proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) = proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op, a: TLoc var op, a: TLoc
@ -436,19 +436,19 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
list.r = pl list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying genAssignment(p, d, list, {}) # no need for deep copying
else: else:
app(pl, ~";$n") add(pl, ~";$n")
line(p, cpsStmts, pl) line(p, cpsStmts, pl)
else: else:
var pl: PRope = nil var pl: Rope = nil
#var param = typ.n.sons[1].sym #var param = typ.n.sons[1].sym
if 1 < ri.len: if 1 < ri.len:
app(pl, genThisArg(p, ri, 1, typ)) add(pl, genThisArg(p, ri, 1, typ))
app(pl, op.r) add(pl, op.r)
var params: PRope var params: Rope
for i in countup(2, length - 1): for i in countup(2, length - 1):
if params != nil: params.app(~", ") if params != nil: params.add(~", ")
assert(sonsLen(typ) == sonsLen(typ.n)) assert(sonsLen(typ) == sonsLen(typ.n))
app(params, genOtherArg(p, ri, i, typ)) add(params, genOtherArg(p, ri, i, typ))
fixupCall(p, le, ri, d, pl, params) fixupCall(p, le, ri, d, pl, params)
proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
@ -468,49 +468,49 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
var start = 3 var start = 3
if ' ' in pat: if ' ' in pat:
start = 1 start = 1
app(pl, op.r) add(pl, op.r)
if length > 1: if length > 1:
app(pl, ~": ") add(pl, ~": ")
app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri)) add(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
start = 2 start = 2
else: else:
if length > 1: if length > 1:
app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri)) add(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
app(pl, ~" ") add(pl, ~" ")
app(pl, op.r) add(pl, op.r)
if length > 2: if length > 2:
app(pl, ~": ") add(pl, ~": ")
app(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri)) add(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri))
for i in countup(start, length-1): for i in countup(start, length-1):
assert(sonsLen(typ) == sonsLen(typ.n)) assert(sonsLen(typ) == sonsLen(typ.n))
if i >= sonsLen(typ): if i >= sonsLen(typ):
internalError(ri.info, "varargs for objective C method?") internalError(ri.info, "varargs for objective C method?")
assert(typ.n.sons[i].kind == nkSym) assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym var param = typ.n.sons[i].sym
app(pl, ~" ") add(pl, ~" ")
app(pl, param.name.s) add(pl, param.name.s)
app(pl, ~": ") add(pl, ~": ")
app(pl, genArg(p, ri.sons[i], param, ri)) add(pl, genArg(p, ri.sons[i], param, ri))
if typ.sons[0] != nil: if typ.sons[0] != nil:
if isInvalidReturnType(typ.sons[0]): if isInvalidReturnType(typ.sons[0]):
if sonsLen(ri) > 1: app(pl, ~" ") if sonsLen(ri) > 1: add(pl, ~" ")
# beware of 'result = p(result)'. We always allocate a temporary: # beware of 'result = p(result)'. We always allocate a temporary:
if d.k in {locTemp, locNone}: if d.k in {locTemp, locNone}:
# We already got a temp. Great, special case it: # We already got a temp. Great, special case it:
if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true) if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true)
app(pl, ~"Result: ") add(pl, ~"Result: ")
app(pl, addrLoc(d)) add(pl, addrLoc(d))
app(pl, ~"];$n") add(pl, ~"];$n")
line(p, cpsStmts, pl) line(p, cpsStmts, pl)
else: else:
var tmp: TLoc var tmp: TLoc
getTemp(p, typ.sons[0], tmp, needsInit=true) getTemp(p, typ.sons[0], tmp, needsInit=true)
app(pl, addrLoc(tmp)) add(pl, addrLoc(tmp))
app(pl, ~"];$n") add(pl, ~"];$n")
line(p, cpsStmts, pl) line(p, cpsStmts, pl)
genAssignment(p, d, tmp, {}) # no need for deep copying genAssignment(p, d, tmp, {}) # no need for deep copying
else: else:
app(pl, ~"]") add(pl, ~"]")
if d.k == locNone: getTemp(p, typ.sons[0], d) if d.k == locNone: getTemp(p, typ.sons[0], d)
assert(d.t != nil) # generate an assignment to d: assert(d.t != nil) # generate an assignment to d:
var list: TLoc var list: TLoc
@ -518,7 +518,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
list.r = pl list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying genAssignment(p, d, list, {}) # no need for deep copying
else: else:
app(pl, ~"];$n") add(pl, ~"];$n")
line(p, cpsStmts, pl) line(p, cpsStmts, pl)
proc genCall(p: BProc, e: PNode, d: var TLoc) = proc genCall(p: BProc, e: PNode, d: var TLoc) =

View file

@ -11,45 +11,45 @@
# -------------------------- constant expressions ------------------------ # -------------------------- constant expressions ------------------------
proc int64Literal(i: BiggestInt): PRope = proc int64Literal(i: BiggestInt): Rope =
if i > low(int64): if i > low(int64):
result = rfmt(nil, "IL64($1)", toRope(i)) result = rfmt(nil, "IL64($1)", rope(i))
else: else:
result = ~"(IL64(-9223372036854775807) - IL64(1))" result = ~"(IL64(-9223372036854775807) - IL64(1))"
proc uint64Literal(i: uint64): PRope = toRope($i & "ULL") proc uint64Literal(i: uint64): Rope = rope($i & "ULL")
proc intLiteral(i: BiggestInt): PRope = proc intLiteral(i: BiggestInt): Rope =
if i > low(int32) and i <= high(int32): if i > low(int32) and i <= high(int32):
result = toRope(i) result = rope(i)
elif i == low(int32): elif i == low(int32):
# Nim has the same bug for the same reasons :-) # Nim has the same bug for the same reasons :-)
result = ~"(-2147483647 -1)" result = ~"(-2147483647 -1)"
elif i > low(int64): elif i > low(int64):
result = rfmt(nil, "IL64($1)", toRope(i)) result = rfmt(nil, "IL64($1)", rope(i))
else: else:
result = ~"(IL64(-9223372036854775807) - IL64(1))" result = ~"(IL64(-9223372036854775807) - IL64(1))"
proc int32Literal(i: int): PRope = proc int32Literal(i: int): Rope =
if i == int(low(int32)): if i == int(low(int32)):
result = ~"(-2147483647 -1)" result = ~"(-2147483647 -1)"
else: else:
result = toRope(i) result = rope(i)
proc genHexLiteral(v: PNode): PRope = proc genHexLiteral(v: PNode): Rope =
# hex literals are unsigned in C # hex literals are unsigned in C
# so we don't generate hex literals any longer. # so we don't generate hex literals any longer.
if v.kind notin {nkIntLit..nkUInt64Lit}: if v.kind notin {nkIntLit..nkUInt64Lit}:
internalError(v.info, "genHexLiteral") internalError(v.info, "genHexLiteral")
result = intLiteral(v.intVal) result = intLiteral(v.intVal)
proc getStrLit(m: BModule, s: string): PRope = proc getStrLit(m: BModule, s: string): Rope =
discard cgsym(m, "TGenericSeq") discard cgsym(m, "TGenericSeq")
result = con("TMP", toRope(backendId())) result = "TMP" & rope(backendId())
appf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n", addf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
[result, makeCString(s), toRope(len(s))]) [result, makeCString(s), rope(len(s))])
proc genLiteral(p: BProc, n: PNode, ty: PType): PRope = proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
if ty == nil: internalError(n.info, "genLiteral: ty is nil") if ty == nil: internalError(n.info, "genLiteral: ty is nil")
case n.kind case n.kind
of nkCharLit..nkUInt64Lit: of nkCharLit..nkUInt64Lit:
@ -62,21 +62,21 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): PRope =
of tyInt64: result = int64Literal(n.intVal) of tyInt64: result = int64Literal(n.intVal)
of tyUInt64: result = uint64Literal(uint64(n.intVal)) of tyUInt64: result = uint64Literal(uint64(n.intVal))
else: else:
result = ropef("(($1) $2)", [getTypeDesc(p.module, result = "(($1) $2)" % [getTypeDesc(p.module,
skipTypes(ty, abstractVarRange)), intLiteral(n.intVal)]) skipTypes(ty, abstractVarRange)), intLiteral(n.intVal)]
of nkNilLit: of nkNilLit:
let t = skipTypes(ty, abstractVarRange) let t = skipTypes(ty, abstractVarRange)
if t.kind == tyProc and t.callConv == ccClosure: if t.kind == tyProc and t.callConv == ccClosure:
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId) var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
result = con("TMP", toRope(id)) result = "TMP" & rope(id)
if id == gBackendId: if id == gBackendId:
# not found in cache: # not found in cache:
inc(gBackendId) inc(gBackendId)
appf(p.module.s[cfsData], addf(p.module.s[cfsData],
"static NIM_CONST $1 $2 = {NIM_NIL,NIM_NIL};$n", "static NIM_CONST $1 $2 = {NIM_NIL,NIM_NIL};$n",
[getTypeDesc(p.module, t), result]) [getTypeDesc(p.module, t), result])
else: else:
result = toRope("NIM_NIL") result = rope("NIM_NIL")
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if n.strVal.isNil: if n.strVal.isNil:
result = ropecg(p.module, "((#NimStringDesc*) NIM_NIL)", []) result = ropecg(p.module, "((#NimStringDesc*) NIM_NIL)", [])
@ -87,16 +87,16 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): PRope =
result = ropecg(p.module, "((#NimStringDesc*) &$1)", result = ropecg(p.module, "((#NimStringDesc*) &$1)",
[getStrLit(p.module, n.strVal)]) [getStrLit(p.module, n.strVal)])
else: else:
result = ropecg(p.module, "((#NimStringDesc*) &TMP$1)", [toRope(id)]) result = ropecg(p.module, "((#NimStringDesc*) &TMP$1)", [rope(id)])
else: else:
result = makeCString(n.strVal) result = makeCString(n.strVal)
of nkFloatLit..nkFloat64Lit: of nkFloatLit..nkFloat64Lit:
result = toRope(n.floatVal.toStrMaxPrecision) result = rope(n.floatVal.toStrMaxPrecision)
else: else:
internalError(n.info, "genLiteral(" & $n.kind & ')') internalError(n.info, "genLiteral(" & $n.kind & ')')
result = nil result = nil
proc genLiteral(p: BProc, n: PNode): PRope = proc genLiteral(p: BProc, n: PNode): Rope =
result = genLiteral(p, n, n.typ) result = genLiteral(p, n, n.typ)
proc bitSetToWord(s: TBitSet, size: int): BiggestInt = proc bitSetToWord(s: TBitSet, size: int): BiggestInt =
@ -113,10 +113,10 @@ proc bitSetToWord(s: TBitSet, size: int): BiggestInt =
for j in countup(0, size - 1): for j in countup(0, size - 1):
if j < len(s): result = result or `shl`(Ze64(s[j]), (Size - 1 - j) * 8) if j < len(s): result = result or `shl`(Ze64(s[j]), (Size - 1 - j) * 8)
proc genRawSetData(cs: TBitSet, size: int): PRope = proc genRawSetData(cs: TBitSet, size: int): Rope =
var frmt: TFormatStr var frmt: FormatStr
if size > 8: if size > 8:
result = ropef("{$n") result = "{$n" % []
for i in countup(0, size - 1): for i in countup(0, size - 1):
if i < size - 1: if i < size - 1:
# not last iteration? # not last iteration?
@ -124,22 +124,22 @@ proc genRawSetData(cs: TBitSet, size: int): PRope =
else: frmt = "0x$1, " else: frmt = "0x$1, "
else: else:
frmt = "0x$1}$n" frmt = "0x$1}$n"
appf(result, frmt, [toRope(toHex(ze64(cs[i]), 2))]) addf(result, frmt, [rope(toHex(ze64(cs[i]), 2))])
else: else:
result = intLiteral(bitSetToWord(cs, size)) result = intLiteral(bitSetToWord(cs, size))
# result := toRope('0x' + ToHex(bitSetToWord(cs, size), size * 2)) # result := rope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
proc genSetNode(p: BProc, n: PNode): PRope = proc genSetNode(p: BProc, n: PNode): Rope =
var cs: TBitSet var cs: TBitSet
var size = int(getSize(n.typ)) var size = int(getSize(n.typ))
toBitSet(n, cs) toBitSet(n, cs)
if size > 8: if size > 8:
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId) var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
result = con("TMP", toRope(id)) result = "TMP" & rope(id)
if id == gBackendId: if id == gBackendId:
# not found in cache: # not found in cache:
inc(gBackendId) inc(gBackendId)
appf(p.module.s[cfsData], "static NIM_CONST $1 $2 = $3;$n", addf(p.module.s[cfsData], "static NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(p.module, n.typ), result, genRawSetData(cs, size)]) [getTypeDesc(p.module, n.typ), result, genRawSetData(cs, size)])
else: else:
result = genRawSetData(cs, size) result = genRawSetData(cs, size)
@ -211,12 +211,12 @@ proc asgnComplexity(n: PNode): int =
result += asgnComplexity(t) result += asgnComplexity(t)
else: discard else: discard
proc optAsgnLoc(a: TLoc, t: PType, field: PRope): TLoc = proc optAsgnLoc(a: TLoc, t: PType, field: Rope): TLoc =
assert field != nil assert field != nil
result.k = locField result.k = locField
result.s = a.s result.s = a.s
result.t = t result.t = t
result.r = rdLoc(a).con(".").con(field) result.r = rdLoc(a) & "." & field
result.heapRoot = a.heapRoot result.heapRoot = a.heapRoot
proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
@ -230,7 +230,7 @@ proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
let t = skipTypes(dest.t, abstractInst).getUniqueType() let t = skipTypes(dest.t, abstractInst).getUniqueType()
for i in 0 .. <t.len: for i in 0 .. <t.len:
let t = t.sons[i] let t = t.sons[i]
let field = ropef("Field$1", i.toRope) let field = "Field$1" % [i.rope]
genAssignment(p, optAsgnLoc(dest, t, field), genAssignment(p, optAsgnLoc(dest, t, field),
optAsgnLoc(src, t, field), newflags) optAsgnLoc(src, t, field), newflags)
@ -313,8 +313,8 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
of tyProc: of tyProc:
if needsComplexAssignment(dest.t): if needsComplexAssignment(dest.t):
# optimize closure assignment: # optimize closure assignment:
let a = optAsgnLoc(dest, dest.t, "ClEnv".toRope) let a = optAsgnLoc(dest, dest.t, "ClEnv".rope)
let b = optAsgnLoc(src, dest.t, "ClEnv".toRope) let b = optAsgnLoc(src, dest.t, "ClEnv".rope)
genRefAssign(p, a, b, flags) genRefAssign(p, a, b, flags)
linefmt(p, cpsStmts, "$1.ClPrc = $2.ClPrc;$n", rdLoc(dest), rdLoc(src)) linefmt(p, cpsStmts, "$1.ClPrc = $2.ClPrc;$n", rdLoc(dest), rdLoc(src))
else: else:
@ -365,7 +365,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if mapType(ty) == ctArray: if mapType(ty) == ctArray:
useStringh(p.module) useStringh(p.module)
linefmt(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n", linefmt(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))) rdLoc(dest), rdLoc(src), rope(getSize(dest.t)))
else: else:
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString, of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString,
@ -391,7 +391,7 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) =
if mapType(ty) == ctArray: if mapType(ty) == ctArray:
useStringh(p.module) useStringh(p.module)
linefmt(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n", linefmt(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
rdLoc(dest), rdLoc(src), toRope(getSize(dest.t))) rdLoc(dest), rdLoc(src), rope(getSize(dest.t)))
else: else:
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
of tyPointer, tyChar, tyBool, tyEnum, tyCString, of tyPointer, tyChar, tyBool, tyEnum, tyCString,
@ -409,7 +409,7 @@ proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) =
else: else:
d = s # ``d`` is free, so fill it with ``s`` d = s # ``d`` is free, so fill it with ``s``
proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) = proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope) =
var a: TLoc var a: TLoc
if d.k != locNone: if d.k != locNone:
# need to generate an assignment here # need to generate an assignment here
@ -424,7 +424,7 @@ proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
d.t = t d.t = t
d.r = r d.r = r
proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) = proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope) =
var a: TLoc var a: TLoc
if d.k != locNone: if d.k != locNone:
# need to generate an assignment here # need to generate an assignment here
@ -486,9 +486,9 @@ proc unaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) =
putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdCharLoc(a)])) putIntoDest(p, d, e.typ, ropecg(p.module, frmt, [rdCharLoc(a)]))
proc binaryArithOverflowRaw(p: BProc, t: PType, a, b: TLoc; proc binaryArithOverflowRaw(p: BProc, t: PType, a, b: TLoc;
frmt: string): PRope = frmt: string): Rope =
var size = getSize(t) var size = getSize(t)
let storage = if size < platform.intSize: toRope("NI") let storage = if size < platform.intSize: rope("NI")
else: getTypeDesc(p.module, t) else: getTypeDesc(p.module, t)
result = getTempName() result = getTempName()
linefmt(p, cpsLocals, "$1 $2;$n", storage, result) linefmt(p, cpsLocals, "$1 $2;$n", storage, result)
@ -522,11 +522,11 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
# later via 'chckRange' # later via 'chckRange'
let t = e.typ.skipTypes(abstractRange) let t = e.typ.skipTypes(abstractRange)
if optOverflowCheck notin p.options: if optOverflowCheck notin p.options:
let res = ropef(opr[m], [getTypeDesc(p.module, t), rdLoc(a), rdLoc(b)]) let res = opr[m] % [getTypeDesc(p.module, t), rdLoc(a), rdLoc(b)]
putIntoDest(p, d, e.typ, res) putIntoDest(p, d, e.typ, res)
else: else:
let res = binaryArithOverflowRaw(p, t, a, b, prc[m]) let res = binaryArithOverflowRaw(p, t, a, b, prc[m])
putIntoDest(p, d, e.typ, ropef("($#)($#)", [getTypeDesc(p.module, t), res])) putIntoDest(p, d, e.typ, "($#)($#)" % [getTypeDesc(p.module, t), res])
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
const const
@ -544,7 +544,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
if optOverflowCheck in p.options: if optOverflowCheck in p.options:
linefmt(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n", linefmt(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n",
rdLoc(a), intLiteral(firstOrd(t))) rdLoc(a), intLiteral(firstOrd(t)))
putIntoDest(p, d, e.typ, ropef(opr[m], [rdLoc(a), toRope(getSize(t) * 8)])) putIntoDest(p, d, e.typ, opr[m] % [rdLoc(a), rope(getSize(t) * 8)])
proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) = proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
const const
@ -613,8 +613,8 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
# BUGFIX: cannot use result-type here, as it may be a boolean # BUGFIX: cannot use result-type here, as it may be a boolean
s = max(getSize(a.t), getSize(b.t)) * 8 s = max(getSize(a.t), getSize(b.t)) * 8
putIntoDest(p, d, e.typ, putIntoDest(p, d, e.typ,
ropef(binArithTab[op], [rdLoc(a), rdLoc(b), toRope(s), binArithTab[op] % [rdLoc(a), rdLoc(b), rope(s),
getSimpleTypeDesc(p.module, e.typ)])) getSimpleTypeDesc(p.module, e.typ)])
proc genEqProc(p: BProc, e: PNode, d: var TLoc) = proc genEqProc(p: BProc, e: PNode, d: var TLoc) =
var a, b: TLoc var a, b: TLoc
@ -624,10 +624,9 @@ proc genEqProc(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[2], b) initLocExpr(p, e.sons[2], b)
if a.t.callConv == ccClosure: if a.t.callConv == ccClosure:
putIntoDest(p, d, e.typ, putIntoDest(p, d, e.typ,
ropef("($1.ClPrc == $2.ClPrc && $1.ClEnv == $2.ClEnv)", [ "($1.ClPrc == $2.ClPrc && $1.ClEnv == $2.ClEnv)" % [rdLoc(a), rdLoc(b)])
rdLoc(a), rdLoc(b)]))
else: else:
putIntoDest(p, d, e.typ, ropef("($1 == $2)", [rdLoc(a), rdLoc(b)])) putIntoDest(p, d, e.typ, "($1 == $2)" % [rdLoc(a), rdLoc(b)])
proc genIsNil(p: BProc, e: PNode, d: var TLoc) = proc genIsNil(p: BProc, e: PNode, d: var TLoc) =
let t = skipTypes(e.sons[1].typ, abstractRange) let t = skipTypes(e.sons[1].typ, abstractRange)
@ -667,8 +666,8 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[1], a)
t = skipTypes(e.typ, abstractRange) t = skipTypes(e.typ, abstractRange)
putIntoDest(p, d, e.typ, putIntoDest(p, d, e.typ,
ropef(unArithTab[op], [rdLoc(a), toRope(getSize(t) * 8), unArithTab[op] % [rdLoc(a), rope(getSize(t) * 8),
getSimpleTypeDesc(p.module, e.typ)])) getSimpleTypeDesc(p.module, e.typ)])
proc isCppRef(p: BProc; typ: PType): bool {.inline.} = proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
result = p.module.compileToCpp and result = p.module.compileToCpp and
@ -707,14 +706,14 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
# so the '&' and '*' cancel out: # so the '&' and '*' cancel out:
putIntoDest(p, d, a.t.sons[0], rdLoc(a)) putIntoDest(p, d, a.t.sons[0], rdLoc(a))
else: else:
putIntoDest(p, d, e.typ, ropef("(*$1)", [rdLoc(a)])) putIntoDest(p, d, e.typ, "(*$1)" % [rdLoc(a)])
proc genAddr(p: BProc, e: PNode, d: var TLoc) = proc genAddr(p: BProc, e: PNode, d: var TLoc) =
# careful 'addr(myptrToArray)' needs to get the ampersand: # careful 'addr(myptrToArray)' needs to get the ampersand:
if e.sons[0].typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}: if e.sons[0].typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
var a: TLoc var a: TLoc
initLocExpr(p, e.sons[0], a) initLocExpr(p, e.sons[0], a)
putIntoDest(p, d, e.typ, con("&", a.r)) putIntoDest(p, d, e.typ, "&" & a.r)
#Message(e.info, warnUser, "HERE NEW &") #Message(e.info, warnUser, "HERE NEW &")
elif mapType(e.sons[0].typ) == ctArray or isCppRef(p, e.sons[0].typ): elif mapType(e.sons[0].typ) == ctArray or isCppRef(p, e.sons[0].typ):
expr(p, e.sons[0], d) expr(p, e.sons[0], d)
@ -747,7 +746,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
case e.sons[1].kind case e.sons[1].kind
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal) of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
else: internalError(e.info, "genTupleElem") else: internalError(e.info, "genTupleElem")
appf(r, ".Field$1", [toRope(i)]) addf(r, ".Field$1", [rope(i)])
putIntoDest(p, d, ty.sons[i], r) putIntoDest(p, d, ty.sons[i], r)
proc genRecordField(p: BProc, e: PNode, d: var TLoc) = proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
@ -758,7 +757,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
if ty.kind == tyTuple: if ty.kind == tyTuple:
# we found a unique tuple type which lacks field information # we found a unique tuple type which lacks field information
# so we use Field$i # so we use Field$i
appf(r, ".Field$1", [toRope(f.position)]) addf(r, ".Field$1", [rope(f.position)])
putIntoDest(p, d, f.typ, r) putIntoDest(p, d, f.typ, r)
else: else:
var field: PSym = nil var field: PSym = nil
@ -767,17 +766,17 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
internalError(e.info, "genRecordField") internalError(e.info, "genRecordField")
field = lookupInRecord(ty.n, f.name) field = lookupInRecord(ty.n, f.name)
if field != nil: break if field != nil: break
if not p.module.compileToCpp: app(r, ".Sup") if not p.module.compileToCpp: add(r, ".Sup")
ty = getUniqueType(ty.sons[0]) ty = getUniqueType(ty.sons[0])
if field == nil: internalError(e.info, "genRecordField 2 ") if field == nil: internalError(e.info, "genRecordField 2 ")
if field.loc.r == nil: internalError(e.info, "genRecordField 3") if field.loc.r == nil: internalError(e.info, "genRecordField 3")
appf(r, ".$1", [field.loc.r]) addf(r, ".$1", [field.loc.r])
putIntoDest(p, d, field.typ, r) putIntoDest(p, d, field.typ, r)
#d.s = a.s #d.s = a.s
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
proc genFieldCheck(p: BProc, e: PNode, obj: PRope, field: PSym) = proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
var test, u, v: TLoc var test, u, v: TLoc
for i in countup(1, sonsLen(e) - 1): for i in countup(1, sonsLen(e) - 1):
var it = e.sons[i] var it = e.sons[i]
@ -790,12 +789,12 @@ proc genFieldCheck(p: BProc, e: PNode, obj: PRope, field: PSym) =
initLoc(test, locNone, it.typ, OnStack) initLoc(test, locNone, it.typ, OnStack)
initLocExpr(p, it.sons[1], u) initLocExpr(p, it.sons[1], u)
initLoc(v, locExpr, disc.typ, OnUnknown) initLoc(v, locExpr, disc.typ, OnUnknown)
v.r = ropef("$1.$2", [obj, disc.sym.loc.r]) v.r = "$1.$2" % [obj, disc.sym.loc.r]
genInExprAux(p, it, u, v, test) genInExprAux(p, it, u, v, test)
let id = nodeTableTestOrSet(p.module.dataCache, let id = nodeTableTestOrSet(p.module.dataCache,
newStrNode(nkStrLit, field.name.s), gBackendId) newStrNode(nkStrLit, field.name.s), gBackendId)
let strLit = if id == gBackendId: getStrLit(p.module, field.name.s) let strLit = if id == gBackendId: getStrLit(p.module, field.name.s)
else: con("TMP", toRope(id)) else: "TMP" & rope(id)
if op.magic == mNot: if op.magic == mNot:
linefmt(p, cpsStmts, linefmt(p, cpsStmts,
"if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n", "if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n",
@ -811,7 +810,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
a: TLoc a: TLoc
f, field: PSym f, field: PSym
ty: PType ty: PType
r: PRope r: Rope
ty = genRecordFieldAux(p, e.sons[0], d, a) ty = genRecordFieldAux(p, e.sons[0], d, a)
r = rdLoc(a) r = rdLoc(a)
f = e.sons[0].sons[1].sym f = e.sons[0].sons[1].sym
@ -820,13 +819,13 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
assert(ty.kind in {tyTuple, tyObject}) assert(ty.kind in {tyTuple, tyObject})
field = lookupInRecord(ty.n, f.name) field = lookupInRecord(ty.n, f.name)
if field != nil: break if field != nil: break
if not p.module.compileToCpp: app(r, ".Sup") if not p.module.compileToCpp: add(r, ".Sup")
ty = getUniqueType(ty.sons[0]) ty = getUniqueType(ty.sons[0])
if field == nil: internalError(e.info, "genCheckedRecordField") if field == nil: internalError(e.info, "genCheckedRecordField")
if field.loc.r == nil: if field.loc.r == nil:
internalError(e.info, "genCheckedRecordField") # generate the checks: internalError(e.info, "genCheckedRecordField") # generate the checks:
genFieldCheck(p, e, r, field) genFieldCheck(p, e, r, field)
app(r, rfmt(nil, ".$1", field.loc.r)) add(r, rfmt(nil, ".$1", field.loc.r))
putIntoDest(p, d, field.typ, r) putIntoDest(p, d, field.typ, r)
else: else:
genRecordField(p, e.sons[0], d) genRecordField(p, e.sons[0], d)
@ -955,11 +954,11 @@ proc genEcho(p: BProc, n: PNode) =
# is threadsafe. # is threadsafe.
internalAssert n.kind == nkBracket internalAssert n.kind == nkBracket
discard lists.includeStr(p.module.headerFiles, "<stdio.h>") discard lists.includeStr(p.module.headerFiles, "<stdio.h>")
var args: PRope = nil var args: Rope = nil
var a: TLoc var a: TLoc
for i in countup(0, n.len-1): for i in countup(0, n.len-1):
initLocExpr(p, n.sons[i], a) initLocExpr(p, n.sons[i], a)
appf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)]) addf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
linefmt(p, cpsStmts, "printf($1$2);$n", linefmt(p, cpsStmts, "printf($1$2);$n",
makeCString(repeat("%s", n.len) & tnl), args) makeCString(repeat("%s", n.len) & tnl), args)
@ -986,22 +985,22 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
var a, tmp: TLoc var a, tmp: TLoc
getTemp(p, e.typ, tmp) getTemp(p, e.typ, tmp)
var L = 0 var L = 0
var appends: PRope = nil var appends: Rope = nil
var lens: PRope = nil var lens: Rope = nil
for i in countup(0, sonsLen(e) - 2): for i in countup(0, sonsLen(e) - 2):
# compute the length expression: # compute the length expression:
initLocExpr(p, e.sons[i + 1], a) initLocExpr(p, e.sons[i + 1], a)
if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar: if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar:
inc(L) inc(L)
app(appends, rfmt(p.module, "#appendChar($1, $2);$n", tmp.r, rdLoc(a))) add(appends, rfmt(p.module, "#appendChar($1, $2);$n", tmp.r, rdLoc(a)))
else: else:
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}: if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
inc(L, len(e.sons[i + 1].strVal)) inc(L, len(e.sons[i + 1].strVal))
else: else:
appf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)]) addf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)])
app(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a))) add(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a)))
linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, toRope(L)) linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L))
app(p.s(cpsStmts), appends) add(p.s(cpsStmts), appends)
if d.k == locNone: if d.k == locNone:
d = tmp d = tmp
keepAlive(p, tmp) keepAlive(p, tmp)
@ -1023,7 +1022,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
# } # }
var var
a, dest: TLoc a, dest: TLoc
appends, lens: PRope appends, lens: Rope
assert(d.k == locNone) assert(d.k == locNone)
var L = 0 var L = 0
initLocExpr(p, e.sons[1], dest) initLocExpr(p, e.sons[1], dest)
@ -1032,19 +1031,19 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[i + 2], a) initLocExpr(p, e.sons[i + 2], a)
if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar: if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar:
inc(L) inc(L)
app(appends, rfmt(p.module, "#appendChar($1, $2);$n", add(appends, rfmt(p.module, "#appendChar($1, $2);$n",
rdLoc(dest), rdLoc(a))) rdLoc(dest), rdLoc(a)))
else: else:
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}: if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
inc(L, len(e.sons[i + 2].strVal)) inc(L, len(e.sons[i + 2].strVal))
else: else:
appf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)]) addf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)])
app(appends, rfmt(p.module, "#appendString($1, $2);$n", add(appends, rfmt(p.module, "#appendString($1, $2);$n",
rdLoc(dest), rdLoc(a))) rdLoc(dest), rdLoc(a)))
linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n", linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
rdLoc(dest), lens, toRope(L)) rdLoc(dest), lens, rope(L))
keepAlive(p, dest) keepAlive(p, dest)
app(p.s(cpsStmts), appends) add(p.s(cpsStmts), appends)
gcUsage(e) gcUsage(e)
proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
@ -1074,14 +1073,14 @@ proc genReset(p: BProc, n: PNode) =
linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n", linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange))) addrLoc(a), genTypeInfo(p.module, skipTypes(a.t, abstractVarRange)))
proc rawGenNew(p: BProc, a: TLoc, sizeExpr: PRope) = proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
var sizeExpr = sizeExpr var sizeExpr = sizeExpr
let refType = skipTypes(a.t, abstractVarRange) let refType = skipTypes(a.t, abstractVarRange)
var b: TLoc var b: TLoc
initLoc(b, locExpr, a.t, OnHeap) initLoc(b, locExpr, a.t, OnHeap)
if sizeExpr.isNil: if sizeExpr.isNil:
sizeExpr = ropef("sizeof($1)", sizeExpr = "sizeof($1)" %
getTypeDesc(p.module, skipTypes(refType.sons[0], abstractRange))) [getTypeDesc(p.module, skipTypes(refType.sons[0], abstractRange))]
let args = [getTypeDesc(p.module, refType), let args = [getTypeDesc(p.module, refType),
genTypeInfo(p.module, refType), genTypeInfo(p.module, refType),
sizeExpr] sizeExpr]
@ -1111,7 +1110,7 @@ proc genNew(p: BProc, e: PNode) =
rawGenNew(p, a, nil) rawGenNew(p, a, nil)
gcUsage(e) gcUsage(e)
proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) = proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope) =
let seqtype = skipTypes(dest.t, abstractVarRange) let seqtype = skipTypes(dest.t, abstractVarRange)
let args = [getTypeDesc(p.module, seqtype), let args = [getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqtype), length] genTypeInfo(p.module, seqtype), length]
@ -1144,7 +1143,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
if isRef: if isRef:
rawGenNew(p, tmp, nil) rawGenNew(p, tmp, nil)
t = t.lastSon.skipTypes(abstractInst) t = t.lastSon.skipTypes(abstractInst)
r = ropef("(*$1)", r) r = "(*$1)" % [r]
gcUsage(e) gcUsage(e)
else: else:
constructLoc(p, tmp) constructLoc(p, tmp)
@ -1158,13 +1157,13 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
while ty != nil: while ty != nil:
field = lookupInRecord(ty.n, it.sons[0].sym.name) field = lookupInRecord(ty.n, it.sons[0].sym.name)
if field != nil: break if field != nil: break
if not p.module.compileToCpp: app(tmp2.r, ".Sup") if not p.module.compileToCpp: add(tmp2.r, ".Sup")
ty = getUniqueType(ty.sons[0]) ty = getUniqueType(ty.sons[0])
if field == nil or field.loc.r == nil: internalError(e.info, "genObjConstr") if field == nil or field.loc.r == nil: internalError(e.info, "genObjConstr")
if it.len == 3 and optFieldCheck in p.options: if it.len == 3 and optFieldCheck in p.options:
genFieldCheck(p, it.sons[2], tmp2.r, field) genFieldCheck(p, it.sons[2], tmp2.r, field)
app(tmp2.r, ".") add(tmp2.r, ".")
app(tmp2.r, field.loc.r) add(tmp2.r, field.loc.r)
tmp2.k = locTemp tmp2.k = locTemp
tmp2.t = field.loc.t tmp2.t = field.loc.t
tmp2.s = if isRef: OnHeap else: OnStack tmp2.s = if isRef: OnHeap else: OnStack
@ -1214,14 +1213,14 @@ proc genNewFinalize(p: BProc, e: PNode) =
var var
a, b, f: TLoc a, b, f: TLoc
refType, bt: PType refType, bt: PType
ti: PRope ti: Rope
oldModule: BModule oldModule: BModule
refType = skipTypes(e.sons[1].typ, abstractVarRange) refType = skipTypes(e.sons[1].typ, abstractVarRange)
initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], f) initLocExpr(p, e.sons[2], f)
initLoc(b, locExpr, a.t, OnHeap) initLoc(b, locExpr, a.t, OnHeap)
ti = genTypeInfo(p.module, refType) ti = genTypeInfo(p.module, refType)
appf(p.module.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)]) addf(p.module.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [ b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
getTypeDesc(p.module, refType), getTypeDesc(p.module, refType),
ti, getTypeDesc(p.module, skipTypes(refType.lastSon, abstractRange))]) ti, getTypeDesc(p.module, skipTypes(refType.lastSon, abstractRange))])
@ -1230,18 +1229,18 @@ proc genNewFinalize(p: BProc, e: PNode) =
genObjectInit(p, cpsStmts, bt, a, false) genObjectInit(p, cpsStmts, bt, a, false)
gcUsage(e) gcUsage(e)
proc genOfHelper(p: BProc; dest: PType; a: PRope): PRope = proc genOfHelper(p: BProc; dest: PType; a: Rope): Rope =
# unfortunately 'genTypeInfo' sets tfObjHasKids as a side effect, so we # unfortunately 'genTypeInfo' sets tfObjHasKids as a side effect, so we
# have to call it here first: # have to call it here first:
let ti = genTypeInfo(p.module, dest) let ti = genTypeInfo(p.module, dest)
if tfFinal in dest.flags or (p.module.objHasKidsValid and if tfFinal in dest.flags or (p.module.objHasKidsValid and
tfObjHasKids notin dest.flags): tfObjHasKids notin dest.flags):
result = ropef("$1.m_type == $2", a, ti) result = "$1.m_type == $2" % [a, ti]
else: else:
discard cgsym(p.module, "TNimType") discard cgsym(p.module, "TNimType")
inc p.module.labels inc p.module.labels
let cache = con("Nim_OfCheck_CACHE", p.module.labels.toRope) let cache = "Nim_OfCheck_CACHE" & p.module.labels.rope
appf(p.module.s[cfsVars], "static TNimType* $#[2];$n", cache) addf(p.module.s[cfsVars], "static TNimType* $#[2];$n", [cache])
result = rfmt(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache) result = rfmt(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache)
when false: when false:
# former version: # former version:
@ -1253,7 +1252,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
initLocExpr(p, x, a) initLocExpr(p, x, a)
var dest = skipTypes(typ, typedescPtrs) var dest = skipTypes(typ, typedescPtrs)
var r = rdLoc(a) var r = rdLoc(a)
var nilCheck: PRope = nil var nilCheck: Rope = nil
var t = skipTypes(a.t, abstractInst) var t = skipTypes(a.t, abstractInst)
while t.kind in {tyVar, tyPtr, tyRef}: while t.kind in {tyVar, tyPtr, tyRef}:
if t.kind != tyVar: nilCheck = r if t.kind != tyVar: nilCheck = r
@ -1262,7 +1261,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
t = skipTypes(t.lastSon, typedescInst) t = skipTypes(t.lastSon, typedescInst)
if not p.module.compileToCpp: if not p.module.compileToCpp:
while t.kind == tyObject and t.sons[0] != nil: while t.kind == tyObject and t.sons[0] != nil:
app(r, ~".Sup") add(r, ~".Sup")
t = skipTypes(t.sons[0], typedescInst) t = skipTypes(t.sons[0], typedescInst)
if isObjLackingTypeField(t): if isObjLackingTypeField(t):
globalError(x.info, errGenerated, globalError(x.info, errGenerated,
@ -1303,13 +1302,13 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
var b: TLoc var b: TLoc
case a.t.kind case a.t.kind
of tyOpenArray, tyVarargs: of tyOpenArray, tyVarargs:
putIntoDest(p, b, e.typ, ropef("$1, $1Len0", [rdLoc(a)])) putIntoDest(p, b, e.typ, "$1, $1Len0" % [rdLoc(a)])
of tyString, tySequence: of tyString, tySequence:
putIntoDest(p, b, e.typ, putIntoDest(p, b, e.typ,
ropef("$1->data, $1->$2", [rdLoc(a), lenField(p)])) "$1->data, $1->$2" % [rdLoc(a), lenField(p)])
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
putIntoDest(p, b, e.typ, putIntoDest(p, b, e.typ,
ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))])) "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))])
else: internalError(e.sons[0].info, "genRepr()") else: internalError(e.sons[0].info, "genRepr()")
putIntoDest(p, d, e.typ, putIntoDest(p, d, e.typ,
ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b), ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
@ -1357,8 +1356,8 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else: unaryExpr(p, e, d, "$1->len") else: unaryExpr(p, e, d, "$1->len")
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
# YYY: length(sideeffect) is optimized away incorrectly? # YYY: length(sideeffect) is optimized away incorrectly?
if op == mHigh: putIntoDest(p, d, e.typ, toRope(lastOrd(typ))) if op == mHigh: putIntoDest(p, d, e.typ, rope(lastOrd(typ)))
else: putIntoDest(p, d, e.typ, toRope(lengthOrd(typ))) else: putIntoDest(p, d, e.typ, rope(lengthOrd(typ)))
else: internalError(e.info, "genArrayLen()") else: internalError(e.info, "genArrayLen()")
proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
@ -1396,13 +1395,13 @@ proc genSwap(p: BProc, e: PNode, d: var TLoc) =
genAssignment(p, a, b, {}) genAssignment(p, a, b, {})
genAssignment(p, b, tmp, {}) genAssignment(p, b, tmp, {})
proc rdSetElemLoc(a: TLoc, setType: PType): PRope = proc rdSetElemLoc(a: TLoc, setType: PType): Rope =
# read a location of an set element; it may need a subtraction operation # read a location of an set element; it may need a subtraction operation
# before the set operation # before the set operation
result = rdCharLoc(a) result = rdCharLoc(a)
assert(setType.kind == tySet) assert(setType.kind == tySet)
if firstOrd(setType) != 0: if firstOrd(setType) != 0:
result = ropef("($1- $2)", [result, toRope(firstOrd(setType))]) result = "($1- $2)" % [result, rope(firstOrd(setType))]
proc fewCmps(s: PNode): bool = proc fewCmps(s: PNode): bool =
# this function estimates whether it is better to emit code # this function estimates whether it is better to emit code
@ -1416,7 +1415,7 @@ proc fewCmps(s: PNode): bool =
result = sonsLen(s) <= 8 # 8 seems to be a good value result = sonsLen(s) <= 8 # 8 seems to be a good value
proc binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) = proc binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) =
putIntoDest(p, d, e.typ, ropef(frmt, [rdLoc(a), rdSetElemLoc(b, a.t)])) putIntoDest(p, d, e.typ, frmt % [rdLoc(a), rdSetElemLoc(b, a.t)])
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) = proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) =
case int(getSize(skipTypes(e.sons[1].typ, abstractVar))) case int(getSize(skipTypes(e.sons[1].typ, abstractVar)))
@ -1446,19 +1445,19 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
e.sons[2] e.sons[2]
initLocExpr(p, ea, a) initLocExpr(p, ea, a)
initLoc(b, locExpr, e.typ, OnUnknown) initLoc(b, locExpr, e.typ, OnUnknown)
b.r = toRope("(") b.r = rope("(")
var length = sonsLen(e.sons[1]) var length = sonsLen(e.sons[1])
for i in countup(0, length - 1): for i in countup(0, length - 1):
if e.sons[1].sons[i].kind == nkRange: if e.sons[1].sons[i].kind == nkRange:
initLocExpr(p, e.sons[1].sons[i].sons[0], x) initLocExpr(p, e.sons[1].sons[i].sons[0], x)
initLocExpr(p, e.sons[1].sons[i].sons[1], y) initLocExpr(p, e.sons[1].sons[i].sons[1], y)
appf(b.r, "$1 >= $2 && $1 <= $3", addf(b.r, "$1 >= $2 && $1 <= $3",
[rdCharLoc(a), rdCharLoc(x), rdCharLoc(y)]) [rdCharLoc(a), rdCharLoc(x), rdCharLoc(y)])
else: else:
initLocExpr(p, e.sons[1].sons[i], x) initLocExpr(p, e.sons[1].sons[i], x)
appf(b.r, "$1 == $2", [rdCharLoc(a), rdCharLoc(x)]) addf(b.r, "$1 == $2", [rdCharLoc(a), rdCharLoc(x)])
if i < length - 1: app(b.r, " || ") if i < length - 1: add(b.r, " || ")
app(b.r, ")") add(b.r, ")")
putIntoDest(p, d, e.typ, b.r) putIntoDest(p, d, e.typ, b.r)
else: else:
assert(e.sons[1].typ != nil) assert(e.sons[1].typ != nil)
@ -1514,7 +1513,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
initLocExpr(p, e.sons[2], b) initLocExpr(p, e.sons[2], b)
if d.k == locNone: getTemp(p, getSysType(tyBool), d) if d.k == locNone: getTemp(p, getSysType(tyBool), d)
lineF(p, cpsStmts, lookupOpr[op], lineF(p, cpsStmts, lookupOpr[op],
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)]) [rdLoc(i), rope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
of mEqSet: of mEqSet:
useStringh(p.module) useStringh(p.module)
binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)") binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
@ -1527,8 +1526,8 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
lineF(p, cpsStmts, lineF(p, cpsStmts,
"for ($1 = 0; $1 < $2; $1++) $n" & "for ($1 = 0; $1 < $2; $1++) $n" &
" $3[$1] = $4[$1] $6 $5[$1];$n", [ " $3[$1] = $4[$1] $6 $5[$1];$n", [
rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b), rdLoc(i), rope(size), rdLoc(d), rdLoc(a), rdLoc(b),
toRope(lookupOpr[op])]) rope(lookupOpr[op])])
of mInSet: genInOp(p, e, d) of mInSet: genInOp(p, e, d)
else: internalError(e.info, "genSetOp") else: internalError(e.info, "genSetOp")
@ -1545,14 +1544,14 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[1], a)
let etyp = skipTypes(e.typ, abstractRange) let etyp = skipTypes(e.typ, abstractRange)
if etyp.kind in ValueTypes and lfIndirect notin a.flags: if etyp.kind in ValueTypes and lfIndirect notin a.flags:
putIntoDest(p, d, e.typ, ropef("(*($1*) ($2))", putIntoDest(p, d, e.typ, "(*($1*) ($2))" %
[getTypeDesc(p.module, e.typ), addrLoc(a)])) [getTypeDesc(p.module, e.typ), addrLoc(a)])
elif etyp.kind == tyProc and etyp.callConv == ccClosure: elif etyp.kind == tyProc and etyp.callConv == ccClosure:
putIntoDest(p, d, e.typ, ropef("(($1) ($2))", putIntoDest(p, d, e.typ, "(($1) ($2))" %
[getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)])) [getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)])
else: else:
putIntoDest(p, d, e.typ, ropef("(($1) ($2))", putIntoDest(p, d, e.typ, "(($1) ($2))" %
[getTypeDesc(p.module, e.typ), rdCharLoc(a)])) [getTypeDesc(p.module, e.typ), rdCharLoc(a)])
proc genCast(p: BProc, e: PNode, d: var TLoc) = proc genCast(p: BProc, e: PNode, d: var TLoc) =
const floatTypes = {tyFloat..tyFloat128} const floatTypes = {tyFloat..tyFloat128}
@ -1562,9 +1561,9 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
if destt.kind in floatTypes or srct.kind in floatTypes: if destt.kind in floatTypes or srct.kind in floatTypes:
# 'cast' and some float type involved? --> use a union. # 'cast' and some float type involved? --> use a union.
inc(p.labels) inc(p.labels)
var lbl = p.labels.toRope var lbl = p.labels.rope
var tmp: TLoc var tmp: TLoc
tmp.r = ropef("LOC$1.source", lbl) tmp.r = "LOC$1.source" % [lbl]
linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n", linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n",
getTypeDesc(p.module, srct), getTypeDesc(p.module, destt), lbl) getTypeDesc(p.module, srct), getTypeDesc(p.module, destt), lbl)
tmp.k = locExpr tmp.k = locExpr
@ -1572,7 +1571,7 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
tmp.s = OnStack tmp.s = OnStack
tmp.flags = {} tmp.flags = {}
expr(p, e.sons[1], tmp) expr(p, e.sons[1], tmp)
putIntoDest(p, d, e.typ, ropef("LOC$#.dest", lbl)) putIntoDest(p, d, e.typ, "LOC$#.dest" % [lbl])
else: else:
# I prefer the shorter cast version for pointer types -> generate less # I prefer the shorter cast version for pointer types -> generate less
# C code; plus it's the right thing to do for closures: # C code; plus it's the right thing to do for closures:
@ -1584,8 +1583,8 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
# range checks for unsigned turned out to be buggy and annoying: # range checks for unsigned turned out to be buggy and annoying:
if optRangeCheck notin p.options or dest.kind in {tyUInt..tyUInt64}: if optRangeCheck notin p.options or dest.kind in {tyUInt..tyUInt64}:
initLocExpr(p, n.sons[0], a) initLocExpr(p, n.sons[0], a)
putIntoDest(p, d, n.typ, ropef("(($1) ($2))", putIntoDest(p, d, n.typ, "(($1) ($2))" %
[getTypeDesc(p.module, dest), rdCharLoc(a)])) [getTypeDesc(p.module, dest), rdCharLoc(a)])
else: else:
initLocExpr(p, n.sons[0], a) initLocExpr(p, n.sons[0], a)
if leValue(n.sons[2], n.sons[1]): if leValue(n.sons[2], n.sons[1]):
@ -1593,7 +1592,7 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [ putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
getTypeDesc(p.module, dest), rdCharLoc(a), getTypeDesc(p.module, dest), rdCharLoc(a),
genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest), genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
toRope(magic)])) rope(magic)]))
proc genConv(p: BProc, e: PNode, d: var TLoc) = proc genConv(p: BProc, e: PNode, d: var TLoc) =
let destType = e.typ.skipTypes({tyVar, tyGenericInst}) let destType = e.typ.skipTypes({tyVar, tyGenericInst})
@ -1605,8 +1604,7 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) =
proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) = proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
var a: TLoc var a: TLoc
initLocExpr(p, n.sons[0], a) initLocExpr(p, n.sons[0], a)
putIntoDest(p, d, skipTypes(n.typ, abstractVar), ropef("$1->data", putIntoDest(p, d, skipTypes(n.typ, abstractVar), "$1->data" % [rdLoc(a)])
[rdLoc(a)]))
proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) = proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
var a: TLoc var a: TLoc
@ -1641,7 +1639,7 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b) initLocExpr(p, e.sons[2], b)
putIntoDest(p, d, e.typ, rfmt(nil, "(($4)($2) $1 ($4)($3))", putIntoDest(p, d, e.typ, rfmt(nil, "(($4)($2) $1 ($4)($3))",
toRope(opr[m]), rdLoc(a), rdLoc(b), rope(opr[m]), rdLoc(a), rdLoc(b),
getSimpleTypeDesc(p.module, e[1].typ))) getSimpleTypeDesc(p.module, e[1].typ)))
if optNaNCheck in p.options: if optNaNCheck in p.options:
linefmt(p, cpsStmts, "#nanCheck($1);$n", rdLoc(d)) linefmt(p, cpsStmts, "#nanCheck($1);$n", rdLoc(d))
@ -1651,7 +1649,7 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
binaryArith(p, e, d, m) binaryArith(p, e, d, m)
proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
var line, filen: PRope var line, filen: Rope
case op case op
of mOr, mAnd: genAndOr(p, e, d, op) of mOr, mAnd: genAndOr(p, e, d, op)
of mNot..mToBiggestInt: unaryArith(p, e, d, op) of mNot..mToBiggestInt: unaryArith(p, e, d, op)
@ -1685,8 +1683,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
let ranged = skipTypes(e.sons[1].typ, {tyGenericInst, tyVar}) let ranged = skipTypes(e.sons[1].typ, {tyGenericInst, tyVar})
let res = binaryArithOverflowRaw(p, ranged, a, b, let res = binaryArithOverflowRaw(p, ranged, a, b,
if underlying.kind == tyInt64: fun64[op] else: fun[op]) if underlying.kind == tyInt64: fun64[op] else: fun[op])
putIntoDest(p, a, ranged, ropef("($#)($#)", [ putIntoDest(p, a, ranged, "($#)($#)" % [
getTypeDesc(p.module, ranged), res])) getTypeDesc(p.module, ranged), res])
of mConStrStr: genStrConcat(p, e, d) of mConStrStr: genStrConcat(p, e, d)
of mAppendStrCh: of mAppendStrCh:
@ -1713,8 +1711,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mNewSeq: genNewSeq(p, e) of mNewSeq: genNewSeq(p, e)
of mSizeOf: of mSizeOf:
let t = e.sons[1].typ.skipTypes({tyTypeDesc}) let t = e.sons[1].typ.skipTypes({tyTypeDesc})
putIntoDest(p, d, e.typ, ropef("((NI)sizeof($1))", putIntoDest(p, d, e.typ, "((NI)sizeof($1))" % [getTypeDesc(p.module, t)])
[getTypeDesc(p.module, t)]))
of mChr: genSomeCast(p, e, d) of mChr: genSomeCast(p, e, d)
of mOrd: genOrd(p, e, d) of mOrd: genOrd(p, e, d)
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray: of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
@ -1752,17 +1749,17 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mDotDot: genCall(p, e, d) of mDotDot: genCall(p, e, d)
else: internalError(e.info, "genMagicExpr: " & $op) else: internalError(e.info, "genMagicExpr: " & $op)
proc genConstExpr(p: BProc, n: PNode): PRope proc genConstExpr(p: BProc, n: PNode): Rope
proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool = proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
if nfAllConst in n.flags and d.k == locNone and n.len > 0 and n.isDeepConstExpr: if nfAllConst in n.flags and d.k == locNone and n.len > 0 and n.isDeepConstExpr:
var t = getUniqueType(n.typ) var t = getUniqueType(n.typ)
discard getTypeDesc(p.module, t) # so that any fields are initialized discard getTypeDesc(p.module, t) # so that any fields are initialized
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId) var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
fillLoc(d, locData, t, con("TMP", toRope(id)), OnHeap) fillLoc(d, locData, t, "TMP" & rope(id), OnHeap)
if id == gBackendId: if id == gBackendId:
# expression not found in the cache: # expression not found in the cache:
inc(gBackendId) inc(gBackendId)
appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(p.module, t), d.r, genConstExpr(p, n)]) [getTypeDesc(p.module, t), d.r, genConstExpr(p, n)])
result = true result = true
else: else:
@ -1824,13 +1821,12 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
var it = n.sons[i] var it = n.sons[i]
if it.kind == nkExprColonExpr: it = it.sons[1] if it.kind == nkExprColonExpr: it = it.sons[1]
initLoc(rec, locExpr, it.typ, d.s) initLoc(rec, locExpr, it.typ, d.s)
rec.r = ropef("$1.Field$2", [rdLoc(d), toRope(i)]) rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
expr(p, it, rec) expr(p, it, rec)
when false: when false:
initLoc(rec, locExpr, it.typ, d.s) initLoc(rec, locExpr, it.typ, d.s)
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genTupleConstr") if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genTupleConstr")
rec.r = ropef("$1.$2", rec.r = "$1.$2" % [rdLoc(d), mangleRecFieldName(t.n.sons[i].sym, t)]
[rdLoc(d), mangleRecFieldName(t.n.sons[i].sym, t)])
expr(p, it, rec) expr(p, it, rec)
proc isConstClosure(n: PNode): bool {.inline.} = proc isConstClosure(n: PNode): bool {.inline.} =
@ -1842,8 +1838,8 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
if isConstClosure(n): if isConstClosure(n):
inc(p.labels) inc(p.labels)
var tmp = con("LOC", toRope(p.labels)) var tmp = "LOC" & rope(p.labels)
appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(p.module, n.typ), tmp, genConstExpr(p, n)]) [getTypeDesc(p.module, n.typ), tmp, genConstExpr(p, n)])
putIntoDest(p, d, n.typ, tmp) putIntoDest(p, d, n.typ, tmp)
else: else:
@ -1861,7 +1857,7 @@ proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
if d.k == locNone: getTemp(p, n.typ, d) if d.k == locNone: getTemp(p, n.typ, d)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
initLoc(arr, locExpr, elemType(skipTypes(n.typ, abstractInst)), d.s) initLoc(arr, locExpr, elemType(skipTypes(n.typ, abstractInst)), d.s)
arr.r = ropef("$1[$2]", [rdLoc(d), intLiteral(i)]) arr.r = "$1[$2]" % [rdLoc(d), intLiteral(i)]
expr(p, n.sons[i], arr) expr(p, n.sons[i], arr)
proc genComplexConst(p: BProc, sym: PSym, d: var TLoc) = proc genComplexConst(p: BProc, sym: PSym, d: var TLoc) =
@ -1880,16 +1876,16 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
var dest = skipTypes(n.typ, abstractPtrs) var dest = skipTypes(n.typ, abstractPtrs)
if optObjCheck in p.options and not isObjLackingTypeField(dest): if optObjCheck in p.options and not isObjLackingTypeField(dest):
var r = rdLoc(a) var r = rdLoc(a)
var nilCheck: PRope = nil var nilCheck: Rope = nil
var t = skipTypes(a.t, abstractInst) var t = skipTypes(a.t, abstractInst)
while t.kind in {tyVar, tyPtr, tyRef}: while t.kind in {tyVar, tyPtr, tyRef}:
if t.kind != tyVar: nilCheck = r if t.kind != tyVar: nilCheck = r
if t.kind != tyVar or not p.module.compileToCpp: if t.kind != tyVar or not p.module.compileToCpp:
r = ropef("(*$1)", [r]) r = "(*$1)" % [r]
t = skipTypes(t.lastSon, abstractInst) t = skipTypes(t.lastSon, abstractInst)
if not p.module.compileToCpp: if not p.module.compileToCpp:
while t.kind == tyObject and t.sons[0] != nil: while t.kind == tyObject and t.sons[0] != nil:
app(r, ".Sup") add(r, ".Sup")
t = skipTypes(t.sons[0], abstractInst) t = skipTypes(t.sons[0], abstractInst)
if nilCheck != nil: if nilCheck != nil:
linefmt(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n", linefmt(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
@ -1899,10 +1895,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
r, genTypeInfo(p.module, dest)) r, genTypeInfo(p.module, dest))
if n.sons[0].typ.kind != tyObject: if n.sons[0].typ.kind != tyObject:
putIntoDest(p, d, n.typ, putIntoDest(p, d, n.typ,
ropef("(($1) ($2))", [getTypeDesc(p.module, n.typ), rdLoc(a)])) "(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)])
else: else:
putIntoDest(p, d, n.typ, ropef("(*($1*) ($2))", putIntoDest(p, d, n.typ, "(*($1*) ($2))" %
[getTypeDesc(p.module, dest), addrLoc(a)])) [getTypeDesc(p.module, dest), addrLoc(a)])
proc downConv(p: BProc, n: PNode, d: var TLoc) = proc downConv(p: BProc, n: PNode, d: var TLoc) =
if p.module.compileToCpp: if p.module.compileToCpp:
@ -1919,10 +1915,10 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
var r = rdLoc(a) var r = rdLoc(a)
let isRef = skipTypes(arg.typ, abstractInst).kind in {tyRef, tyPtr, tyVar} let isRef = skipTypes(arg.typ, abstractInst).kind in {tyRef, tyPtr, tyVar}
if isRef: if isRef:
app(r, "->Sup") add(r, "->Sup")
else: else:
app(r, ".Sup") add(r, ".Sup")
for i in countup(2, abs(inheritanceDiff(dest, src))): app(r, ".Sup") for i in countup(2, abs(inheritanceDiff(dest, src))): add(r, ".Sup")
if isRef: if isRef:
# it can happen that we end up generating '&&x->Sup' here, so we pack # it can happen that we end up generating '&&x->Sup' here, so we pack
# the '&x->Sup' into a temporary and then those address is taken # the '&x->Sup' into a temporary and then those address is taken
@ -1933,7 +1929,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
getTemp(p, n.typ, d) getTemp(p, n.typ, d)
linefmt(p, cpsStmts, "$1 = &$2;$n", rdLoc(d), r) linefmt(p, cpsStmts, "$1 = &$2;$n", rdLoc(d), r)
else: else:
r = con("&", r) r = "&" & r
putIntoDest(p, d, n.typ, r) putIntoDest(p, d, n.typ, r)
else: else:
putIntoDest(p, d, n.typ, r) putIntoDest(p, d, n.typ, r)
@ -1942,12 +1938,12 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
var t = getUniqueType(n.typ) var t = getUniqueType(n.typ)
discard getTypeDesc(p.module, t) # so that any fields are initialized discard getTypeDesc(p.module, t) # so that any fields are initialized
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId) var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
var tmp = con("TMP", toRope(id)) var tmp = "TMP" & rope(id)
if id == gBackendId: if id == gBackendId:
# expression not found in the cache: # expression not found in the cache:
inc(gBackendId) inc(gBackendId)
appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(p.module, t), tmp, genConstExpr(p, n)]) [getTypeDesc(p.module, t), tmp, genConstExpr(p, n)])
if d.k == locNone: if d.k == locNone:
@ -1982,7 +1978,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
else: else:
genComplexConst(p, sym, d) genComplexConst(p, sym, d)
of skEnumField: of skEnumField:
putIntoDest(p, d, n.typ, toRope(sym.position)) putIntoDest(p, d, n.typ, rope(sym.position))
of skVar, skForVar, skResult, skLet: of skVar, skForVar, skResult, skLet:
if sfGlobal in sym.flags: genVarPrototype(p.module, sym) if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
if sym.loc.r == nil or sym.loc.t == nil: if sym.loc.r == nil or sym.loc.t == nil:
@ -1991,7 +1987,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
if sfThread in sym.flags: if sfThread in sym.flags:
accessThreadLocalVar(p, sym) accessThreadLocalVar(p, sym)
if emulatedThreadVars(): if emulatedThreadVars():
putIntoDest(p, d, sym.loc.t, con("NimTV->", sym.loc.r)) putIntoDest(p, d, sym.loc.t, "NimTV->" & sym.loc.r)
else: else:
putLocIntoDest(p, d, sym.loc) putLocIntoDest(p, d, sym.loc)
else: else:
@ -2134,42 +2130,42 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
of nkBreakState: genBreakState(p, n) of nkBreakState: genBreakState(p, n)
else: internalError(n.info, "expr(" & $n.kind & "); unknown node kind") else: internalError(n.info, "expr(" & $n.kind & "); unknown node kind")
proc genNamedConstExpr(p: BProc, n: PNode): PRope = proc genNamedConstExpr(p: BProc, n: PNode): Rope =
if n.kind == nkExprColonExpr: result = genConstExpr(p, n.sons[1]) if n.kind == nkExprColonExpr: result = genConstExpr(p, n.sons[1])
else: result = genConstExpr(p, n) else: result = genConstExpr(p, n)
proc genConstSimpleList(p: BProc, n: PNode): PRope = proc genConstSimpleList(p: BProc, n: PNode): Rope =
var length = sonsLen(n) var length = sonsLen(n)
result = toRope("{") result = rope("{")
for i in countup(0, length - 2): for i in countup(0, length - 2):
appf(result, "$1,$n", [genNamedConstExpr(p, n.sons[i])]) addf(result, "$1,$n", [genNamedConstExpr(p, n.sons[i])])
if length > 0: app(result, genNamedConstExpr(p, n.sons[length - 1])) if length > 0: add(result, genNamedConstExpr(p, n.sons[length - 1]))
appf(result, "}$n") addf(result, "}$n", [])
proc genConstSeq(p: BProc, n: PNode, t: PType): PRope = proc genConstSeq(p: BProc, n: PNode, t: PType): Rope =
var data = ropef("{{$1, $1}", n.len.toRope) var data = "{{$1, $1}" % [n.len.rope]
if n.len > 0: if n.len > 0:
# array part needs extra curlies: # array part needs extra curlies:
data.app(", {") data.add(", {")
for i in countup(0, n.len - 1): for i in countup(0, n.len - 1):
if i > 0: data.appf(",$n") if i > 0: data.addf(",$n", [])
data.app genConstExpr(p, n.sons[i]) data.add genConstExpr(p, n.sons[i])
data.app("}") data.add("}")
data.app("}") data.add("}")
inc(gBackendId) inc(gBackendId)
result = con("CNSTSEQ", gBackendId.toRope) result = "CNSTSEQ" & gBackendId.rope
appcg(p.module, cfsData, appcg(p.module, cfsData,
"NIM_CONST struct {$n" & "NIM_CONST struct {$n" &
" #TGenericSeq Sup;$n" & " #TGenericSeq Sup;$n" &
" $1 data[$2];$n" & " $1 data[$2];$n" &
"} $3 = $4;$n", [ "} $3 = $4;$n", [
getTypeDesc(p.module, t.sons[0]), n.len.toRope, result, data]) getTypeDesc(p.module, t.sons[0]), n.len.rope, result, data])
result = ropef("(($1)&$2)", [getTypeDesc(p.module, t), result]) result = "(($1)&$2)" % [getTypeDesc(p.module, t), result]
proc genConstExpr(p: BProc, n: PNode): PRope = proc genConstExpr(p: BProc, n: PNode): Rope =
case n.kind case n.kind
of nkHiddenStdConv, nkHiddenSubConv: of nkHiddenStdConv, nkHiddenSubConv:
result = genConstExpr(p, n.sons[1]) result = genConstExpr(p, n.sons[1])

View file

@ -45,29 +45,29 @@ const
] ]
NimMergeEndMark = "/*\tNIM_merge_END:*/" NimMergeEndMark = "/*\tNIM_merge_END:*/"
proc genSectionStart*(fs: TCFileSection): PRope = proc genSectionStart*(fs: TCFileSection): Rope =
if compilationCachePresent: if compilationCachePresent:
result = toRope(tnl) result = rope(tnl)
app(result, "/*\t") add(result, "/*\t")
app(result, CFileSectionNames[fs]) add(result, CFileSectionNames[fs])
app(result, ":*/") add(result, ":*/")
app(result, tnl) add(result, tnl)
proc genSectionEnd*(fs: TCFileSection): PRope = proc genSectionEnd*(fs: TCFileSection): Rope =
if compilationCachePresent: if compilationCachePresent:
result = toRope(NimMergeEndMark & tnl) result = rope(NimMergeEndMark & tnl)
proc genSectionStart*(ps: TCProcSection): PRope = proc genSectionStart*(ps: TCProcSection): Rope =
if compilationCachePresent: if compilationCachePresent:
result = toRope(tnl) result = rope(tnl)
app(result, "/*\t") add(result, "/*\t")
app(result, CProcSectionNames[ps]) add(result, CProcSectionNames[ps])
app(result, ":*/") add(result, ":*/")
app(result, tnl) add(result, tnl)
proc genSectionEnd*(ps: TCProcSection): PRope = proc genSectionEnd*(ps: TCProcSection): Rope =
if compilationCachePresent: if compilationCachePresent:
result = toRope(NimMergeEndMark & tnl) result = rope(NimMergeEndMark & tnl)
proc writeTypeCache(a: TIdTable, s: var string) = proc writeTypeCache(a: TIdTable, s: var string) =
var i = 0 var i = 0
@ -79,7 +79,7 @@ proc writeTypeCache(a: TIdTable, s: var string) =
s.add(' ') s.add(' ')
encodeVInt(id, s) encodeVInt(id, s)
s.add(':') s.add(':')
encodeStr($PRope(value), s) encodeStr($Rope(value), s)
inc i inc i
s.add('}') s.add('}')
@ -95,7 +95,7 @@ proc writeIntSet(a: IntSet, s: var string) =
inc i inc i
s.add('}') s.add('}')
proc genMergeInfo*(m: BModule): PRope = proc genMergeInfo*(m: BModule): Rope =
if optSymbolFiles notin gGlobalOptions: return nil if optSymbolFiles notin gGlobalOptions: return nil
var s = "/*\tNIM_merge_INFO:" var s = "/*\tNIM_merge_INFO:"
s.add(tnl) s.add(tnl)
@ -111,7 +111,7 @@ proc genMergeInfo*(m: BModule): PRope =
encodeVInt(ord(m.frameDeclared), s) encodeVInt(ord(m.frameDeclared), s)
s.add(tnl) s.add(tnl)
s.add("*/") s.add("*/")
result = s.toRope result = s.rope
template `^`(pos: int): expr = L.buf[pos] template `^`(pos: int): expr = L.buf[pos]
@ -145,7 +145,7 @@ proc atEndMark(buf: cstring, pos: int): bool =
while s < NimMergeEndMark.len and buf[pos+s] == NimMergeEndMark[s]: inc s while s < NimMergeEndMark.len and buf[pos+s] == NimMergeEndMark[s]: inc s
result = s == NimMergeEndMark.len result = s == NimMergeEndMark.len
proc readVerbatimSection(L: var TBaseLexer): PRope = proc readVerbatimSection(L: var TBaseLexer): Rope =
var pos = L.bufpos var pos = L.bufpos
var buf = L.buf var buf = L.buf
var r = newStringOfCap(30_000) var r = newStringOfCap(30_000)
@ -169,7 +169,7 @@ proc readVerbatimSection(L: var TBaseLexer): PRope =
r.add(buf[pos]) r.add(buf[pos])
inc pos inc pos
L.bufpos = pos L.bufpos = pos
result = r.toRope result = r.rope
proc readKey(L: var TBaseLexer, result: var string) = proc readKey(L: var TBaseLexer, result: var string) =
var pos = L.bufpos var pos = L.bufpos
@ -197,7 +197,7 @@ proc readTypeCache(L: var TBaseLexer, result: var TIdTable) =
# XXX little hack: we create a "fake" type object with the correct Id # XXX little hack: we create a "fake" type object with the correct Id
# better would be to adapt the data structure to not even store the # better would be to adapt the data structure to not even store the
# object as key, but only the Id # object as key, but only the Id
idTablePut(result, newFakeType(key), value.toRope) idTablePut(result, newFakeType(key), value.rope)
inc L.bufpos inc L.bufpos
proc readIntSet(L: var TBaseLexer, result: var IntSet) = proc readIntSet(L: var TBaseLexer, result: var IntSet) =
@ -293,6 +293,6 @@ proc mergeFiles*(cfilename: string, m: BModule) =
readMergeSections(cfilename, old) readMergeSections(cfilename, old)
# do the merge; old section before new section: # do the merge; old section before new section:
for i in low(TCFileSection)..high(TCFileSection): for i in low(TCFileSection)..high(TCFileSection):
m.s[i] = con(old.f[i], m.s[i]) m.s[i] = old.f[i] & m.s[i]
for i in low(TCProcSection)..high(TCProcSection): for i in low(TCProcSection)..high(TCProcSection):
m.initProc.s(i) = con(old.p[i], m.initProc.s(i)) m.initProc.s(i) = old.p[i] & m.initProc.s(i)

View file

@ -61,11 +61,10 @@ proc genVarTuple(p: BProc, n: PNode) =
initLocalVar(p, v, immediateAsgn=isAssignedImmediately(n[L-1])) initLocalVar(p, v, immediateAsgn=isAssignedImmediately(n[L-1]))
initLoc(field, locExpr, t.sons[i], tup.s) initLoc(field, locExpr, t.sons[i], tup.s)
if t.kind == tyTuple: if t.kind == tyTuple:
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)]) field.r = "$1.Field$2" % [rdLoc(tup), rope(i)]
else: else:
if t.n.sons[i].kind != nkSym: internalError(n.info, "genVarTuple") if t.n.sons[i].kind != nkSym: internalError(n.info, "genVarTuple")
field.r = ropef("$1.$2", field.r = "$1.$2" % [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)]
[rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
putLocIntoDest(p, v.loc, field) putLocIntoDest(p, v.loc, field)
proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false)
@ -86,8 +85,8 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
else: else:
expr(p, ri, a) expr(p, ri, a)
proc startBlock(p: BProc, start: TFormatStr = "{$n", proc startBlock(p: BProc, start: FormatStr = "{$n",
args: varargs[PRope]): int {.discardable.} = args: varargs[Rope]): int {.discardable.} =
lineCg(p, cpsStmts, start, args) lineCg(p, cpsStmts, start, args)
inc(p.labels) inc(p.labels)
result = len(p.blocks) result = len(p.blocks)
@ -96,21 +95,21 @@ proc startBlock(p: BProc, start: TFormatStr = "{$n",
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16 p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
p.blocks[result].nestedExceptStmts = p.inExceptBlock.int16 p.blocks[result].nestedExceptStmts = p.inExceptBlock.int16
proc assignLabel(b: var TBlock): PRope {.inline.} = proc assignLabel(b: var TBlock): Rope {.inline.} =
b.label = con("LA", b.id.toRope) b.label = "LA" & b.id.rope
result = b.label result = b.label
proc blockBody(b: var TBlock): PRope = proc blockBody(b: var TBlock): Rope =
result = b.sections[cpsLocals] result = b.sections[cpsLocals]
if b.frameLen > 0: if b.frameLen > 0:
result.appf("F.len+=$1;$n", b.frameLen.toRope) result.addf("F.len+=$1;$n", [b.frameLen.rope])
result.app(b.sections[cpsInit]) result.add(b.sections[cpsInit])
result.app(b.sections[cpsStmts]) result.add(b.sections[cpsStmts])
proc endBlock(p: BProc, blockEnd: PRope) = proc endBlock(p: BProc, blockEnd: Rope) =
let topBlock = p.blocks.len-1 let topBlock = p.blocks.len-1
# the block is merged into the parent block # the block is merged into the parent block
app(p.blocks[topBlock-1].sections[cpsStmts], p.blocks[topBlock].blockBody) add(p.blocks[topBlock-1].sections[cpsStmts], p.blocks[topBlock].blockBody)
setLen(p.blocks, topBlock) setLen(p.blocks, topBlock)
# this is done after the block is popped so $n is # this is done after the block is popped so $n is
# properly indented when pretty printing is enabled # properly indented when pretty printing is enabled
@ -124,7 +123,7 @@ proc endBlock(p: BProc) =
~"}$n" ~"}$n"
let frameLen = p.blocks[topBlock].frameLen let frameLen = p.blocks[topBlock].frameLen
if frameLen > 0: if frameLen > 0:
blockEnd.appf("F.len-=$1;$n", frameLen.toRope) blockEnd.addf("F.len-=$1;$n", [frameLen.rope])
endBlock(p, blockEnd) endBlock(p, blockEnd)
proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} = proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} =
@ -145,7 +144,7 @@ template preserveBreakIdx(body: stmt): stmt {.immediate.} =
proc genState(p: BProc, n: PNode) = proc genState(p: BProc, n: PNode) =
internalAssert n.len == 1 and n.sons[0].kind == nkIntLit internalAssert n.len == 1 and n.sons[0].kind == nkIntLit
let idx = n.sons[0].intVal let idx = n.sons[0].intVal
linefmt(p, cpsStmts, "STATE$1: ;$n", idx.toRope) linefmt(p, cpsStmts, "STATE$1: ;$n", idx.rope)
proc genGotoState(p: BProc, n: PNode) = proc genGotoState(p: BProc, n: PNode) =
# we resist the temptation to translate it into duff's device as it later # we resist the temptation to translate it into duff's device as it later
@ -159,7 +158,7 @@ proc genGotoState(p: BProc, n: PNode) =
p.beforeRetNeeded = true p.beforeRetNeeded = true
lineF(p, cpsStmts, "case -1: goto BeforeRet;$n", []) lineF(p, cpsStmts, "case -1: goto BeforeRet;$n", [])
for i in 0 .. lastOrd(n.sons[0].typ): for i in 0 .. lastOrd(n.sons[0].typ):
lineF(p, cpsStmts, "case $1: goto STATE$1;$n", [toRope(i)]) lineF(p, cpsStmts, "case $1: goto STATE$1;$n", [rope(i)])
lineF(p, cpsStmts, "}$n", []) lineF(p, cpsStmts, "}$n", [])
proc genBreakState(p: BProc, n: PNode) = proc genBreakState(p: BProc, n: PNode) =
@ -214,17 +213,17 @@ proc genSingleVar(p: BProc, a: PNode) =
var tmp: TLoc var tmp: TLoc
if value.kind in nkCallKinds and value[0].kind == nkSym and if value.kind in nkCallKinds and value[0].kind == nkSym and
sfConstructor in value[0].sym.flags: sfConstructor in value[0].sym.flags:
var params: PRope var params: Rope
let typ = skipTypes(value.sons[0].typ, abstractInst) let typ = skipTypes(value.sons[0].typ, abstractInst)
assert(typ.kind == tyProc) assert(typ.kind == tyProc)
for i in 1.. <value.len: for i in 1.. <value.len:
if params != nil: params.app(~", ") if params != nil: params.add(~", ")
assert(sonsLen(typ) == sonsLen(typ.n)) assert(sonsLen(typ) == sonsLen(typ.n))
app(params, genOtherArg(p, value, i, typ)) add(params, genOtherArg(p, value, i, typ))
lineF(p, cpsStmts, "$#($#);$n", decl, params) lineF(p, cpsStmts, "$#($#);$n", [decl, params])
else: else:
initLocExprSingleUse(p, value, tmp) initLocExprSingleUse(p, value, tmp)
lineF(p, cpsStmts, "$# = $#;$n", decl, tmp.rdLoc) lineF(p, cpsStmts, "$# = $#;$n", [decl, tmp.rdLoc])
return return
assignLocalVar(p, v) assignLocalVar(p, v)
initLocalVar(p, v, imm) initLocalVar(p, v, imm)
@ -298,9 +297,9 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
when not newScopeForIf: startBlock(p) when not newScopeForIf: startBlock(p)
if p.module.compileToCpp: if p.module.compileToCpp:
# avoid "jump to label crosses initialization" error: # avoid "jump to label crosses initialization" error:
app(p.s(cpsStmts), "{") add(p.s(cpsStmts), "{")
expr(p, it.sons[1], d) expr(p, it.sons[1], d)
app(p.s(cpsStmts), "}") add(p.s(cpsStmts), "}")
else: else:
expr(p, it.sons[1], d) expr(p, it.sons[1], d)
endBlock(p) endBlock(p)
@ -389,11 +388,11 @@ proc genComputedGoto(p: BProc; n: PNode) =
localError(n.info, "no case statement found for computed goto"); return localError(n.info, "no case statement found for computed goto"); return
var id = p.labels+1 var id = p.labels+1
inc p.labels, arraySize+1 inc p.labels, arraySize+1
let tmp = ropef("TMP$1", id.toRope) let tmp = "TMP$1" % [id.rope]
var gotoArray = ropef("static void* $#[$#] = {", tmp, arraySize.toRope) var gotoArray = "static void* $#[$#] = {" % [tmp, arraySize.rope]
for i in 1..arraySize-1: for i in 1..arraySize-1:
gotoArray.appf("&&TMP$#, ", (id+i).toRope) gotoArray.addf("&&TMP$#, ", [(id+i).rope])
gotoArray.appf("&&TMP$#};$n", (id+arraySize).toRope) gotoArray.addf("&&TMP$#};$n", [(id+arraySize).rope])
line(p, cpsLocals, gotoArray) line(p, cpsLocals, gotoArray)
let topBlock = p.blocks.len-1 let topBlock = p.blocks.len-1
@ -407,13 +406,13 @@ proc genComputedGoto(p: BProc; n: PNode) =
for j in 0 .. casePos-1: genStmts(p, n.sons[j]) for j in 0 .. casePos-1: genStmts(p, n.sons[j])
let tailA = p.blocks[topBlock].sections[cpsStmts] let tailA = p.blocks[topBlock].sections[cpsStmts]
p.blocks[topBlock].sections[cpsStmts] = oldBody.con(tailA) p.blocks[topBlock].sections[cpsStmts] = oldBody & tailA
let caseStmt = n.sons[casePos] let caseStmt = n.sons[casePos]
var a: TLoc var a: TLoc
initLocExpr(p, caseStmt.sons[0], a) initLocExpr(p, caseStmt.sons[0], a)
# first goto: # first goto:
lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc) lineF(p, cpsStmts, "goto *$#[$#];$n", [tmp, a.rdLoc])
for i in 1 .. <caseStmt.len: for i in 1 .. <caseStmt.len:
startBlock(p) startBlock(p)
@ -423,16 +422,16 @@ proc genComputedGoto(p: BProc; n: PNode) =
localError(it.info, "range notation not available for computed goto") localError(it.info, "range notation not available for computed goto")
return return
let val = getOrdValue(it.sons[j]) let val = getOrdValue(it.sons[j])
lineF(p, cpsStmts, "TMP$#:$n", intLiteral(val+id+1)) lineF(p, cpsStmts, "TMP$#:$n", [intLiteral(val+id+1)])
genStmts(p, it.lastSon) genStmts(p, it.lastSon)
#for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) # tailB #for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) # tailB
#for j in 0 .. casePos-1: genStmts(p, n.sons[j]) # tailA #for j in 0 .. casePos-1: genStmts(p, n.sons[j]) # tailA
app(p.s(cpsStmts), tailB) add(p.s(cpsStmts), tailB)
app(p.s(cpsStmts), tailA) add(p.s(cpsStmts), tailA)
var a: TLoc var a: TLoc
initLocExpr(p, caseStmt.sons[0], a) initLocExpr(p, caseStmt.sons[0], a)
lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc) lineF(p, cpsStmts, "goto *$#[$#];$n", [tmp, a.rdLoc])
endBlock(p) endBlock(p)
proc genWhileStmt(p: BProc, t: PNode) = proc genWhileStmt(p: BProc, t: PNode) =
@ -498,9 +497,9 @@ proc genParForStmt(p: BProc, t: PNode) =
lineF(p, cpsStmts, "#pragma omp parallel for $4$n" & lineF(p, cpsStmts, "#pragma omp parallel for $4$n" &
"for ($1 = $2; $1 <= $3; ++$1)", "for ($1 = $2; $1 <= $3; ++$1)",
forLoopVar.loc.rdLoc, [forLoopVar.loc.rdLoc,
rangeA.rdLoc, rangeB.rdLoc, rangeA.rdLoc, rangeB.rdLoc,
call.sons[3].getStr.toRope) call.sons[3].getStr.rope])
p.breakIdx = startBlock(p) p.breakIdx = startBlock(p)
p.blocks[p.breakIdx].isLoop = true p.blocks[p.breakIdx].isLoop = true
@ -560,7 +559,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
linefmt(p, cpsStmts, "#reraiseException();$n") linefmt(p, cpsStmts, "#reraiseException();$n")
proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
rangeFormat, eqFormat: TFormatStr, labl: TLabel) = rangeFormat, eqFormat: FormatStr, labl: TLabel) =
var var
x, y: TLoc x, y: TLoc
var length = sonsLen(b) var length = sonsLen(b)
@ -578,7 +577,7 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
labId, until: int): TLabel = labId, until: int): TLabel =
var lend = getLabel(p) var lend = getLabel(p)
for i in 1..until: for i in 1..until:
lineF(p, cpsStmts, "LA$1: ;$n", [toRope(labId + i)]) lineF(p, cpsStmts, "LA$1: ;$n", [rope(labId + i)])
if t.sons[i].kind == nkOfBranch: if t.sons[i].kind == nkOfBranch:
var length = sonsLen(t.sons[i]) var length = sonsLen(t.sons[i])
exprBlock(p, t.sons[i].sons[length - 1], d) exprBlock(p, t.sons[i].sons[length - 1], d)
@ -588,7 +587,7 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
result = lend result = lend
proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc, proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
rangeFormat, eqFormat: TFormatStr, rangeFormat, eqFormat: FormatStr,
until: int, a: TLoc): TLabel = until: int, a: TLoc): TLabel =
# generate a C-if statement for a Nim case statement # generate a C-if statement for a Nim case statement
var labId = p.labels var labId = p.labels
@ -596,27 +595,27 @@ proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
inc(p.labels) inc(p.labels)
if t.sons[i].kind == nkOfBranch: # else statement if t.sons[i].kind == nkOfBranch: # else statement
genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat, genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
con("LA", toRope(p.labels))) "LA" & rope(p.labels))
else: else:
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)]) lineF(p, cpsStmts, "goto LA$1;$n", [rope(p.labels)])
if until < t.len-1: if until < t.len-1:
inc(p.labels) inc(p.labels)
var gotoTarget = p.labels var gotoTarget = p.labels
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(gotoTarget)]) lineF(p, cpsStmts, "goto LA$1;$n", [rope(gotoTarget)])
result = genCaseSecondPass(p, t, d, labId, until) result = genCaseSecondPass(p, t, d, labId, until)
lineF(p, cpsStmts, "LA$1: ;$n", [toRope(gotoTarget)]) lineF(p, cpsStmts, "LA$1: ;$n", [rope(gotoTarget)])
else: else:
result = genCaseSecondPass(p, t, d, labId, until) result = genCaseSecondPass(p, t, d, labId, until)
proc genCaseGeneric(p: BProc, t: PNode, d: var TLoc, proc genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
rangeFormat, eqFormat: TFormatStr) = rangeFormat, eqFormat: FormatStr) =
var a: TLoc var a: TLoc
initLocExpr(p, t.sons[0], a) initLocExpr(p, t.sons[0], a)
var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, sonsLen(t)-1, a) var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, sonsLen(t)-1, a)
fixLabel(p, lend) fixLabel(p, lend)
proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel, proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
branches: var openArray[PRope]) = branches: var openArray[Rope]) =
var x: TLoc var x: TLoc
var length = sonsLen(b) var length = sonsLen(b)
for i in countup(0, length - 2): for i in countup(0, length - 2):
@ -634,7 +633,7 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1) if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1)
if strings > stringCaseThreshold: if strings > stringCaseThreshold:
var bitMask = math.nextPowerOfTwo(strings) - 1 var bitMask = math.nextPowerOfTwo(strings) - 1
var branches: seq[PRope] var branches: seq[Rope]
newSeq(branches, bitMask + 1) newSeq(branches, bitMask + 1)
var a: TLoc var a: TLoc
initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto: initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto:
@ -642,21 +641,21 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
for i in countup(1, sonsLen(t) - 1): for i in countup(1, sonsLen(t) - 1):
inc(p.labels) inc(p.labels)
if t.sons[i].kind == nkOfBranch: if t.sons[i].kind == nkOfBranch:
genCaseStringBranch(p, t.sons[i], a, con("LA", toRope(p.labels)), genCaseStringBranch(p, t.sons[i], a, "LA" & rope(p.labels),
branches) branches)
else: else:
# else statement: nothing to do yet # else statement: nothing to do yet
# but we reserved a label, which we use later # but we reserved a label, which we use later
discard discard
linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n", linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
rdLoc(a), toRope(bitMask)) rdLoc(a), rope(bitMask))
for j in countup(0, high(branches)): for j in countup(0, high(branches)):
if branches[j] != nil: if branches[j] != nil:
lineF(p, cpsStmts, "case $1: $n$2break;$n", lineF(p, cpsStmts, "case $1: $n$2break;$n",
[intLiteral(j), branches[j]]) [intLiteral(j), branches[j]])
lineF(p, cpsStmts, "}$n") # else statement: lineF(p, cpsStmts, "}$n", []) # else statement:
if t.sons[sonsLen(t)-1].kind != nkOfBranch: if t.sons[sonsLen(t)-1].kind != nkOfBranch:
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)]) lineF(p, cpsStmts, "goto LA$1;$n", [rope(p.labels)])
# third pass: generate statements # third pass: generate statements
var lend = genCaseSecondPass(p, t, d, labId, sonsLen(t)-1) var lend = genCaseSecondPass(p, t, d, labId, sonsLen(t)-1)
fixLabel(p, lend) fixLabel(p, lend)
@ -718,13 +717,13 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
genCaseRange(p, branch) genCaseRange(p, branch)
else: else:
# else part of case statement: # else part of case statement:
lineF(p, cpsStmts, "default:$n") lineF(p, cpsStmts, "default:$n", [])
hasDefault = true hasDefault = true
exprBlock(p, branch.lastSon, d) exprBlock(p, branch.lastSon, d)
lineF(p, cpsStmts, "break;$n") lineF(p, cpsStmts, "break;$n", [])
if (hasAssume in CC[cCompiler].props) and not hasDefault: if (hasAssume in CC[cCompiler].props) and not hasDefault:
lineF(p, cpsStmts, "default: __assume(0);$n") lineF(p, cpsStmts, "default: __assume(0);$n", [])
lineF(p, cpsStmts, "}$n") lineF(p, cpsStmts, "}$n", [])
if lend != nil: fixLabel(p, lend) if lend != nil: fixLabel(p, lend)
proc genCase(p: BProc, t: PNode, d: var TLoc) = proc genCase(p: BProc, t: PNode, d: var TLoc) =
@ -774,7 +773,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
if not isEmptyType(t.typ) and d.k == locNone: if not isEmptyType(t.typ) and d.k == locNone:
getTemp(p, t.typ, d) getTemp(p, t.typ, d)
var var
exc: PRope exc: Rope
i, length, blen: int i, length, blen: int
genLineDir(p, t) genLineDir(p, t)
exc = getTempName() exc = getTempName()
@ -794,16 +793,16 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
var catchAllPresent = false var catchAllPresent = false
while (i < length) and (t.sons[i].kind == nkExceptBranch): while (i < length) and (t.sons[i].kind == nkExceptBranch):
blen = sonsLen(t.sons[i]) blen = sonsLen(t.sons[i])
if i > 1: appf(p.s(cpsStmts), "else ") if i > 1: addf(p.s(cpsStmts), "else ", [])
if blen == 1: if blen == 1:
# general except section: # general except section:
catchAllPresent = true catchAllPresent = true
exprBlock(p, t.sons[i].sons[0], d) exprBlock(p, t.sons[i].sons[0], d)
else: else:
var orExpr: PRope = nil var orExpr: Rope = nil
for j in countup(0, blen - 2): for j in countup(0, blen - 2):
assert(t.sons[i].sons[j].kind == nkType) assert(t.sons[i].sons[j].kind == nkType)
if orExpr != nil: app(orExpr, "||") if orExpr != nil: add(orExpr, "||")
appcg(p.module, orExpr, appcg(p.module, orExpr,
"#isObj($1.exp->m_type, $2)", "#isObj($1.exp->m_type, $2)",
[exc, genTypeInfo(p.module, t.sons[i].sons[j].typ)]) [exc, genTypeInfo(p.module, t.sons[i].sons[j].typ)])
@ -814,7 +813,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
# reraise the exception if there was no catch all # reraise the exception if there was no catch all
# and none of the handlers matched # and none of the handlers matched
if not catchAllPresent: if not catchAllPresent:
if i > 1: lineF(p, cpsStmts, "else ") if i > 1: lineF(p, cpsStmts, "else ", [])
startBlock(p) startBlock(p)
var finallyBlock = t.lastSon var finallyBlock = t.lastSon
if finallyBlock.kind == nkFinally: if finallyBlock.kind == nkFinally:
@ -824,7 +823,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
line(p, cpsStmts, ~"throw;$n") line(p, cpsStmts, ~"throw;$n")
endBlock(p) endBlock(p)
lineF(p, cpsStmts, "}$n") # end of catch block lineF(p, cpsStmts, "}$n", []) # end of catch block
dec p.inExceptBlock dec p.inExceptBlock
discard pop(p.nestedTryStmts) discard pop(p.nestedTryStmts)
@ -895,17 +894,17 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
var blen = sonsLen(t.sons[i]) var blen = sonsLen(t.sons[i])
if blen == 1: if blen == 1:
# general except section: # general except section:
if i > 1: lineF(p, cpsStmts, "else") if i > 1: lineF(p, cpsStmts, "else", [])
startBlock(p) startBlock(p)
linefmt(p, cpsStmts, "$1.status = 0;$n", safePoint) linefmt(p, cpsStmts, "$1.status = 0;$n", safePoint)
expr(p, t.sons[i].sons[0], d) expr(p, t.sons[i].sons[0], d)
linefmt(p, cpsStmts, "#popCurrentException();$n") linefmt(p, cpsStmts, "#popCurrentException();$n")
endBlock(p) endBlock(p)
else: else:
var orExpr: PRope = nil var orExpr: Rope = nil
for j in countup(0, blen - 2): for j in countup(0, blen - 2):
assert(t.sons[i].sons[j].kind == nkType) assert(t.sons[i].sons[j].kind == nkType)
if orExpr != nil: app(orExpr, "||") if orExpr != nil: add(orExpr, "||")
appcg(p.module, orExpr, appcg(p.module, orExpr,
"#isObj(#getCurrentException()->Sup.m_type, $1)", "#isObj(#getCurrentException()->Sup.m_type, $1)",
[genTypeInfo(p.module, t.sons[i].sons[j].typ)]) [genTypeInfo(p.module, t.sons[i].sons[j].typ)])
@ -925,7 +924,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
discard pop(p.finallySafePoints) discard pop(p.finallySafePoints)
linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", safePoint) linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", safePoint)
proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope = proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
var res = "" var res = ""
for i in countup(0, sonsLen(t) - 1): for i in countup(0, sonsLen(t) - 1):
case t.sons[i].kind case t.sons[i].kind
@ -954,15 +953,15 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope =
if x[j] in {'"', ':'}: if x[j] in {'"', ':'}:
# don't modify the line if already in quotes or # don't modify the line if already in quotes or
# some clobber register list: # some clobber register list:
app(result, x); app(result, tnl) add(result, x); add(result, tnl)
elif x[j] != '\0': elif x[j] != '\0':
# ignore empty lines # ignore empty lines
app(result, "\"") add(result, "\"")
app(result, x) add(result, x)
app(result, "\\n\"\n") add(result, "\\n\"\n")
else: else:
res.add(tnl) res.add(tnl)
result = res.toRope result = res.rope
proc genAsmStmt(p: BProc, t: PNode) = proc genAsmStmt(p: BProc, t: PNode) =
assert(t.kind == nkAsmStmt) assert(t.kind == nkAsmStmt)
@ -973,7 +972,7 @@ proc genAsmStmt(p: BProc, t: PNode) =
# work: # work:
if p.prc == nil: if p.prc == nil:
# top level asm statement? # top level asm statement?
appf(p.module.s[cfsProcHeaders], CC[cCompiler].asmStmtFrmt, [s]) addf(p.module.s[cfsProcHeaders], CC[cCompiler].asmStmtFrmt, [s])
else: else:
lineF(p, cpsStmts, CC[cCompiler].asmStmtFrmt, [s]) lineF(p, cpsStmts, CC[cCompiler].asmStmtFrmt, [s])
@ -982,14 +981,14 @@ proc genEmit(p: BProc, t: PNode) =
if p.prc == nil: if p.prc == nil:
# top level emit pragma? # top level emit pragma?
genCLineDir(p.module.s[cfsProcHeaders], t.info) genCLineDir(p.module.s[cfsProcHeaders], t.info)
app(p.module.s[cfsProcHeaders], s) add(p.module.s[cfsProcHeaders], s)
else: else:
genLineDir(p, t) genLineDir(p, t)
line(p, cpsStmts, s) line(p, cpsStmts, s)
var var
breakPointId: int = 0 breakPointId: int = 0
gBreakpoints: PRope # later the breakpoints are inserted into the main proc gBreakpoints: Rope # later the breakpoints are inserted into the main proc
proc genBreakPoint(p: BProc, t: PNode) = proc genBreakPoint(p: BProc, t: PNode) =
var name: string var name: string
@ -1003,7 +1002,7 @@ proc genBreakPoint(p: BProc, t: PNode) =
genLineDir(p, t) # BUGFIX genLineDir(p, t) # BUGFIX
appcg(p.module, gBreakpoints, appcg(p.module, gBreakpoints,
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [ "#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)), rope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
makeCString(name)]) makeCString(name)])
proc genWatchpoint(p: BProc, n: PNode) = proc genWatchpoint(p: BProc, n: PNode) =

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## Thread var support for crappy architectures that lack native support for ## Thread var support for crappy architectures that lack native support for
## thread local storage. (**Thank you Mac OS X!**) ## thread local storage. (**Thank you Mac OS X!**)
# included from cgen.nim # included from cgen.nim
@ -19,12 +19,12 @@ proc accessThreadLocalVar(p: BProc, s: PSym) =
if emulatedThreadVars() and not p.threadVarAccessed: if emulatedThreadVars() and not p.threadVarAccessed:
p.threadVarAccessed = true p.threadVarAccessed = true
p.module.usesThreadVars = true p.module.usesThreadVars = true
appf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV;$n") addf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV;$n", [])
app(p.procSec(cpsInit), add(p.procSec(cpsInit),
ropecg(p.module, "\tNimTV = (NimThreadVars*) #GetThreadLocalVars();$n")) ropecg(p.module, "\tNimTV = (NimThreadVars*) #GetThreadLocalVars();$n"))
var var
nimtv: PRope # nimrod thread vars; the struct body nimtv: Rope # nimrod thread vars; the struct body
nimtvDeps: seq[PType] = @[] # type deps: every module needs whole struct nimtvDeps: seq[PType] = @[] # type deps: every module needs whole struct
nimtvDeclared = initIntSet() # so that every var/field exists only once nimtvDeclared = initIntSet() # so that every var/field exists only once
# in the struct # in the struct
@ -43,23 +43,23 @@ proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
# allocator for it :-( # allocator for it :-(
if not containsOrIncl(nimtvDeclared, s.id): if not containsOrIncl(nimtvDeclared, s.id):
nimtvDeps.add(s.loc.t) nimtvDeps.add(s.loc.t)
appf(nimtv, "$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.r]) addf(nimtv, "$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.r])
else: else:
if isExtern: app(m.s[cfsVars], "extern ") if isExtern: add(m.s[cfsVars], "extern ")
if optThreads in gGlobalOptions: app(m.s[cfsVars], "NIM_THREADVAR ") if optThreads in gGlobalOptions: add(m.s[cfsVars], "NIM_THREADVAR ")
app(m.s[cfsVars], getTypeDesc(m, s.loc.t)) add(m.s[cfsVars], getTypeDesc(m, s.loc.t))
appf(m.s[cfsVars], " $1;$n", [s.loc.r]) addf(m.s[cfsVars], " $1;$n", [s.loc.r])
proc generateThreadLocalStorage(m: BModule) = proc generateThreadLocalStorage(m: BModule) =
if nimtv != nil and (m.usesThreadVars or sfMainModule in m.module.flags): if nimtv != nil and (m.usesThreadVars or sfMainModule in m.module.flags):
for t in items(nimtvDeps): discard getTypeDesc(m, t) for t in items(nimtvDeps): discard getTypeDesc(m, t)
appf(m.s[cfsSeqTypes], "typedef struct {$1} NimThreadVars;$n", [nimtv]) addf(m.s[cfsSeqTypes], "typedef struct {$1} NimThreadVars;$n", [nimtv])
proc generateThreadVarsSize(m: BModule) = proc generateThreadVarsSize(m: BModule) =
if nimtv != nil: if nimtv != nil:
let externc = if gCmd != cmdCompileToCpp and let externc = if gCmd != cmdCompileToCpp and
sfCompileToCpp in m.module.flags: "extern \"C\"" sfCompileToCpp in m.module.flags: "extern \"C\""
else: "" else: ""
appf(m.s[cfsProcs], addf(m.s[cfsProcs],
"$#NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}$n", "$#NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}$n",
[externc.toRope]) [externc.rope])

View file

@ -17,11 +17,11 @@ type
p: BProc p: BProc
visitorFrmt: string visitorFrmt: string
proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) proc genTraverseProc(c: var TTraversalClosure, accessor: Rope, typ: PType)
proc genCaseRange(p: BProc, branch: PNode) proc genCaseRange(p: BProc, branch: PNode)
proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false)
proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) = proc genTraverseProc(c: var TTraversalClosure, accessor: Rope, n: PNode) =
if n == nil: return if n == nil: return
case n.kind case n.kind
of nkRecList: of nkRecList:
@ -31,31 +31,31 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) =
if (n.sons[0].kind != nkSym): internalError(n.info, "genTraverseProc") if (n.sons[0].kind != nkSym): internalError(n.info, "genTraverseProc")
var p = c.p var p = c.p
let disc = n.sons[0].sym let disc = n.sons[0].sym
lineF(p, cpsStmts, "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): for i in countup(1, sonsLen(n) - 1):
let branch = n.sons[i] let branch = n.sons[i]
assert branch.kind in {nkOfBranch, nkElse} assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch: if branch.kind == nkOfBranch:
genCaseRange(c.p, branch) genCaseRange(c.p, branch)
else: else:
lineF(p, cpsStmts, "default:$n") lineF(p, cpsStmts, "default:$n", [])
genTraverseProc(c, accessor, lastSon(branch)) genTraverseProc(c, accessor, lastSon(branch))
lineF(p, cpsStmts, "break;$n") lineF(p, cpsStmts, "break;$n", [])
lineF(p, cpsStmts, "} $n") lineF(p, cpsStmts, "} $n", [])
of nkSym: of nkSym:
let field = n.sym let field = n.sym
if field.loc.t == nil: if field.loc.t == nil:
internalError(n.info, "genTraverseProc()") internalError(n.info, "genTraverseProc()")
genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t) genTraverseProc(c, "$1.$2" % [accessor, field.loc.r], field.loc.t)
else: internalError(n.info, "genTraverseProc()") else: internalError(n.info, "genTraverseProc()")
proc parentObj(accessor: PRope; m: BModule): PRope {.inline.} = proc parentObj(accessor: Rope; m: BModule): Rope {.inline.} =
if not m.compileToCpp: if not m.compileToCpp:
result = ropef("$1.Sup", accessor) result = "$1.Sup" % [accessor]
else: else:
result = accessor result = accessor
proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) = proc genTraverseProc(c: var TTraversalClosure, accessor: Rope, typ: PType) =
if typ == nil: return if typ == nil: return
var p = c.p var p = c.p
case typ.kind case typ.kind
@ -66,9 +66,9 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
var i: TLoc var i: TLoc
getTemp(p, getSysType(tyInt), i) getTemp(p, getSysType(tyInt), i)
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
i.r, arraySize.toRope) i.r, arraySize.rope)
genTraverseProc(c, rfmt(nil, "$1[$2]", accessor, i.r), typ.sons[1]) genTraverseProc(c, rfmt(nil, "$1[$2]", accessor, i.r), typ.sons[1])
lineF(p, cpsStmts, "}$n") lineF(p, cpsStmts, "}$n", [])
of tyObject: of tyObject:
for i in countup(0, sonsLen(typ) - 1): for i in countup(0, sonsLen(typ) - 1):
genTraverseProc(c, accessor.parentObj(c.p.module), typ.sons[i]) genTraverseProc(c, accessor.parentObj(c.p.module), typ.sons[i])
@ -76,7 +76,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
of tyTuple: of tyTuple:
let typ = getUniqueType(typ) let typ = getUniqueType(typ)
for i in countup(0, sonsLen(typ) - 1): for i in countup(0, sonsLen(typ) - 1):
genTraverseProc(c, rfmt(nil, "$1.Field$2", accessor, i.toRope), typ.sons[i]) genTraverseProc(c, rfmt(nil, "$1.Field$2", accessor, i.rope), typ.sons[i])
of tyRef, tyString, tySequence: of tyRef, tyString, tySequence:
lineCg(p, cpsStmts, c.visitorFrmt, accessor) lineCg(p, cpsStmts, c.visitorFrmt, accessor)
of tyProc: of tyProc:
@ -85,67 +85,67 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
else: else:
discard discard
proc genTraverseProcSeq(c: var TTraversalClosure, accessor: PRope, typ: PType) = proc genTraverseProcSeq(c: var TTraversalClosure, accessor: Rope, typ: PType) =
var p = c.p var p = c.p
assert typ.kind == tySequence assert typ.kind == tySequence
var i: TLoc var i: TLoc
getTemp(p, getSysType(tyInt), i) getTemp(p, getSysType(tyInt), i)
lineF(p, 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 c.p.module.compileToCpp: "len" else: "Sup.len")) [i.r, accessor, rope(if c.p.module.compileToCpp: "len" else: "Sup.len")])
genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0]) genTraverseProc(c, "$1->data[$2]" % [accessor, i.r], typ.sons[0])
lineF(p, cpsStmts, "}$n") lineF(p, cpsStmts, "}$n", [])
proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope = proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): Rope =
var c: TTraversalClosure var c: TTraversalClosure
var p = newProc(nil, m) var p = newProc(nil, m)
result = getGlobalTempName() result = getGlobalTempName()
case reason case reason
of tiNew: c.visitorFrmt = "#nimGCvisit((void*)$1, op);$n" of tiNew: c.visitorFrmt = "#nimGCvisit((void*)$1, op);$n"
else: assert false else: assert false
let header = ropef("N_NIMCALL(void, $1)(void* p, NI op)", result) let header = "N_NIMCALL(void, $1)(void* p, NI op)" % [result]
let t = getTypeDesc(m, typ) let t = getTypeDesc(m, typ)
lineF(p, cpsLocals, "$1 a;$n", t) lineF(p, cpsLocals, "$1 a;$n", [t])
lineF(p, cpsInit, "a = ($1)p;$n", t) lineF(p, cpsInit, "a = ($1)p;$n", [t])
c.p = p c.p = p
assert typ.kind != tyTypeDesc assert typ.kind != tyTypeDesc
if typ.kind == tySequence: if typ.kind == tySequence:
genTraverseProcSeq(c, "a".toRope, typ) genTraverseProcSeq(c, "a".rope, typ)
else: else:
if skipTypes(typ.sons[0], typedescInst).kind in {tyArrayConstr, tyArray}: if skipTypes(typ.sons[0], typedescInst).kind in {tyArrayConstr, tyArray}:
# C's arrays are broken beyond repair: # C's arrays are broken beyond repair:
genTraverseProc(c, "a".toRope, typ.sons[0]) genTraverseProc(c, "a".rope, typ.sons[0])
else: else:
genTraverseProc(c, "(*a)".toRope, typ.sons[0]) genTraverseProc(c, "(*a)".rope, typ.sons[0])
let generatedProc = ropef("$1 {$n$2$3$4}$n",
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)])
m.s[cfsProcHeaders].appf("$1;$n", header)
m.s[cfsProcs].app(generatedProc)
proc genTraverseProcForGlobal(m: BModule, s: PSym): PRope = let generatedProc = "$1 {$n$2$3$4}$n" %
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)]
m.s[cfsProcHeaders].addf("$1;$n", [header])
m.s[cfsProcs].add(generatedProc)
proc genTraverseProcForGlobal(m: BModule, s: PSym): Rope =
discard genTypeInfo(m, s.loc.t) discard genTypeInfo(m, s.loc.t)
var c: TTraversalClosure var c: TTraversalClosure
var p = newProc(nil, m) var p = newProc(nil, m)
var sLoc = s.loc.r var sLoc = s.loc.r
result = getGlobalTempName() result = getGlobalTempName()
if sfThread in s.flags and emulatedThreadVars(): if sfThread in s.flags and emulatedThreadVars():
accessThreadLocalVar(p, s) accessThreadLocalVar(p, s)
sLoc = con("NimTV->", sLoc) sLoc = "NimTV->" & sLoc
c.visitorFrmt = "#nimGCvisit((void*)$1, 0);$n" c.visitorFrmt = "#nimGCvisit((void*)$1, 0);$n"
c.p = p c.p = p
let header = ropef("N_NIMCALL(void, $1)()", result) let header = "N_NIMCALL(void, $1)()" % [result]
genTraverseProc(c, sLoc, s.loc.t) genTraverseProc(c, sLoc, s.loc.t)
let generatedProc = ropef("$1 {$n$2$3$4}$n", let generatedProc = "$1 {$n$2$3$4}$n" %
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)]) [header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)]
m.s[cfsProcHeaders].appf("$1;$n", header) m.s[cfsProcHeaders].addf("$1;$n", [header])
m.s[cfsProcs].app(generatedProc) m.s[cfsProcs].add(generatedProc)

View file

@ -25,7 +25,7 @@ proc isKeyword(w: PIdent): bool =
ord(wInline): return true ord(wInline): return true
else: return false else: return false
proc mangleName(s: PSym): PRope = proc mangleName(s: PSym): Rope =
result = s.loc.r result = s.loc.r
if result == nil: if result == nil:
when oKeepVariableNames: when oKeepVariableNames:
@ -77,27 +77,27 @@ proc mangleName(s: PSym): PRope =
# These are not properly scoped now - we need to add blocks # These are not properly scoped now - we need to add blocks
# around for loops in transf # around for loops in transf
if keepOrigName: if keepOrigName:
result = s.name.s.mangle.toRope result = s.name.s.mangle.rope
else: else:
app(result, toRope(mangle(s.name.s))) add(result, rope(mangle(s.name.s)))
app(result, ~"_") add(result, ~"_")
app(result, toRope(s.id)) add(result, rope(s.id))
else: else:
app(result, toRope(mangle(s.name.s))) add(result, rope(mangle(s.name.s)))
app(result, ~"_") add(result, ~"_")
app(result, toRope(s.id)) add(result, rope(s.id))
s.loc.r = result s.loc.r = result
proc typeName(typ: PType): PRope = proc typeName(typ: PType): Rope =
result = if typ.sym != nil: typ.sym.name.s.mangle.toRope result = if typ.sym != nil: typ.sym.name.s.mangle.rope
else: ~"TY" else: ~"TY"
proc getTypeName(typ: PType): PRope = proc getTypeName(typ: PType): Rope =
if typ.sym != nil and {sfImportc, sfExportc} * typ.sym.flags != {}: if typ.sym != nil and {sfImportc, sfExportc} * typ.sym.flags != {}:
result = typ.sym.loc.r result = typ.sym.loc.r
else: else:
if typ.loc.r == nil: if typ.loc.r == nil:
typ.loc.r = con(typ.typeName, typ.id.toRope) typ.loc.r = typ.typeName & typ.id.rope
result = typ.loc.r result = typ.loc.r
if result == nil: internalError("getTypeName: " & $typ.kind) if result == nil: internalError("getTypeName: " & $typ.kind)
@ -156,7 +156,7 @@ proc isImportedType(t: PType): bool =
proc isImportedCppType(t: PType): bool = proc isImportedCppType(t: PType): bool =
result = t.sym != nil and sfInfixCall in t.sym.flags result = t.sym != nil and sfInfixCall in t.sym.flags
proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope
proc needsComplexAssignment(typ: PType): bool = proc needsComplexAssignment(typ: PType): bool =
result = containsGarbageCollectedRef(typ) result = containsGarbageCollectedRef(typ)
@ -189,17 +189,17 @@ const
# but one can #define it to what one wants # but one can #define it to what one wants
"N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_CLOSURE", "N_NOCONV"] "N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_CLOSURE", "N_NOCONV"]
proc cacheGetType(tab: TIdTable, key: PType): PRope = proc cacheGetType(tab: TIdTable, key: PType): Rope =
# returns nil if we need to declare this type # returns nil if we need to declare this type
# since types are now unique via the ``getUniqueType`` mechanism, this slow # since types are now unique via the ``getUniqueType`` mechanism, this slow
# linear search is not necessary anymore: # linear search is not necessary anymore:
result = PRope(idTableGet(tab, key)) result = Rope(idTableGet(tab, key))
proc getTempName(): PRope = proc getTempName(): Rope =
result = rfmt(nil, "TMP$1", toRope(backendId())) result = rfmt(nil, "TMP$1", rope(backendId()))
proc getGlobalTempName(): PRope = proc getGlobalTempName(): Rope =
result = rfmt(nil, "TMP$1", toRope(backendId())) result = rfmt(nil, "TMP$1", rope(backendId()))
proc ccgIntroducedPtr(s: PSym): bool = proc ccgIntroducedPtr(s: PSym): bool =
var pt = skipTypes(s.typ, typedescInst) var pt = skipTypes(s.typ, typedescInst)
@ -226,13 +226,13 @@ proc fillResult(param: PSym) =
incl(param.loc.flags, lfIndirect) incl(param.loc.flags, lfIndirect)
param.loc.s = OnUnknown param.loc.s = OnUnknown
proc typeNameOrLiteral(t: PType, literal: string): PRope = proc typeNameOrLiteral(t: PType, literal: string): Rope =
if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone: if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone:
result = getTypeName(t) result = getTypeName(t)
else: else:
result = toRope(literal) result = rope(literal)
proc getSimpleTypeDesc(m: BModule, typ: PType): PRope = proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
const const
NumericalTypeToStr: array[tyInt..tyUInt64, string] = [ NumericalTypeToStr: array[tyInt..tyUInt64, string] = [
"NI", "NI8", "NI16", "NI32", "NI64", "NI", "NI8", "NI16", "NI32", "NI64",
@ -268,20 +268,20 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): PRope =
proc pushType(m: BModule, typ: PType) = proc pushType(m: BModule, typ: PType) =
add(m.typeStack, typ) add(m.typeStack, typ)
proc getTypePre(m: BModule, typ: PType): PRope = proc getTypePre(m: BModule, typ: PType): Rope =
if typ == nil: result = toRope("void") if typ == nil: result = rope("void")
else: else:
result = getSimpleTypeDesc(m, typ) result = getSimpleTypeDesc(m, typ)
if result == nil: result = cacheGetType(m.typeCache, typ) if result == nil: result = cacheGetType(m.typeCache, typ)
proc structOrUnion(t: PType): PRope = proc structOrUnion(t: PType): Rope =
(if tfUnion in t.flags: toRope("union") else: toRope("struct")) (if tfUnion in t.flags: rope("union") else: rope("struct"))
proc getForwardStructFormat(m: BModule): string = proc getForwardStructFormat(m: BModule): string =
if m.compileToCpp: result = "$1 $2;$n" if m.compileToCpp: result = "$1 $2;$n"
else: result = "typedef $1 $2 $2;$n" else: result = "typedef $1 $2 $2;$n"
proc getTypeForward(m: BModule, typ: PType): PRope = proc getTypeForward(m: BModule, typ: PType): Rope =
result = cacheGetType(m.forwTypeCache, typ) result = cacheGetType(m.forwTypeCache, typ)
if result != nil: return if result != nil: return
result = getTypePre(m, typ) result = getTypePre(m, typ)
@ -290,12 +290,12 @@ proc getTypeForward(m: BModule, typ: PType): PRope =
of tySequence, tyTuple, tyObject: of tySequence, tyTuple, tyObject:
result = getTypeName(typ) result = getTypeName(typ)
if not isImportedType(typ): if not isImportedType(typ):
appf(m.s[cfsForwardTypes], getForwardStructFormat(m), addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
[structOrUnion(typ), result]) [structOrUnion(typ), result])
idTablePut(m.forwTypeCache, typ, result) idTablePut(m.forwTypeCache, typ, result)
else: internalError("getTypeForward(" & $typ.kind & ')') else: internalError("getTypeForward(" & $typ.kind & ')')
proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): PRope = proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
## like getTypeDescAux but creates only a *weak* dependency. In other words ## like getTypeDescAux but creates only a *weak* dependency. In other words
## we know we only need a pointer to it so we only generate a struct forward ## we know we only need a pointer to it so we only generate a struct forward
## declaration: ## declaration:
@ -310,7 +310,7 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): PRope =
pushType(m, x) pushType(m, x)
of tySequence: of tySequence:
let x = getUniqueType(etB) let x = getUniqueType(etB)
result = getTypeForward(m, x).con("*") result = getTypeForward(m, x) & "*"
pushType(m, x) pushType(m, x)
else: else:
result = getTypeDescAux(m, t, check) result = getTypeDescAux(m, t, check)
@ -321,7 +321,7 @@ proc paramStorageLoc(param: PSym): TStorageLoc =
else: else:
result = OnUnknown result = OnUnknown
proc genProcParams(m: BModule, t: PType, rettype, params: var PRope, proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
check: var IntSet, declareEnvironment=true) = check: var IntSet, declareEnvironment=true) =
params = nil params = nil
if (t.sons[0] == nil) or isInvalidReturnType(t.sons[0]): if (t.sons[0] == nil) or isInvalidReturnType(t.sons[0]):
@ -332,18 +332,18 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var PRope,
if t.n.sons[i].kind != nkSym: internalError(t.n.info, "genProcParams") if t.n.sons[i].kind != nkSym: internalError(t.n.info, "genProcParams")
var param = t.n.sons[i].sym var param = t.n.sons[i].sym
if isCompileTimeOnly(param.typ): continue if isCompileTimeOnly(param.typ): continue
if params != nil: app(params, ~", ") if params != nil: add(params, ~", ")
fillLoc(param.loc, locParam, param.typ, mangleName(param), fillLoc(param.loc, locParam, param.typ, mangleName(param),
param.paramStorageLoc) param.paramStorageLoc)
if ccgIntroducedPtr(param): if ccgIntroducedPtr(param):
app(params, getTypeDescWeak(m, param.typ, check)) add(params, getTypeDescWeak(m, param.typ, check))
app(params, ~"*") add(params, ~"*")
incl(param.loc.flags, lfIndirect) incl(param.loc.flags, lfIndirect)
param.loc.s = OnUnknown param.loc.s = OnUnknown
else: else:
app(params, getTypeDescAux(m, param.typ, check)) add(params, getTypeDescAux(m, param.typ, check))
app(params, ~" ") add(params, ~" ")
app(params, param.loc.r) add(params, param.loc.r)
# declare the len field for open arrays: # declare the len field for open arrays:
var arr = param.typ var arr = param.typ
if arr.kind == tyVar: arr = arr.sons[0] if arr.kind == tyVar: arr = arr.sons[0]
@ -352,78 +352,78 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var PRope,
# this fixes the 'sort' bug: # this fixes the 'sort' bug:
if param.typ.kind == tyVar: param.loc.s = OnUnknown if param.typ.kind == tyVar: param.loc.s = OnUnknown
# need to pass hidden parameter: # need to pass hidden parameter:
appf(params, ", NI $1Len$2", [param.loc.r, j.toRope]) addf(params, ", NI $1Len$2", [param.loc.r, j.rope])
inc(j) inc(j)
arr = arr.sons[0] arr = arr.sons[0]
if (t.sons[0] != nil) and isInvalidReturnType(t.sons[0]): if (t.sons[0] != nil) and isInvalidReturnType(t.sons[0]):
var arr = t.sons[0] var arr = t.sons[0]
if params != nil: app(params, ", ") if params != nil: add(params, ", ")
if (mapReturnType(t.sons[0]) != ctArray): if (mapReturnType(t.sons[0]) != ctArray):
app(params, getTypeDescWeak(m, arr, check)) add(params, getTypeDescWeak(m, arr, check))
app(params, "*") add(params, "*")
else: else:
app(params, getTypeDescAux(m, arr, check)) add(params, getTypeDescAux(m, arr, check))
appf(params, " Result", []) addf(params, " Result", [])
if t.callConv == ccClosure and declareEnvironment: if t.callConv == ccClosure and declareEnvironment:
if params != nil: app(params, ", ") if params != nil: add(params, ", ")
app(params, "void* ClEnv") add(params, "void* ClEnv")
if tfVarargs in t.flags: if tfVarargs in t.flags:
if params != nil: app(params, ", ") if params != nil: add(params, ", ")
app(params, "...") add(params, "...")
if params == nil: app(params, "void)") if params == nil: add(params, "void)")
else: app(params, ")") else: add(params, ")")
params = con("(", params) params = "(" & params
proc mangleRecFieldName(field: PSym, rectype: PType): PRope = proc mangleRecFieldName(field: PSym, rectype: PType): Rope =
if (rectype.sym != nil) and if (rectype.sym != nil) and
({sfImportc, sfExportc} * rectype.sym.flags != {}): ({sfImportc, sfExportc} * rectype.sym.flags != {}):
result = field.loc.r result = field.loc.r
else: else:
result = toRope(mangleField(field.name.s)) result = rope(mangleField(field.name.s))
if result == nil: internalError(field.info, "mangleRecFieldName") if result == nil: internalError(field.info, "mangleRecFieldName")
proc genRecordFieldsAux(m: BModule, n: PNode, proc genRecordFieldsAux(m: BModule, n: PNode,
accessExpr: PRope, rectype: PType, accessExpr: Rope, rectype: PType,
check: var IntSet): PRope = check: var IntSet): Rope =
var var
ae, uname, sname, a: PRope ae, uname, sname, a: Rope
k: PNode k: PNode
field: PSym field: PSym
result = nil result = nil
case n.kind case n.kind
of nkRecList: of nkRecList:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
app(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype, check)) add(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype, check))
of nkRecCase: of nkRecCase:
if n.sons[0].kind != nkSym: internalError(n.info, "genRecordFieldsAux") if n.sons[0].kind != nkSym: internalError(n.info, "genRecordFieldsAux")
app(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check)) add(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check))
uname = toRope(mangle(n.sons[0].sym.name.s) & 'U') uname = rope(mangle(n.sons[0].sym.name.s) & 'U')
if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, uname]) if accessExpr != nil: ae = "$1.$2" % [accessExpr, uname]
else: ae = uname else: ae = uname
var unionBody: PRope = nil var unionBody: Rope = nil
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
case n.sons[i].kind case n.sons[i].kind
of nkOfBranch, nkElse: of nkOfBranch, nkElse:
k = lastSon(n.sons[i]) k = lastSon(n.sons[i])
if k.kind != nkSym: if k.kind != nkSym:
sname = con("S", toRope(i)) sname = "S" & rope(i)
a = genRecordFieldsAux(m, k, ropef("$1.$2", [ae, sname]), rectype, a = genRecordFieldsAux(m, k, "$1.$2" % [ae, sname], rectype,
check) check)
if a != nil: if a != nil:
app(unionBody, "struct {") add(unionBody, "struct {")
app(unionBody, a) add(unionBody, a)
appf(unionBody, "} $1;$n", [sname]) addf(unionBody, "} $1;$n", [sname])
else: else:
app(unionBody, genRecordFieldsAux(m, k, ae, rectype, check)) add(unionBody, genRecordFieldsAux(m, k, ae, rectype, check))
else: internalError("genRecordFieldsAux(record case branch)") else: internalError("genRecordFieldsAux(record case branch)")
if unionBody != nil: if unionBody != nil:
appf(result, "union{$n$1} $2;$n", [unionBody, uname]) addf(result, "union{$n$1} $2;$n", [unionBody, uname])
of nkSym: of nkSym:
field = n.sym field = n.sym
if field.typ.kind == tyEmpty: return if field.typ.kind == tyEmpty: return
#assert(field.ast == nil) #assert(field.ast == nil)
sname = mangleRecFieldName(field, rectype) sname = mangleRecFieldName(field, rectype)
if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, sname]) if accessExpr != nil: ae = "$1.$2" % [accessExpr, sname]
else: ae = sname else: ae = sname
fillLoc(field.loc, locField, field.typ, ae, OnUnknown) fillLoc(field.loc, locField, field.typ, ae, OnUnknown)
# for importcpp'ed objects, we only need to set field.loc, but don't # for importcpp'ed objects, we only need to set field.loc, but don't
@ -432,27 +432,27 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
if not isImportedCppType(rectype): if not isImportedCppType(rectype):
let fieldType = field.loc.t.skipTypes(abstractInst) let fieldType = field.loc.t.skipTypes(abstractInst)
if fieldType.kind == tyArray and tfUncheckedArray in fieldType.flags: if fieldType.kind == tyArray and tfUncheckedArray in fieldType.flags:
appf(result, "$1 $2[SEQ_DECL_SIZE];$n", addf(result, "$1 $2[SEQ_DECL_SIZE];$n",
[getTypeDescAux(m, fieldType.elemType, check), sname]) [getTypeDescAux(m, fieldType.elemType, check), sname])
elif fieldType.kind == tySequence: elif fieldType.kind == tySequence:
# we need to use a weak dependency here for trecursive_table. # we need to use a weak dependency here for trecursive_table.
appf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname]) addf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname])
else: else:
# don't use fieldType here because we need the # don't use fieldType here because we need the
# tyGenericInst for C++ template support # tyGenericInst for C++ template support
appf(result, "$1 $2;$n", [getTypeDescAux(m, field.loc.t, check), sname]) addf(result, "$1 $2;$n", [getTypeDescAux(m, field.loc.t, check), sname])
else: internalError(n.info, "genRecordFieldsAux()") else: internalError(n.info, "genRecordFieldsAux()")
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): PRope = proc getRecordFields(m: BModule, typ: PType, check: var IntSet): Rope =
result = genRecordFieldsAux(m, typ.n, nil, typ, check) result = genRecordFieldsAux(m, typ.n, nil, typ, check)
proc getRecordDesc(m: BModule, typ: PType, name: PRope, proc getRecordDesc(m: BModule, typ: PType, name: Rope,
check: var IntSet): PRope = check: var IntSet): Rope =
# declare the record: # declare the record:
var hasField = false var hasField = false
var attribute: PRope = var attribute: Rope =
if tfPacked in typ.flags: toRope(CC[cCompiler].packedPragma) if tfPacked in typ.flags: rope(CC[cCompiler].packedPragma)
else: nil else: nil
result = ropecg(m, CC[cCompiler].structStmtFmt, result = ropecg(m, CC[cCompiler].structStmtFmt,
@ -475,27 +475,27 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
[getTypeDescAux(m, typ.sons[0], check)]) [getTypeDescAux(m, typ.sons[0], check)])
hasField = true hasField = true
else: else:
appf(result, " {$n", [name]) addf(result, " {$n", [name])
var desc = getRecordFields(m, typ, check) var desc = getRecordFields(m, typ, check)
if desc == nil and not hasField: if desc == nil and not hasField:
appf(result, "char dummy;$n", []) addf(result, "char dummy;$n", [])
else: else:
app(result, desc) add(result, desc)
app(result, "};" & tnl) add(result, "};" & tnl)
proc getTupleDesc(m: BModule, typ: PType, name: PRope, proc getTupleDesc(m: BModule, typ: PType, name: Rope,
check: var IntSet): PRope = check: var IntSet): Rope =
result = ropef("$1 $2 {$n", [structOrUnion(typ), name]) result = "$1 $2 {$n" % [structOrUnion(typ), name]
var desc: PRope = nil var desc: Rope = nil
for i in countup(0, sonsLen(typ) - 1): for i in countup(0, sonsLen(typ) - 1):
appf(desc, "$1 Field$2;$n", addf(desc, "$1 Field$2;$n",
[getTypeDescAux(m, typ.sons[i], check), toRope(i)]) [getTypeDescAux(m, typ.sons[i], check), rope(i)])
if desc == nil: app(result, "char dummy;" & tnl) if desc == nil: add(result, "char dummy;" & tnl)
else: app(result, desc) else: add(result, desc)
app(result, "};" & tnl) add(result, "};" & tnl)
proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): Rope =
# returns only the type's name # returns only the type's name
var t = getUniqueType(typ) var t = getUniqueType(typ)
if t == nil: internalError("getTypeDescAux: t == nil") if t == nil: internalError("getTypeDescAux: t == nil")
@ -523,39 +523,39 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
case etB.kind case etB.kind
of tyObject, tyTuple: of tyObject, tyTuple:
if isImportedCppType(etB) and et.kind == tyGenericInst: if isImportedCppType(etB) and et.kind == tyGenericInst:
result = con(getTypeDescAux(m, et, check), star) result = getTypeDescAux(m, et, check) & star
else: else:
# no restriction! We have a forward declaration for structs # no restriction! We have a forward declaration for structs
let x = getUniqueType(etB) let x = getUniqueType(etB)
let name = getTypeForward(m, x) let name = getTypeForward(m, x)
result = con(name, star) result = name & star
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
pushType(m, x) pushType(m, x)
of tySequence: of tySequence:
# no restriction! We have a forward declaration for structs # no restriction! We have a forward declaration for structs
let x = getUniqueType(etB) let x = getUniqueType(etB)
let name = getTypeForward(m, x) let name = getTypeForward(m, x)
result = con(name, "*" & star) result = name & "*" & star
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
pushType(m, x) pushType(m, x)
else: else:
# else we have a strong dependency :-( # else we have a strong dependency :-(
result = con(getTypeDescAux(m, et, check), star) result = getTypeDescAux(m, et, check) & star
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
of tyOpenArray, tyVarargs: of tyOpenArray, tyVarargs:
result = con(getTypeDescAux(m, t.sons[0], check), "*") result = getTypeDescAux(m, t.sons[0], check) & "*"
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
of tyProc: of tyProc:
result = getTypeName(t) result = getTypeName(t)
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
var rettype, desc: PRope var rettype, desc: Rope
genProcParams(m, t, rettype, desc, check) genProcParams(m, t, rettype, desc, check)
if not isImportedType(t): if not isImportedType(t):
if t.callConv != ccClosure: # procedure vars may need a closure! if t.callConv != ccClosure: # procedure vars may need a closure!
appf(m.s[cfsTypes], "typedef $1_PTR($2, $3) $4;$n", addf(m.s[cfsTypes], "typedef $1_PTR($2, $3) $4;$n",
[toRope(CallingConvToStr[t.callConv]), rettype, result, desc]) [rope(CallingConvToStr[t.callConv]), rettype, result, desc])
else: else:
appf(m.s[cfsTypes], "typedef struct {$n" & addf(m.s[cfsTypes], "typedef struct {$n" &
"N_NIMCALL_PTR($2, ClPrc) $3;$n" & "N_NIMCALL_PTR($2, ClPrc) $3;$n" &
"void* ClEnv;$n} $1;$n", "void* ClEnv;$n} $1;$n",
[result, rettype, desc]) [result, rettype, desc])
@ -566,11 +566,11 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
if result == nil: if result == nil:
result = getTypeName(t) result = getTypeName(t)
if not isImportedType(t): if not isImportedType(t):
appf(m.s[cfsForwardTypes], getForwardStructFormat(m), addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
[structOrUnion(t), result]) [structOrUnion(t), result])
idTablePut(m.forwTypeCache, t, result) idTablePut(m.forwTypeCache, t, result)
assert(cacheGetType(m.typeCache, t) == nil) assert(cacheGetType(m.typeCache, t) == nil)
idTablePut(m.typeCache, t, con(result, "*")) idTablePut(m.typeCache, t, result & "*")
if not isImportedType(t): if not isImportedType(t):
if skipTypes(t.sons[0], typedescInst).kind != tyEmpty: if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
const const
@ -582,8 +582,8 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
" $1 data[SEQ_DECL_SIZE];$n" & " $1 data[SEQ_DECL_SIZE];$n" &
"};$n", [getTypeDescAux(m, t.sons[0], check), result]) "};$n", [getTypeDescAux(m, t.sons[0], check), result])
else: else:
result = toRope("TGenericSeq") result = rope("TGenericSeq")
app(result, "*") add(result, "*")
of tyArrayConstr, tyArray: of tyArrayConstr, tyArray:
var n: BiggestInt = lengthOrd(t) var n: BiggestInt = lengthOrd(t)
if n <= 0: n = 1 # make an array of at least one element if n <= 0: n = 1 # make an array of at least one element
@ -591,17 +591,17 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
if not isImportedType(t): if not isImportedType(t):
let foo = getTypeDescAux(m, t.sons[1], check) let foo = getTypeDescAux(m, t.sons[1], check)
appf(m.s[cfsTypes], "typedef $1 $2[$3];$n", addf(m.s[cfsTypes], "typedef $1 $2[$3];$n",
[foo, result, toRope(n)]) [foo, result, rope(n)])
of tyObject, tyTuple: of tyObject, tyTuple:
if isImportedCppType(t) and typ.kind == tyGenericInst: if isImportedCppType(t) and typ.kind == tyGenericInst:
# for instantiated templates we do not go through the type cache as the # for instantiated templates we do not go through the type cache as the
# the type cache is not aware of 'tyGenericInst'. # the type cache is not aware of 'tyGenericInst'.
result = getTypeName(t).con("<") result = getTypeName(t) & "<"
for i in 1 .. typ.len-2: for i in 1 .. typ.len-2:
if i > 1: result.app(", ") if i > 1: result.add(", ")
result.app(getTypeDescAux(m, typ.sons[i], check)) result.add(getTypeDescAux(m, typ.sons[i], check))
result.app("> ") result.add("> ")
# always call for sideeffects: # always call for sideeffects:
assert t.kind != tyTuple assert t.kind != tyTuple
discard getRecordDesc(m, t, result, check) discard getRecordDesc(m, t, result, check)
@ -610,25 +610,25 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
if result == nil: if result == nil:
result = getTypeName(t) result = getTypeName(t)
if not isImportedType(t): if not isImportedType(t):
appf(m.s[cfsForwardTypes], getForwardStructFormat(m), addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
[structOrUnion(t), result]) [structOrUnion(t), result])
idTablePut(m.forwTypeCache, t, result) idTablePut(m.forwTypeCache, t, result)
idTablePut(m.typeCache, t, result) # always call for sideeffects: idTablePut(m.typeCache, t, result) # always call for sideeffects:
let recdesc = if t.kind != tyTuple: getRecordDesc(m, t, result, check) let recdesc = if t.kind != tyTuple: getRecordDesc(m, t, result, check)
else: getTupleDesc(m, t, result, check) else: getTupleDesc(m, t, result, check)
if not isImportedType(t): app(m.s[cfsTypes], recdesc) if not isImportedType(t): add(m.s[cfsTypes], recdesc)
of tySet: of tySet:
case int(getSize(t)) case int(getSize(t))
of 1: result = toRope("NU8") of 1: result = rope("NU8")
of 2: result = toRope("NU16") of 2: result = rope("NU16")
of 4: result = toRope("NU32") of 4: result = rope("NU32")
of 8: result = toRope("NU64") of 8: result = rope("NU64")
else: else:
result = getTypeName(t) result = getTypeName(t)
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
if not isImportedType(t): if not isImportedType(t):
appf(m.s[cfsTypes], "typedef NU8 $1[$2];$n", addf(m.s[cfsTypes], "typedef NU8 $1[$2];$n",
[result, toRope(getSize(t))]) [result, rope(getSize(t))])
of tyGenericInst, tyDistinct, tyOrdinal, tyConst, tyMutable, of tyGenericInst, tyDistinct, tyOrdinal, tyConst, tyMutable,
tyIter, tyTypeDesc: tyIter, tyTypeDesc:
result = getTypeDescAux(m, lastSon(t), check) result = getTypeDescAux(m, lastSon(t), check)
@ -638,7 +638,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
# fixes bug #145: # fixes bug #145:
excl(check, t.id) excl(check, t.id)
proc getTypeDesc(m: BModule, typ: PType): PRope = proc getTypeDesc(m: BModule, typ: PType): Rope =
var check = initIntSet() var check = initIntSet()
result = getTypeDescAux(m, typ, check) result = getTypeDescAux(m, typ, check)
@ -646,23 +646,23 @@ type
TClosureTypeKind = enum TClosureTypeKind = enum
clHalf, clHalfWithEnv, clFull clHalf, clHalfWithEnv, clFull
proc getClosureType(m: BModule, t: PType, kind: TClosureTypeKind): PRope = proc getClosureType(m: BModule, t: PType, kind: TClosureTypeKind): Rope =
assert t.kind == tyProc assert t.kind == tyProc
var check = initIntSet() var check = initIntSet()
result = getTempName() result = getTempName()
var rettype, desc: PRope var rettype, desc: Rope
genProcParams(m, t, rettype, desc, check, declareEnvironment=kind != clHalf) genProcParams(m, t, rettype, desc, check, declareEnvironment=kind != clHalf)
if not isImportedType(t): if not isImportedType(t):
if t.callConv != ccClosure or kind != clFull: if t.callConv != ccClosure or kind != clFull:
appf(m.s[cfsTypes], "typedef $1_PTR($2, $3) $4;$n", addf(m.s[cfsTypes], "typedef $1_PTR($2, $3) $4;$n",
[toRope(CallingConvToStr[t.callConv]), rettype, result, desc]) [rope(CallingConvToStr[t.callConv]), rettype, result, desc])
else: else:
appf(m.s[cfsTypes], "typedef struct {$n" & addf(m.s[cfsTypes], "typedef struct {$n" &
"N_NIMCALL_PTR($2, ClPrc) $3;$n" & "N_NIMCALL_PTR($2, ClPrc) $3;$n" &
"void* ClEnv;$n} $1;$n", "void* ClEnv;$n} $1;$n",
[result, rettype, desc]) [result, rettype, desc])
proc getTypeDesc(m: BModule, magic: string): PRope = proc getTypeDesc(m: BModule, magic: string): Rope =
var sym = magicsys.getCompilerProc(magic) var sym = magicsys.getCompilerProc(magic)
if sym != nil: if sym != nil:
result = getTypeDesc(m, sym.typ) result = getTypeDesc(m, sym.typ)
@ -678,38 +678,38 @@ proc finishTypeDescriptions(m: BModule) =
template cgDeclFrmt*(s: PSym): string = s.constraint.strVal template cgDeclFrmt*(s: PSym): string = s.constraint.strVal
proc genProcHeader(m: BModule, prc: PSym): PRope = proc genProcHeader(m: BModule, prc: PSym): Rope =
var var
rettype, params: PRope rettype, params: Rope
genCLineDir(result, prc.info) genCLineDir(result, prc.info)
# using static is needed for inline procs # using static is needed for inline procs
if lfExportLib in prc.loc.flags: if lfExportLib in prc.loc.flags:
if m.isHeaderFile: if m.isHeaderFile:
result.app "N_LIB_IMPORT " result.add "N_LIB_IMPORT "
else: else:
result.app "N_LIB_EXPORT " result.add "N_LIB_EXPORT "
elif prc.typ.callConv == ccInline: elif prc.typ.callConv == ccInline:
result.app "static " result.add "static "
var check = initIntSet() var check = initIntSet()
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnUnknown) fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnUnknown)
genProcParams(m, prc.typ, rettype, params, check) genProcParams(m, prc.typ, rettype, params, check)
# careful here! don't access ``prc.ast`` as that could reload large parts of # careful here! don't access ``prc.ast`` as that could reload large parts of
# the object graph! # the object graph!
if prc.constraint.isNil: if prc.constraint.isNil:
appf(result, "$1($2, $3)$4", addf(result, "$1($2, $3)$4",
[toRope(CallingConvToStr[prc.typ.callConv]), rettype, prc.loc.r, [rope(CallingConvToStr[prc.typ.callConv]), rettype, prc.loc.r,
params]) params])
else: else:
result = ropef(prc.cgDeclFrmt, [rettype, prc.loc.r, params]) result = prc.cgDeclFrmt % [rettype, prc.loc.r, params]
# ------------------ type info generation ------------------------------------- # ------------------ type info generation -------------------------------------
proc genTypeInfo(m: BModule, t: PType): PRope proc genTypeInfo(m: BModule, t: PType): Rope
proc getNimNode(m: BModule): PRope = proc getNimNode(m: BModule): Rope =
result = ropef("$1[$2]", [m.typeNodesName, toRope(m.typeNodes)]) result = "$1[$2]" % [m.typeNodesName, rope(m.typeNodes)]
inc(m.typeNodes) inc(m.typeNodes)
proc genTypeInfoAuxBase(m: BModule; typ, origType: PType; name, base: PRope) = proc genTypeInfoAuxBase(m: BModule; typ, origType: PType; name, base: Rope) =
var nimtypeKind: int var nimtypeKind: int
#allocMemTI(m, typ, name) #allocMemTI(m, typ, name)
if isObjLackingTypeField(typ): if isObjLackingTypeField(typ):
@ -717,48 +717,47 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType; name, base: PRope) =
else: else:
nimtypeKind = ord(typ.kind) nimtypeKind = ord(typ.kind)
var size: PRope var size: Rope
if tfIncompleteStruct in typ.flags: size = toRope"void*" if tfIncompleteStruct in typ.flags: size = rope"void*"
elif m.compileToCpp: size = getTypeDesc(m, origType) elif m.compileToCpp: size = getTypeDesc(m, origType)
else: size = getTypeDesc(m, typ) else: size = getTypeDesc(m, typ)
appf(m.s[cfsTypeInit3], addf(m.s[cfsTypeInit3],
"$1.size = sizeof($2);$n" & "$1.kind = $3;$n" & "$1.base = $4;$n", "$1.size = sizeof($2);$n" & "$1.kind = $3;$n" & "$1.base = $4;$n",
[name, size, toRope(nimtypeKind), base]) [name, size, rope(nimtypeKind), base])
# compute type flags for GC optimization # compute type flags for GC optimization
var flags = 0 var flags = 0
if not containsGarbageCollectedRef(typ): flags = flags or 1 if not containsGarbageCollectedRef(typ): flags = flags or 1
if not canFormAcycle(typ): flags = flags or 2 if not canFormAcycle(typ): flags = flags or 2
#else MessageOut("can contain a cycle: " & typeToString(typ)) #else MessageOut("can contain a cycle: " & typeToString(typ))
if flags != 0: if flags != 0:
appf(m.s[cfsTypeInit3], "$1.flags = $2;$n", [name, toRope(flags)]) addf(m.s[cfsTypeInit3], "$1.flags = $2;$n", [name, rope(flags)])
discard cgsym(m, "TNimType") discard cgsym(m, "TNimType")
appf(m.s[cfsVars], "TNimType $1; /* $2 */$n", addf(m.s[cfsVars], "TNimType $1; /* $2 */$n",
[name, toRope(typeToString(typ))]) [name, rope(typeToString(typ))])
proc genTypeInfoAux(m: BModule, typ, origType: PType, name: PRope) = proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope) =
var base: PRope var base: Rope
if (sonsLen(typ) > 0) and (typ.sons[0] != nil): if (sonsLen(typ) > 0) and (typ.sons[0] != nil):
base = genTypeInfo(m, typ.sons[0]) base = genTypeInfo(m, typ.sons[0])
else: else:
base = toRope("0") base = rope("0")
genTypeInfoAuxBase(m, typ, origType, name, base) genTypeInfoAuxBase(m, typ, origType, name, base)
proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope = proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): Rope =
# bugfix: we need to search the type that contains the discriminator: # bugfix: we need to search the type that contains the discriminator:
var objtype = objtype var objtype = objtype
while lookupInRecord(objtype.n, d.name) == nil: while lookupInRecord(objtype.n, d.name) == nil:
objtype = objtype.sons[0] objtype = objtype.sons[0]
if objtype.sym == nil: if objtype.sym == nil:
internalError(d.info, "anonymous obj with discriminator") internalError(d.info, "anonymous obj with discriminator")
result = ropef("NimDT_$1_$2", [ result = "NimDT_$1_$2" % [rope(objtype.id), rope(d.name.s.mangle)]
toRope(objtype.id), toRope(d.name.s.mangle)])
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): PRope = proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): Rope =
discard cgsym(m, "TNimNode") discard cgsym(m, "TNimNode")
var tmp = discriminatorTableName(m, objtype, d) var tmp = discriminatorTableName(m, objtype, d)
result = ropef("TNimNode* $1[$2];$n", [tmp, toRope(lengthOrd(d.typ)+1)]) result = "TNimNode* $1[$2];$n" % [tmp, rope(lengthOrd(d.typ)+1)]
proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) = proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: Rope) =
case n.kind case n.kind
of nkRecList: of nkRecList:
var L = sonsLen(n) var L = sonsLen(n)
@ -766,29 +765,29 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
genObjectFields(m, typ, n.sons[0], expr) genObjectFields(m, typ, n.sons[0], expr)
elif L > 0: elif L > 0:
var tmp = getTempName() var tmp = getTempName()
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, toRope(L)]) addf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, rope(L)])
for i in countup(0, L-1): for i in countup(0, L-1):
var tmp2 = getNimNode(m) var tmp2 = getNimNode(m)
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2]) addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, rope(i), tmp2])
genObjectFields(m, typ, n.sons[i], tmp2) genObjectFields(m, typ, n.sons[i], tmp2)
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n", addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
[expr, toRope(L), tmp]) [expr, rope(L), tmp])
else: else:
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n", [expr, toRope(L)]) addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n", [expr, rope(L)])
of nkRecCase: of nkRecCase:
assert(n.sons[0].kind == nkSym) assert(n.sons[0].kind == nkSym)
var field = n.sons[0].sym var field = n.sons[0].sym
var tmp = discriminatorTableName(m, typ, field) var tmp = discriminatorTableName(m, typ, field)
var L = lengthOrd(field.typ) var L = lengthOrd(field.typ)
assert L > 0 assert L > 0
appf(m.s[cfsTypeInit3], "$1.kind = 3;$n" & addf(m.s[cfsTypeInit3], "$1.kind = 3;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" & "$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
"$1.name = $5;$n" & "$1.sons = &$6[0];$n" & "$1.name = $5;$n" & "$1.sons = &$6[0];$n" &
"$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r, "$1.len = $7;$n", [expr, getTypeDesc(m, typ), field.loc.r,
genTypeInfo(m, field.typ), genTypeInfo(m, field.typ),
makeCString(field.name.s), makeCString(field.name.s),
tmp, toRope(L)]) tmp, rope(L)])
appf(m.s[cfsData], "TNimNode* $1[$2];$n", [tmp, toRope(L+1)]) addf(m.s[cfsData], "TNimNode* $1[$2];$n", [tmp, rope(L+1)])
for i in countup(1, sonsLen(n)-1): for i in countup(1, sonsLen(n)-1):
var b = n.sons[i] # branch var b = n.sons[i] # branch
var tmp2 = getNimNode(m) var tmp2 = getNimNode(m)
@ -802,60 +801,60 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) =
var x = int(getOrdValue(b.sons[j].sons[0])) var x = int(getOrdValue(b.sons[j].sons[0]))
var y = int(getOrdValue(b.sons[j].sons[1])) var y = int(getOrdValue(b.sons[j].sons[1]))
while x <= y: while x <= y:
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(x), tmp2]) addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, rope(x), tmp2])
inc(x) inc(x)
else: else:
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n",
[tmp, toRope(getOrdValue(b.sons[j])), tmp2]) [tmp, rope(getOrdValue(b.sons[j])), tmp2])
of nkElse: of nkElse:
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n",
[tmp, toRope(L), tmp2]) [tmp, rope(L), tmp2])
else: internalError(n.info, "genObjectFields(nkRecCase)") else: internalError(n.info, "genObjectFields(nkRecCase)")
of nkSym: of nkSym:
var field = n.sym var field = n.sym
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" & addf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
"$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" & "$1.offset = offsetof($2, $3);$n" & "$1.typ = $4;$n" &
"$1.name = $5;$n", [expr, getTypeDesc(m, typ), "$1.name = $5;$n", [expr, getTypeDesc(m, typ),
field.loc.r, genTypeInfo(m, field.typ), makeCString(field.name.s)]) field.loc.r, genTypeInfo(m, field.typ), makeCString(field.name.s)])
else: internalError(n.info, "genObjectFields") else: internalError(n.info, "genObjectFields")
proc genObjectInfo(m: BModule, typ, origType: PType, name: PRope) = proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope) =
if typ.kind == tyObject: genTypeInfoAux(m, typ, origType, name) if typ.kind == tyObject: genTypeInfoAux(m, typ, origType, name)
else: genTypeInfoAuxBase(m, typ, origType, name, toRope("0")) else: genTypeInfoAuxBase(m, typ, origType, name, rope("0"))
var tmp = getNimNode(m) var tmp = getNimNode(m)
if not isImportedCppType(typ): if not isImportedCppType(typ):
genObjectFields(m, typ, typ.n, tmp) genObjectFields(m, typ, typ.n, tmp)
appf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp]) addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
var t = typ.sons[0] var t = typ.sons[0]
while t != nil: while t != nil:
t = t.skipTypes(abstractInst) t = t.skipTypes(abstractInst)
t.flags.incl tfObjHasKids t.flags.incl tfObjHasKids
t = t.sons[0] t = t.sons[0]
proc genTupleInfo(m: BModule, typ: PType, name: PRope) = proc genTupleInfo(m: BModule, typ: PType, name: Rope) =
genTypeInfoAuxBase(m, typ, typ, name, toRope("0")) genTypeInfoAuxBase(m, typ, typ, name, rope("0"))
var expr = getNimNode(m) var expr = getNimNode(m)
var length = sonsLen(typ) var length = sonsLen(typ)
if length > 0: if length > 0:
var tmp = getTempName() var tmp = getTempName()
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, toRope(length)]) addf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [tmp, rope(length)])
for i in countup(0, length - 1): for i in countup(0, length - 1):
var a = typ.sons[i] var a = typ.sons[i]
var tmp2 = getNimNode(m) var tmp2 = getNimNode(m)
appf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, toRope(i), tmp2]) addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, rope(i), tmp2])
appf(m.s[cfsTypeInit3], "$1.kind = 1;$n" & addf(m.s[cfsTypeInit3], "$1.kind = 1;$n" &
"$1.offset = offsetof($2, Field$3);$n" & "$1.offset = offsetof($2, Field$3);$n" &
"$1.typ = $4;$n" & "$1.typ = $4;$n" &
"$1.name = \"Field$3\";$n", "$1.name = \"Field$3\";$n",
[tmp2, getTypeDesc(m, typ), toRope(i), genTypeInfo(m, a)]) [tmp2, getTypeDesc(m, typ), rope(i), genTypeInfo(m, a)])
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n", addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n",
[expr, toRope(length), tmp]) [expr, rope(length), tmp])
else: else:
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n", addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n",
[expr, toRope(length)]) [expr, rope(length)])
appf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, expr]) addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, expr])
proc genEnumInfo(m: BModule, typ: PType, name: PRope) = proc genEnumInfo(m: BModule, typ: PType, name: Rope) =
# Type information for enumerations is quite heavy, so we do some # Type information for enumerations is quite heavy, so we do some
# optimizations here: The ``typ`` field is never set, as it is redundant # optimizations here: The ``typ`` field is never set, as it is redundant
# anyway. We generate a cstring array and a loop over it. Exceptional # anyway. We generate a cstring array and a loop over it. Exceptional
@ -863,9 +862,9 @@ proc genEnumInfo(m: BModule, typ: PType, name: PRope) =
genTypeInfoAux(m, typ, typ, name) genTypeInfoAux(m, typ, typ, name)
var nodePtrs = getTempName() var nodePtrs = getTempName()
var length = sonsLen(typ.n) var length = sonsLen(typ.n)
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", addf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n",
[nodePtrs, toRope(length)]) [nodePtrs, rope(length)])
var enumNames, specialCases: PRope var enumNames, specialCases: Rope
var firstNimNode = m.typeNodes var firstNimNode = m.typeNodes
var hasHoles = false var hasHoles = false
for i in countup(0, length - 1): for i in countup(0, length - 1):
@ -874,38 +873,38 @@ proc genEnumInfo(m: BModule, typ: PType, name: PRope) =
var elemNode = getNimNode(m) var elemNode = getNimNode(m)
if field.ast == nil: if field.ast == nil:
# no explicit string literal for the enum field, so use field.name: # no explicit string literal for the enum field, so use field.name:
app(enumNames, makeCString(field.name.s)) add(enumNames, makeCString(field.name.s))
else: else:
app(enumNames, makeCString(field.ast.strVal)) add(enumNames, makeCString(field.ast.strVal))
if i < length - 1: app(enumNames, ", " & tnl) if i < length - 1: add(enumNames, ", " & tnl)
if field.position != i or tfEnumHasHoles in typ.flags: if field.position != i or tfEnumHasHoles in typ.flags:
appf(specialCases, "$1.offset = $2;$n", [elemNode, toRope(field.position)]) addf(specialCases, "$1.offset = $2;$n", [elemNode, rope(field.position)])
hasHoles = true hasHoles = true
var enumArray = getTempName() var enumArray = getTempName()
var counter = getTempName() var counter = getTempName()
appf(m.s[cfsTypeInit1], "NI $1;$n", [counter]) addf(m.s[cfsTypeInit1], "NI $1;$n", [counter])
appf(m.s[cfsTypeInit1], "static char* NIM_CONST $1[$2] = {$n$3};$n", addf(m.s[cfsTypeInit1], "static char* NIM_CONST $1[$2] = {$n$3};$n",
[enumArray, toRope(length), enumNames]) [enumArray, rope(length), enumNames])
appf(m.s[cfsTypeInit3], "for ($1 = 0; $1 < $2; $1++) {$n" & addf(m.s[cfsTypeInit3], "for ($1 = 0; $1 < $2; $1++) {$n" &
"$3[$1+$4].kind = 1;$n" & "$3[$1+$4].offset = $1;$n" & "$3[$1+$4].kind = 1;$n" & "$3[$1+$4].offset = $1;$n" &
"$3[$1+$4].name = $5[$1];$n" & "$6[$1] = &$3[$1+$4];$n" & "}$n", [counter, "$3[$1+$4].name = $5[$1];$n" & "$6[$1] = &$3[$1+$4];$n" & "}$n", [counter,
toRope(length), m.typeNodesName, toRope(firstNimNode), enumArray, nodePtrs]) rope(length), m.typeNodesName, rope(firstNimNode), enumArray, nodePtrs])
app(m.s[cfsTypeInit3], specialCases) add(m.s[cfsTypeInit3], specialCases)
appf(m.s[cfsTypeInit3], addf(m.s[cfsTypeInit3],
"$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4.node = &$1;$n", "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4.node = &$1;$n",
[getNimNode(m), toRope(length), nodePtrs, name]) [getNimNode(m), rope(length), nodePtrs, name])
if hasHoles: if hasHoles:
# 1 << 2 is {ntfEnumHole} # 1 << 2 is {ntfEnumHole}
appf(m.s[cfsTypeInit3], "$1.flags = 1<<2;$n", [name]) addf(m.s[cfsTypeInit3], "$1.flags = 1<<2;$n", [name])
proc genSetInfo(m: BModule, typ: PType, name: PRope) = proc genSetInfo(m: BModule, typ: PType, name: Rope) =
assert(typ.sons[0] != nil) assert(typ.sons[0] != nil)
genTypeInfoAux(m, typ, typ, name) genTypeInfoAux(m, typ, typ, name)
var tmp = getNimNode(m) var tmp = getNimNode(m)
appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 0;$n" & "$3.node = &$1;$n", addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 0;$n" & "$3.node = &$1;$n",
[tmp, toRope(firstOrd(typ)), name]) [tmp, rope(firstOrd(typ)), name])
proc genArrayInfo(m: BModule, typ: PType, name: PRope) = proc genArrayInfo(m: BModule, typ: PType, name: Rope) =
genTypeInfoAuxBase(m, typ, typ, name, genTypeInfo(m, typ.sons[1])) genTypeInfoAuxBase(m, typ, typ, name, genTypeInfo(m, typ.sons[1]))
proc fakeClosureType(owner: PSym): PType = proc fakeClosureType(owner: PSym): PType =
@ -925,17 +924,17 @@ type
include ccgtrav include ccgtrav
proc genDeepCopyProc(m: BModule; s: PSym; result: PRope) = proc genDeepCopyProc(m: BModule; s: PSym; result: Rope) =
genProc(m, s) genProc(m, s)
appf(m.s[cfsTypeInit3], "$1.deepcopy =(void* (N_RAW_NIMCALL*)(void*))$2;$n", addf(m.s[cfsTypeInit3], "$1.deepcopy =(void* (N_RAW_NIMCALL*)(void*))$2;$n",
[result, s.loc.r]) [result, s.loc.r])
proc genTypeInfo(m: BModule, t: PType): PRope = proc genTypeInfo(m: BModule, t: PType): Rope =
let origType = t let origType = t
var t = getUniqueType(t) var t = getUniqueType(t)
result = ropef("NTI$1", [toRope(t.id)]) result = "NTI$1" % [rope(t.id)]
if containsOrIncl(m.typeInfoMarker, t.id): if containsOrIncl(m.typeInfoMarker, t.id):
return con("(&".toRope, result, ")".toRope) return "(&".rope & result & ")".rope
# getUniqueType doesn't skip tyDistinct when that has an overriden operation: # getUniqueType doesn't skip tyDistinct when that has an overriden operation:
while t.kind == tyDistinct: t = t.lastSon while t.kind == tyDistinct: t = t.lastSon
@ -946,23 +945,23 @@ proc genTypeInfo(m: BModule, t: PType): PRope =
# reference the type info as extern here # reference the type info as extern here
discard cgsym(m, "TNimType") discard cgsym(m, "TNimType")
discard cgsym(m, "TNimNode") discard cgsym(m, "TNimNode")
appf(m.s[cfsVars], "extern TNimType $1; /* $2 */$n", addf(m.s[cfsVars], "extern TNimType $1; /* $2 */$n",
[result, toRope(typeToString(t))]) [result, rope(typeToString(t))])
return con("(&".toRope, result, ")".toRope) return "(&".rope & result & ")".rope
case t.kind case t.kind
of tyEmpty: result = toRope"0" of tyEmpty: result = rope"0"
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar: of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar:
genTypeInfoAuxBase(m, t, t, result, toRope"0") genTypeInfoAuxBase(m, t, t, result, rope"0")
of tyProc: of tyProc:
if t.callConv != ccClosure: if t.callConv != ccClosure:
genTypeInfoAuxBase(m, t, t, result, toRope"0") genTypeInfoAuxBase(m, t, t, result, rope"0")
else: else:
genTupleInfo(m, fakeClosureType(t.owner), result) genTupleInfo(m, fakeClosureType(t.owner), result)
of tySequence, tyRef: of tySequence, tyRef:
genTypeInfoAux(m, t, t, result) genTypeInfoAux(m, t, t, result)
if gSelectedGC >= gcMarkAndSweep: if gSelectedGC >= gcMarkAndSweep:
let markerProc = genTraverseProc(m, t, tiNew) let markerProc = genTraverseProc(m, t, tiNew)
appf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc]) addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc])
of tyPtr, tyRange: genTypeInfoAux(m, t, t, result) of tyPtr, tyRange: genTypeInfoAux(m, t, t, result)
of tyArrayConstr, tyArray: genArrayInfo(m, t, result) of tyArrayConstr, tyArray: genArrayInfo(m, t, result)
of tySet: genSetInfo(m, t, result) of tySet: genSetInfo(m, t, result)
@ -979,7 +978,7 @@ proc genTypeInfo(m: BModule, t: PType): PRope =
genDeepCopyProc(m, t.deepCopy, result) genDeepCopyProc(m, t.deepCopy, result)
elif origType.deepCopy != nil: elif origType.deepCopy != nil:
genDeepCopyProc(m, origType.deepCopy, result) genDeepCopyProc(m, origType.deepCopy, result)
result = con("(&".toRope, result, ")".toRope) result = "(&".rope & result & ")".rope
proc genTypeSection(m: BModule, n: PNode) = proc genTypeSection(m: BModule, n: PNode) =
discard discard

View file

@ -193,13 +193,13 @@ proc mangle*(name: string): string =
else: else:
add(result, "HEX" & toHex(ord(c), 2)) add(result, "HEX" & toHex(ord(c), 2))
proc makeLLVMString*(s: string): PRope = proc makeLLVMString*(s: string): Rope =
const MaxLineLength = 64 const MaxLineLength = 64
result = nil result = nil
var res = "c\"" var res = "c\""
for i in countup(0, len(s) - 1): for i in countup(0, len(s) - 1):
if (i + 1) mod MaxLineLength == 0: if (i + 1) mod MaxLineLength == 0:
app(result, toRope(res)) add(result, rope(res))
setLen(res, 0) setLen(res, 0)
case s[i] case s[i]
of '\0'..'\x1F', '\x80'..'\xFF', '\"', '\\': of '\0'..'\x1F', '\x80'..'\xFF', '\"', '\\':
@ -207,6 +207,6 @@ proc makeLLVMString*(s: string): PRope =
add(res, toHex(ord(s[i]), 2)) add(res, toHex(ord(s[i]), 2))
else: add(res, s[i]) else: add(res, s[i])
add(res, "\\00\"") add(res, "\\00\"")
app(result, toRope(res)) add(result, rope(res))
initTypeTables() initTypeTables()

View file

@ -10,13 +10,15 @@
## This module implements the C code generator. ## This module implements the C code generator.
import import
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, ast, astalgo, hashes, trees, platform, magicsys, extccomp,
options, intsets, options, intsets,
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms,
rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings,
semparallel semparallel
import strutils except `%` # collides with ropes.`%`
when options.hasTinyCBackend: when options.hasTinyCBackend:
import tccgen import tccgen
@ -48,7 +50,7 @@ proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) =
result.r = nil result.r = nil
result.flags = {} result.flags = {}
proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) = proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: Rope, s: TStorageLoc) =
# fills the loc if it is not already initialized # fills the loc if it is not already initialized
if a.k == locNone: if a.k == locNone:
a.k = k a.k = k
@ -72,9 +74,9 @@ proc useHeader(m: BModule, sym: PSym) =
assert(sym.annex != nil) assert(sym.annex != nil)
discard lists.includeStr(m.headerFiles, getStr(sym.annex.path)) discard lists.includeStr(m.headerFiles, getStr(sym.annex.path))
proc cgsym(m: BModule, name: string): PRope proc cgsym(m: BModule, name: string): Rope
proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope = proc ropecg(m: BModule, frmt: FormatStr, args: varargs[Rope]): Rope =
var i = 0 var i = 0
var length = len(frmt) var length = len(frmt)
result = nil result = nil
@ -84,11 +86,11 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
inc(i) # skip '$' inc(i) # skip '$'
case frmt[i] case frmt[i]
of '$': of '$':
app(result, "$") add(result, "$")
inc(i) inc(i)
of '#': of '#':
inc(i) inc(i)
app(result, args[num]) add(result, args[num])
inc(num) inc(num)
of '0'..'9': of '0'..'9':
var j = 0 var j = 0
@ -99,12 +101,12 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
num = j num = j
if j > high(args) + 1: if j > high(args) + 1:
internalError("ropes: invalid format string $" & $j) internalError("ropes: invalid format string $" & $j)
app(result, args[j-1]) add(result, args[j-1])
of 'n': of 'n':
if optLineDir notin gOptions: app(result, rnl) if optLineDir notin gOptions: add(result, rnl)
inc(i) inc(i)
of 'N': of 'N':
app(result, rnl) add(result, rnl)
inc(i) inc(i)
else: internalError("ropes: invalid format string $" & frmt[i]) else: internalError("ropes: invalid format string $" & frmt[i])
elif frmt[i] == '#' and frmt[i+1] in IdentStartChars: elif frmt[i] == '#' and frmt[i+1] in IdentStartChars:
@ -113,74 +115,74 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
while frmt[j] in IdentChars: inc(j) while frmt[j] in IdentChars: inc(j)
var ident = substr(frmt, i, j-1) var ident = substr(frmt, i, j-1)
i = j i = j
app(result, cgsym(m, ident)) add(result, cgsym(m, ident))
elif frmt[i] == '#' and frmt[i+1] == '$': elif frmt[i] == '#' and frmt[i+1] == '$':
inc(i, 2) inc(i, 2)
var j = 0 var j = 0
while frmt[i] in Digits: while frmt[i] in Digits:
j = (j * 10) + ord(frmt[i]) - ord('0') j = (j * 10) + ord(frmt[i]) - ord('0')
inc(i) inc(i)
app(result, cgsym(m, $args[j-1])) add(result, cgsym(m, $args[j-1]))
var start = i var start = i
while i < length: while i < length:
if frmt[i] != '$' and frmt[i] != '#': inc(i) if frmt[i] != '$' and frmt[i] != '#': inc(i)
else: break else: break
if i - 1 >= start: if i - 1 >= start:
app(result, substr(frmt, start, i - 1)) add(result, substr(frmt, start, i - 1))
template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr = template rfmt(m: BModule, fmt: string, args: varargs[Rope]): expr =
ropecg(m, fmt, args) ropecg(m, fmt, args)
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, proc appcg(m: BModule, c: var Rope, frmt: FormatStr,
args: varargs[PRope]) = args: varargs[Rope]) =
app(c, ropecg(m, frmt, args)) add(c, ropecg(m, frmt, args))
proc appcg(m: BModule, s: TCFileSection, frmt: TFormatStr, proc appcg(m: BModule, s: TCFileSection, frmt: FormatStr,
args: varargs[PRope]) = args: varargs[Rope]) =
app(m.s[s], ropecg(m, frmt, args)) add(m.s[s], ropecg(m, frmt, args))
proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr, proc appcg(p: BProc, s: TCProcSection, frmt: FormatStr,
args: varargs[PRope]) = args: varargs[Rope]) =
app(p.s(s), ropecg(p.module, frmt, args)) add(p.s(s), ropecg(p.module, frmt, args))
var indent = "\t".toRope var indent = "\t".rope
proc indentLine(p: BProc, r: PRope): PRope = proc indentLine(p: BProc, r: Rope): Rope =
result = r result = r
for i in countup(0, p.blocks.len-1): prepend(result, indent) for i in countup(0, p.blocks.len-1): prepend(result, indent)
proc line(p: BProc, s: TCProcSection, r: PRope) = proc line(p: BProc, s: TCProcSection, r: Rope) =
app(p.s(s), indentLine(p, r)) add(p.s(s), indentLine(p, r))
proc line(p: BProc, s: TCProcSection, r: string) = proc line(p: BProc, s: TCProcSection, r: string) =
app(p.s(s), indentLine(p, r.toRope)) add(p.s(s), indentLine(p, r.rope))
proc lineF(p: BProc, s: TCProcSection, frmt: TFormatStr, proc lineF(p: BProc, s: TCProcSection, frmt: FormatStr,
args: varargs[PRope]) = args: openarray[Rope]) =
app(p.s(s), indentLine(p, ropef(frmt, args))) add(p.s(s), indentLine(p, frmt % args))
proc lineCg(p: BProc, s: TCProcSection, frmt: TFormatStr, proc lineCg(p: BProc, s: TCProcSection, frmt: FormatStr,
args: varargs[PRope]) = args: varargs[Rope]) =
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) add(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
proc linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr, proc linefmt(p: BProc, s: TCProcSection, frmt: FormatStr,
args: varargs[PRope]) = args: varargs[Rope]) =
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) add(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
proc appLineCg(p: BProc, r: var PRope, frmt: TFormatStr, proc appLineCg(p: BProc, r: var Rope, frmt: FormatStr,
args: varargs[PRope]) = args: varargs[Rope]) =
app(r, indentLine(p, ropecg(p.module, frmt, args))) add(r, indentLine(p, ropecg(p.module, frmt, args)))
proc safeLineNm(info: TLineInfo): int = proc safeLineNm(info: TLineInfo): int =
result = toLinenumber(info) result = toLinenumber(info)
if result < 0: result = 0 # negative numbers are not allowed in #line if result < 0: result = 0 # negative numbers are not allowed in #line
proc genCLineDir(r: var PRope, filename: string, line: int) = proc genCLineDir(r: var Rope, filename: string, line: int) =
assert line >= 0 assert line >= 0
if optLineDir in gOptions: if optLineDir in gOptions:
appf(r, "$N#line $2 $1$N", addf(r, "$N#line $2 $1$N",
[toRope(makeSingleLineCString(filename)), toRope(line)]) [rope(makeSingleLineCString(filename)), rope(line)])
proc genCLineDir(r: var PRope, info: TLineInfo) = proc genCLineDir(r: var Rope, info: TLineInfo) =
genCLineDir(r, info.toFullPath, info.safeLineNm) genCLineDir(r, info.toFullPath, info.safeLineNm)
proc freshLineInfo(p: BProc; info: TLineInfo): bool = proc freshLineInfo(p: BProc; info: TLineInfo): bool =
@ -193,22 +195,22 @@ proc freshLineInfo(p: BProc; info: TLineInfo): bool =
proc genLineDir(p: BProc, t: PNode) = proc genLineDir(p: BProc, t: PNode) =
var line = t.info.safeLineNm var line = t.info.safeLineNm
if optEmbedOrigSrc in gGlobalOptions: if optEmbedOrigSrc in gGlobalOptions:
app(p.s(cpsStmts), con(~"//", t.info.sourceLine, rnl)) add(p.s(cpsStmts), ~"//" & t.info.sourceLine & rnl)
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line) genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and
(p.prc == nil or sfPure notin p.prc.flags): (p.prc == nil or sfPure notin p.prc.flags):
if freshLineInfo(p, t.info): if freshLineInfo(p, t.info):
linefmt(p, cpsStmts, "#endb($1, $2);$n", linefmt(p, cpsStmts, "#endb($1, $2);$n",
line.toRope, makeCString(toFilename(t.info))) line.rope, makeCString(toFilename(t.info)))
elif ({optLineTrace, optStackTrace} * p.options == elif ({optLineTrace, optStackTrace} * p.options ==
{optLineTrace, optStackTrace}) and {optLineTrace, optStackTrace}) and
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex >= 0: (p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex >= 0:
if freshLineInfo(p, t.info): if freshLineInfo(p, t.info):
linefmt(p, cpsStmts, "nimln($1, $2);$n", linefmt(p, cpsStmts, "nimln($1, $2);$n",
line.toRope, t.info.quotedFilename) line.rope, t.info.quotedFilename)
proc postStmtActions(p: BProc) {.inline.} = proc postStmtActions(p: BProc) {.inline.} =
app(p.s(cpsStmts), p.module.injectStmt) add(p.s(cpsStmts), p.module.injectStmt)
proc accessThreadLocalVar(p: BProc, s: PSym) proc accessThreadLocalVar(p: BProc, s: PSym)
proc emulatedThreadVars(): bool {.inline.} proc emulatedThreadVars(): bool {.inline.}
@ -221,21 +223,21 @@ include "ccgtypes.nim"
# ------------------------------ Manager of temporaries ------------------ # ------------------------------ Manager of temporaries ------------------
proc rdLoc(a: TLoc): PRope = proc rdLoc(a: TLoc): Rope =
# 'read' location (deref if indirect) # 'read' location (deref if indirect)
result = a.r result = a.r
if lfIndirect in a.flags: result = ropef("(*$1)", [result]) if lfIndirect in a.flags: result = "(*$1)" % [result]
proc addrLoc(a: TLoc): PRope = proc addrLoc(a: TLoc): Rope =
result = a.r result = a.r
if lfIndirect notin a.flags and mapType(a.t) != ctArray: if lfIndirect notin a.flags and mapType(a.t) != ctArray:
result = con("(&", result).con(")") result = "(&" & result & ")"
proc rdCharLoc(a: TLoc): PRope = proc rdCharLoc(a: TLoc): Rope =
# read a location that may need a char-cast: # read a location that may need a char-cast:
result = rdLoc(a) result = rdLoc(a)
if skipTypes(a.t, abstractRange).kind == tyChar: if skipTypes(a.t, abstractRange).kind == tyChar:
result = ropef("((NU8)($1))", [result]) result = "((NU8)($1))" % [result]
proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc, proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
takeAddr: bool) = takeAddr: bool) =
@ -244,11 +246,11 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
discard discard
of frHeader: of frHeader:
var r = rdLoc(a) var r = rdLoc(a)
if not takeAddr: r = ropef("(*$1)", [r]) if not takeAddr: r = "(*$1)" % [r]
var s = skipTypes(t, abstractInst) var s = skipTypes(t, abstractInst)
if not p.module.compileToCpp: if not p.module.compileToCpp:
while (s.kind == tyObject) and (s.sons[0] != nil): while (s.kind == tyObject) and (s.sons[0] != nil):
app(r, ".Sup") add(r, ".Sup")
s = skipTypes(s.sons[0], abstractInst) s = skipTypes(s.sons[0], abstractInst)
linefmt(p, section, "$1.m_type = $2;$n", r, genTypeInfo(p.module, t)) linefmt(p, section, "$1.m_type = $2;$n", r, genTypeInfo(p.module, t))
of frEmbedded: of frEmbedded:
@ -276,7 +278,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
if containsGcRef: if containsGcRef:
var nilLoc: TLoc var nilLoc: TLoc
initLoc(nilLoc, locTemp, loc.t, OnStack) initLoc(nilLoc, locTemp, loc.t, OnStack)
nilLoc.r = toRope("NIM_NIL") nilLoc.r = rope("NIM_NIL")
genRefAssign(p, loc, nilLoc, {afSrcIsNil}) genRefAssign(p, loc, nilLoc, {afSrcIsNil})
else: else:
linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc)) linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc))
@ -325,7 +327,7 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
inc(p.labels) inc(p.labels)
result.r = con("LOC", toRope(p.labels)) result.r = "LOC" & rope(p.labels)
linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r) linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
result.k = locTemp result.k = locTemp
#result.a = - 1 #result.a = - 1
@ -340,9 +342,9 @@ proc keepAlive(p: BProc, toKeepAlive: TLoc) =
# of interior pointers instead # of interior pointers instead
if optRefcGC notin gGlobalOptions: return if optRefcGC notin gGlobalOptions: return
var result: TLoc var result: TLoc
var fid = toRope(p.gcFrameId) var fid = rope(p.gcFrameId)
result.r = con("GCFRAME.F", fid) result.r = "GCFRAME.F" & fid
appf(p.gcFrameType, " $1 F$2;$n", addf(p.gcFrameType, " $1 F$2;$n",
[getTypeDesc(p.module, toKeepAlive.t), fid]) [getTypeDesc(p.module, toKeepAlive.t), fid])
inc(p.gcFrameId) inc(p.gcFrameId)
result.k = locTemp result.k = locTemp
@ -359,10 +361,10 @@ proc keepAlive(p: BProc, toKeepAlive: TLoc) =
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n", "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
addrLoc(result), addrLoc(toKeepAlive), rdLoc(result)) addrLoc(result), addrLoc(toKeepAlive), rdLoc(result))
proc initGCFrame(p: BProc): PRope = proc initGCFrame(p: BProc): Rope =
if p.gcFrameId > 0: result = ropef("struct {$1} GCFRAME;$n", p.gcFrameType) if p.gcFrameId > 0: result = "struct {$1} GCFRAME;$n" % [p.gcFrameType]
proc deinitGCFrame(p: BProc): PRope = proc deinitGCFrame(p: BProc): Rope =
if p.gcFrameId > 0: if p.gcFrameId > 0:
result = ropecg(p.module, result = ropecg(p.module,
"if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n") "if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n")
@ -371,42 +373,42 @@ proc localDebugInfo(p: BProc, s: PSym) =
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
# XXX work around a bug: No type information for open arrays possible: # XXX work around a bug: No type information for open arrays possible:
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
var a = con("&", s.loc.r) var a = "&" & s.loc.r
if s.kind == skParam and ccgIntroducedPtr(s): a = s.loc.r if s.kind == skParam and ccgIntroducedPtr(s): a = s.loc.r
lineF(p, cpsInit, lineF(p, cpsInit,
"F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n", "F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n",
[p.maxFrameLen.toRope, makeCString(normalize(s.name.s)), a, [p.maxFrameLen.rope, makeCString(normalize(s.name.s)), a,
genTypeInfo(p.module, s.loc.t)]) genTypeInfo(p.module, s.loc.t)])
inc(p.maxFrameLen) inc(p.maxFrameLen)
inc p.blocks[p.blocks.len-1].frameLen inc p.blocks[p.blocks.len-1].frameLen
proc localVarDecl(p: BProc; s: PSym): PRope = proc localVarDecl(p: BProc; s: PSym): Rope =
if s.loc.k == locNone: if s.loc.k == locNone:
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack) fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack)
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy) if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
result = getTypeDesc(p.module, s.loc.t) result = getTypeDesc(p.module, s.loc.t)
if s.constraint.isNil: if s.constraint.isNil:
if sfRegister in s.flags: app(result, " register") if sfRegister in s.flags: add(result, " register")
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds: #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
# app(decl, " GC_GUARD") # add(decl, " GC_GUARD")
if sfVolatile in s.flags: app(result, " volatile") if sfVolatile in s.flags: add(result, " volatile")
app(result, " ") add(result, " ")
app(result, s.loc.r) add(result, s.loc.r)
else: else:
result = ropef(s.cgDeclFrmt, result, s.loc.r) result = s.cgDeclFrmt % [result, s.loc.r]
proc assignLocalVar(p: BProc, s: PSym) = proc assignLocalVar(p: BProc, s: PSym) =
#assert(s.loc.k == locNone) # not yet assigned #assert(s.loc.k == locNone) # not yet assigned
# this need not be fulfilled for inline procs; they are regenerated # this need not be fulfilled for inline procs; they are regenerated
# for each module that uses them! # for each module that uses them!
let decl = localVarDecl(p, s).con(";" & tnl) let decl = localVarDecl(p, s) & ";" & tnl
line(p, cpsLocals, decl) line(p, cpsLocals, decl)
localDebugInfo(p, s) localDebugInfo(p, s)
include ccgthreadvars include ccgthreadvars
proc varInDynamicLib(m: BModule, sym: PSym) proc varInDynamicLib(m: BModule, sym: PSym)
proc mangleDynLibProc(sym: PSym): PRope proc mangleDynLibProc(sym: PSym): Rope
proc assignGlobalVar(p: BProc, s: PSym) = proc assignGlobalVar(p: BProc, s: PSym) =
if s.loc.k == locNone: if s.loc.k == locNone:
@ -424,17 +426,17 @@ proc assignGlobalVar(p: BProc, s: PSym) =
if sfThread in s.flags: if sfThread in s.flags:
declareThreadVar(p.module, s, sfImportc in s.flags) declareThreadVar(p.module, s, sfImportc in s.flags)
else: else:
var decl: PRope = nil var decl: Rope = nil
var td = getTypeDesc(p.module, s.loc.t) var td = getTypeDesc(p.module, s.loc.t)
if s.constraint.isNil: if s.constraint.isNil:
if sfImportc in s.flags: app(decl, "extern ") if sfImportc in s.flags: add(decl, "extern ")
app(decl, td) add(decl, td)
if sfRegister in s.flags: app(decl, " register") if sfRegister in s.flags: add(decl, " register")
if sfVolatile in s.flags: app(decl, " volatile") if sfVolatile in s.flags: add(decl, " volatile")
appf(decl, " $1;$n", [s.loc.r]) addf(decl, " $1;$n", [s.loc.r])
else: else:
decl = ropef(s.cgDeclFrmt & ";$n", td, s.loc.r) decl = (s.cgDeclFrmt & ";$n") % [td, s.loc.r]
app(p.module.s[cfsVars], decl) add(p.module.s[cfsVars], decl)
if p.withinLoop > 0: if p.withinLoop > 0:
# fixes tests/run/tzeroarray: # fixes tests/run/tzeroarray:
resetLoc(p, s.loc) resetLoc(p, s.loc)
@ -455,7 +457,7 @@ proc fillProcLoc(sym: PSym) =
proc getLabel(p: BProc): TLabel = proc getLabel(p: BProc): TLabel =
inc(p.labels) inc(p.labels)
result = con("LA", toRope(p.labels)) result = "LA" & rope(p.labels)
proc fixLabel(p: BProc, labl: TLabel) = proc fixLabel(p: BProc, labl: TLabel) =
lineF(p, cpsStmts, "$1: ;$n", [labl]) lineF(p, cpsStmts, "$1: ;$n", [labl])
@ -467,9 +469,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc)
proc genProcPrototype(m: BModule, sym: PSym) proc genProcPrototype(m: BModule, sym: PSym)
proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc)
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
proc intLiteral(i: BiggestInt): PRope proc intLiteral(i: BiggestInt): Rope
proc genLiteral(p: BProc, n: PNode): PRope proc genLiteral(p: BProc, n: PNode): Rope
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): PRope proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) = proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
initLoc(result, locNone, e.typ, OnUnknown) initLoc(result, locNone, e.typ, OnUnknown)
@ -480,8 +482,8 @@ proc initLocExprSingleUse(p: BProc, e: PNode, result: var TLoc) =
result.flags.incl lfSingleUse result.flags.incl lfSingleUse
expr(p, e, result) expr(p, e, result)
proc lenField(p: BProc): PRope = proc lenField(p: BProc): Rope =
result = toRope(if p.module.compileToCpp: "len" else: "Sup.len") result = rope(if p.module.compileToCpp: "len" else: "Sup.len")
include ccgcalls, "ccgstmts.nim", "ccgexprs.nim" include ccgcalls, "ccgstmts.nim", "ccgexprs.nim"
@ -500,16 +502,16 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
var tmp = getGlobalTempName() var tmp = getGlobalTempName()
assert(lib.name == nil) assert(lib.name == nil)
lib.name = tmp # BUGFIX: cgsym has awful side-effects lib.name = tmp # BUGFIX: cgsym has awful side-effects
appf(m.s[cfsVars], "static void* $1;$n", [tmp]) addf(m.s[cfsVars], "static void* $1;$n", [tmp])
if lib.path.kind in {nkStrLit..nkTripleStrLit}: if lib.path.kind in {nkStrLit..nkTripleStrLit}:
var s: TStringSeq = @[] var s: TStringSeq = @[]
libCandidates(lib.path.strVal, s) libCandidates(lib.path.strVal, s)
if gVerbosity >= 2: if gVerbosity >= 2:
msgWriteln("Dependency: " & lib.path.strVal) msgWriteln("Dependency: " & lib.path.strVal)
var loadlib: PRope = nil var loadlib: Rope = nil
for i in countup(0, high(s)): for i in countup(0, high(s)):
inc(m.labels) inc(m.labels)
if i > 0: app(loadlib, "||") if i > 0: add(loadlib, "||")
appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n", appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n",
[tmp, getStrLit(m, s[i])]) [tmp, getStrLit(m, s[i])])
appcg(m, m.s[cfsDynLibInit], appcg(m, m.s[cfsDynLibInit],
@ -520,21 +522,21 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
p.options = p.options - {optStackTrace, optEndb} p.options = p.options - {optStackTrace, optEndb}
var dest: TLoc var dest: TLoc
initLocExpr(p, lib.path, dest) initLocExpr(p, lib.path, dest)
app(m.s[cfsVars], p.s(cpsLocals)) add(m.s[cfsVars], p.s(cpsLocals))
app(m.s[cfsDynLibInit], p.s(cpsInit)) add(m.s[cfsDynLibInit], p.s(cpsInit))
app(m.s[cfsDynLibInit], p.s(cpsStmts)) add(m.s[cfsDynLibInit], p.s(cpsStmts))
appcg(m, m.s[cfsDynLibInit], appcg(m, m.s[cfsDynLibInit],
"if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n", "if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n",
[tmp, rdLoc(dest)]) [tmp, rdLoc(dest)])
if lib.name == nil: internalError("loadDynamicLib") if lib.name == nil: internalError("loadDynamicLib")
proc mangleDynLibProc(sym: PSym): PRope = proc mangleDynLibProc(sym: PSym): Rope =
if sfCompilerProc in sym.flags: if sfCompilerProc in sym.flags:
# NOTE: sym.loc.r is the external name! # NOTE: sym.loc.r is the external name!
result = toRope(sym.name.s) result = rope(sym.name.s)
else: else:
result = ropef("Dl_$1", [toRope(sym.id)]) result = "Dl_$1" % [rope(sym.id)]
proc symInDynamicLib(m: BModule, sym: PSym) = proc symInDynamicLib(m: BModule, sym: PSym) =
var lib = sym.annex var lib = sym.annex
@ -549,28 +551,28 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
let n = lib.path let n = lib.path
var a: TLoc var a: TLoc
initLocExpr(m.initProc, n[0], a) initLocExpr(m.initProc, n[0], a)
var params = con(rdLoc(a), "(") var params = rdLoc(a) & "("
for i in 1 .. n.len-2: for i in 1 .. n.len-2:
initLocExpr(m.initProc, n[i], a) initLocExpr(m.initProc, n[i], a)
params.app(rdLoc(a)) params.add(rdLoc(a))
params.app(", ") params.add(", ")
let load = ropef("\t$1 = ($2) ($3$4));$n", let load = "\t$1 = ($2) ($3$4));$n" %
[tmp, getTypeDesc(m, sym.typ), params, makeCString($extname)]) [tmp, getTypeDesc(m, sym.typ), params, makeCString($extname)]
var last = lastSon(n) var last = lastSon(n)
if last.kind == nkHiddenStdConv: last = last.sons[1] if last.kind == nkHiddenStdConv: last = last.sons[1]
internalAssert(last.kind == nkStrLit) internalAssert(last.kind == nkStrLit)
let idx = last.strVal let idx = last.strVal
if idx.len == 0: if idx.len == 0:
app(m.initProc.s(cpsStmts), load) add(m.initProc.s(cpsStmts), load)
elif idx.len == 1 and idx[0] in {'0'..'9'}: elif idx.len == 1 and idx[0] in {'0'..'9'}:
app(m.extensionLoaders[idx[0]], load) add(m.extensionLoaders[idx[0]], load)
else: else:
internalError(sym.info, "wrong index: " & idx) internalError(sym.info, "wrong index: " & idx)
else: else:
appcg(m, m.s[cfsDynLibInit], appcg(m, m.s[cfsDynLibInit],
"\t$1 = ($2) #nimGetProcAddr($3, $4);$n", "\t$1 = ($2) #nimGetProcAddr($3, $4);$n",
[tmp, getTypeDesc(m, sym.typ), lib.name, makeCString($extname)]) [tmp, getTypeDesc(m, sym.typ), lib.name, makeCString($extname)])
appf(m.s[cfsVars], "$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t)]) addf(m.s[cfsVars], "$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t)])
proc varInDynamicLib(m: BModule, sym: PSym) = proc varInDynamicLib(m: BModule, sym: PSym) =
var lib = sym.annex var lib = sym.annex
@ -583,14 +585,14 @@ proc varInDynamicLib(m: BModule, sym: PSym) =
appcg(m, m.s[cfsDynLibInit], appcg(m, m.s[cfsDynLibInit],
"$1 = ($2*) #nimGetProcAddr($3, $4);$n", "$1 = ($2*) #nimGetProcAddr($3, $4);$n",
[tmp, getTypeDesc(m, sym.typ), lib.name, makeCString($extname)]) [tmp, getTypeDesc(m, sym.typ), lib.name, makeCString($extname)])
appf(m.s[cfsVars], "$2* $1;$n", addf(m.s[cfsVars], "$2* $1;$n",
[sym.loc.r, getTypeDesc(m, sym.loc.t)]) [sym.loc.r, getTypeDesc(m, sym.loc.t)])
proc symInDynamicLibPartial(m: BModule, sym: PSym) = proc symInDynamicLibPartial(m: BModule, sym: PSym) =
sym.loc.r = mangleDynLibProc(sym) sym.loc.r = mangleDynLibProc(sym)
sym.typ.sym = nil # generate a new name sym.typ.sym = nil # generate a new name
proc cgsym(m: BModule, name: string): PRope = proc cgsym(m: BModule, name: string): Rope =
var sym = magicsys.getCompilerProc(name) var sym = magicsys.getCompilerProc(name)
if sym != nil: if sym != nil:
case sym.kind case sym.kind
@ -606,29 +608,29 @@ proc cgsym(m: BModule, name: string): PRope =
result = sym.loc.r result = sym.loc.r
proc generateHeaders(m: BModule) = proc generateHeaders(m: BModule) =
app(m.s[cfsHeaders], tnl & "#include \"nimbase.h\"" & tnl) add(m.s[cfsHeaders], tnl & "#include \"nimbase.h\"" & tnl)
var it = PStrEntry(m.headerFiles.head) var it = PStrEntry(m.headerFiles.head)
while it != nil: while it != nil:
if it.data[0] notin {'\"', '<'}: if it.data[0] notin {'\"', '<'}:
appf(m.s[cfsHeaders], "$N#include \"$1\"$N", [toRope(it.data)]) addf(m.s[cfsHeaders], "$N#include \"$1\"$N", [rope(it.data)])
else: else:
appf(m.s[cfsHeaders], "$N#include $1$N", [toRope(it.data)]) addf(m.s[cfsHeaders], "$N#include $1$N", [rope(it.data)])
it = PStrEntry(it.next) it = PStrEntry(it.next)
proc retIsNotVoid(s: PSym): bool = proc retIsNotVoid(s: PSym): bool =
result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0]) result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0])
proc initFrame(p: BProc, procname, filename: PRope): PRope = proc initFrame(p: BProc, procname, filename: Rope): Rope =
discard cgsym(p.module, "nimFrame") discard cgsym(p.module, "nimFrame")
if p.maxFrameLen > 0: if p.maxFrameLen > 0:
discard cgsym(p.module, "TVarSlot") discard cgsym(p.module, "TVarSlot")
result = rfmt(nil, "\tnimfrs($1, $2, $3, $4)$N", result = rfmt(nil, "\tnimfrs($1, $2, $3, $4)$N",
procname, filename, p.maxFrameLen.toRope, procname, filename, p.maxFrameLen.rope,
p.blocks[0].frameLen.toRope) p.blocks[0].frameLen.rope)
else: else:
result = rfmt(nil, "\tnimfr($1, $2)$N", procname, filename) result = rfmt(nil, "\tnimfr($1, $2)$N", procname, filename)
proc deinitFrame(p: BProc): PRope = proc deinitFrame(p: BProc): Rope =
result = rfmt(p.module, "\t#popFrame();$n") result = rfmt(p.module, "\t#popFrame();$n")
proc closureSetup(p: BProc, prc: PSym) = proc closureSetup(p: BProc, prc: PSym) =
@ -647,7 +649,7 @@ proc closureSetup(p: BProc, prc: PSym) =
proc genProcAux(m: BModule, prc: PSym) = proc genProcAux(m: BModule, prc: PSym) =
var p = newProc(prc, m) var p = newProc(prc, m)
var header = genProcHeader(m, prc) var header = genProcHeader(m, prc)
var returnStmt: PRope = nil var returnStmt: Rope = nil
assert(prc.ast != nil) assert(prc.ast != nil)
if sfPure notin prc.flags and prc.typ.sons[0] != nil: if sfPure notin prc.flags and prc.typ.sons[0] != nil:
if resultPos >= prc.ast.len: if resultPos >= prc.ast.len:
@ -673,33 +675,33 @@ proc genProcAux(m: BModule, prc: PSym) =
assignParam(p, param) assignParam(p, param)
closureSetup(p, prc) closureSetup(p, prc)
genStmts(p, prc.getBody) # modifies p.locals, p.init, etc. genStmts(p, prc.getBody) # modifies p.locals, p.init, etc.
var generatedProc: PRope var generatedProc: Rope
if sfPure in prc.flags: if sfPure in prc.flags:
if hasNakedDeclspec in extccomp.CC[extccomp.cCompiler].props: if hasNakedDeclspec in extccomp.CC[extccomp.cCompiler].props:
header = con("__declspec(naked) ", header) header = "__declspec(naked) " & header
generatedProc = rfmt(nil, "$N$1 {$n$2$3$4}$N$N", generatedProc = rfmt(nil, "$N$1 {$n$2$3$4}$N$N",
header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)) header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts))
else: else:
generatedProc = rfmt(nil, "$N$1 {$N", header) generatedProc = rfmt(nil, "$N$1 {$N", header)
app(generatedProc, initGCFrame(p)) add(generatedProc, initGCFrame(p))
if optStackTrace in prc.options: if optStackTrace in prc.options:
app(generatedProc, p.s(cpsLocals)) add(generatedProc, p.s(cpsLocals))
var procname = makeCString(prc.name.s) var procname = makeCString(prc.name.s)
app(generatedProc, initFrame(p, procname, prc.info.quotedFilename)) add(generatedProc, initFrame(p, procname, prc.info.quotedFilename))
else: else:
app(generatedProc, p.s(cpsLocals)) add(generatedProc, p.s(cpsLocals))
if optProfiler in prc.options: if optProfiler in prc.options:
# invoke at proc entry for recursion: # invoke at proc entry for recursion:
appcg(p, cpsInit, "\t#nimProfile();$n", []) appcg(p, cpsInit, "\t#nimProfile();$n", [])
if p.beforeRetNeeded: app(generatedProc, "{") if p.beforeRetNeeded: add(generatedProc, "{")
app(generatedProc, p.s(cpsInit)) add(generatedProc, p.s(cpsInit))
app(generatedProc, p.s(cpsStmts)) add(generatedProc, p.s(cpsStmts))
if p.beforeRetNeeded: app(generatedProc, ~"\t}BeforeRet: ;$n") if p.beforeRetNeeded: add(generatedProc, ~"\t}BeforeRet: ;$n")
app(generatedProc, deinitGCFrame(p)) add(generatedProc, deinitGCFrame(p))
if optStackTrace in prc.options: app(generatedProc, deinitFrame(p)) if optStackTrace in prc.options: add(generatedProc, deinitFrame(p))
app(generatedProc, returnStmt) add(generatedProc, returnStmt)
app(generatedProc, ~"}$N") add(generatedProc, ~"}$N")
app(m.s[cfsProcs], generatedProc) add(m.s[cfsProcs], generatedProc)
proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} = proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} =
result = sfCompileToCpp in m.module.flags and result = sfCompileToCpp in m.module.flags and
@ -712,15 +714,15 @@ proc genProcPrototype(m: BModule, sym: PSym) =
if lfDynamicLib in sym.loc.flags: if lfDynamicLib in sym.loc.flags:
if getModule(sym).id != m.module.id and if getModule(sym).id != m.module.id and
not containsOrIncl(m.declaredThings, sym.id): not containsOrIncl(m.declaredThings, sym.id):
app(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n", add(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n",
getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym))) getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)))
elif not containsOrIncl(m.declaredProtos, sym.id): elif not containsOrIncl(m.declaredProtos, sym.id):
var header = genProcHeader(m, sym) var header = genProcHeader(m, sym)
if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym): if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym):
header = con("extern \"C\" ", header) header = "extern \"C\" " & header
if sfPure in sym.flags and hasNakedAttribute in CC[cCompiler].props: if sfPure in sym.flags and hasNakedAttribute in CC[cCompiler].props:
header.app(" __attribute__((naked))") header.add(" __attribute__((naked))")
app(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header)) add(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header))
proc genProcNoForward(m: BModule, prc: PSym) = proc genProcNoForward(m: BModule, prc: PSym) =
fillProcLoc(prc) fillProcLoc(prc)
@ -757,16 +759,16 @@ proc requestConstImpl(p: BProc, sym: PSym) =
var q = findPendingModule(m, sym) var q = findPendingModule(m, sym)
if q != nil and not containsOrIncl(q.declaredThings, sym.id): if q != nil and not containsOrIncl(q.declaredThings, sym.id):
assert q.initProc.module == q assert q.initProc.module == q
appf(q.s[cfsData], "NIM_CONST $1 $2 = $3;$n", addf(q.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(q, sym.typ), sym.loc.r, genConstExpr(q.initProc, sym.ast)]) [getTypeDesc(q, sym.typ), sym.loc.r, genConstExpr(q.initProc, sym.ast)])
# declare header: # declare header:
if q != m and not containsOrIncl(m.declaredThings, sym.id): if q != m and not containsOrIncl(m.declaredThings, sym.id):
assert(sym.loc.r != nil) assert(sym.loc.r != nil)
let headerDecl = ropef("extern NIM_CONST $1 $2;$n", let headerDecl = "extern NIM_CONST $1 $2;$n" %
[getTypeDesc(m, sym.loc.t), sym.loc.r]) [getTypeDesc(m, sym.loc.t), sym.loc.r]
app(m.s[cfsData], headerDecl) add(m.s[cfsData], headerDecl)
if sfExportc in sym.flags and generatedHeader != nil: if sfExportc in sym.flags and generatedHeader != nil:
app(generatedHeader.s[cfsData], headerDecl) add(generatedHeader.s[cfsData], headerDecl)
proc isActivated(prc: PSym): bool = prc.typ != nil proc isActivated(prc: PSym): bool = prc.typ != nil
@ -795,47 +797,47 @@ proc genVarPrototypeAux(m: BModule, sym: PSym) =
if sfThread in sym.flags: if sfThread in sym.flags:
declareThreadVar(m, sym, true) declareThreadVar(m, sym, true)
else: else:
app(m.s[cfsVars], "extern ") add(m.s[cfsVars], "extern ")
app(m.s[cfsVars], getTypeDesc(m, sym.loc.t)) add(m.s[cfsVars], getTypeDesc(m, sym.loc.t))
if lfDynamicLib in sym.loc.flags: app(m.s[cfsVars], "*") if lfDynamicLib in sym.loc.flags: add(m.s[cfsVars], "*")
if sfRegister in sym.flags: app(m.s[cfsVars], " register") if sfRegister in sym.flags: add(m.s[cfsVars], " register")
if sfVolatile in sym.flags: app(m.s[cfsVars], " volatile") if sfVolatile in sym.flags: add(m.s[cfsVars], " volatile")
appf(m.s[cfsVars], " $1;$n", [sym.loc.r]) addf(m.s[cfsVars], " $1;$n", [sym.loc.r])
proc genVarPrototype(m: BModule, sym: PSym) = proc genVarPrototype(m: BModule, sym: PSym) =
genVarPrototypeAux(m, sym) genVarPrototypeAux(m, sym)
proc addIntTypes(result: var PRope) {.inline.} = proc addIntTypes(result: var Rope) {.inline.} =
appf(result, "#define NIM_INTBITS $1", [ addf(result, "#define NIM_INTBITS $1", [
platform.CPU[targetCPU].intSize.toRope]) platform.CPU[targetCPU].intSize.rope])
proc getCopyright(cfile: string): PRope = proc getCopyright(cfile: string): Rope =
if optCompileOnly in gGlobalOptions: if optCompileOnly in gGlobalOptions:
result = ropef("/* Generated by Nim Compiler v$1 */$N" & result = ("/* Generated by Nim Compiler v$1 */$N" &
"/* (c) 2015 Andreas Rumpf */$N" & "/* (c) 2015 Andreas Rumpf */$N" &
"/* The generated code is subject to the original license. */$N", "/* The generated code is subject to the original license. */$N") %
[toRope(VersionAsString)]) [rope(VersionAsString)]
else: else:
result = ropef("/* Generated by Nim Compiler v$1 */$N" & result = ("/* Generated by Nim Compiler v$1 */$N" &
"/* (c) 2015 Andreas Rumpf */$N" & "/* (c) 2015 Andreas Rumpf */$N" &
"/* The generated code is subject to the original license. */$N" & "/* The generated code is subject to the original license. */$N" &
"/* Compiled for: $2, $3, $4 */$N" & "/* Compiled for: $2, $3, $4 */$N" &
"/* Command for C compiler:$n $5 */$N", "/* Command for C compiler:$n $5 */$N") %
[toRope(VersionAsString), [rope(VersionAsString),
toRope(platform.OS[targetOS].name), rope(platform.OS[targetOS].name),
toRope(platform.CPU[targetCPU].name), rope(platform.CPU[targetCPU].name),
toRope(extccomp.CC[extccomp.cCompiler].name), rope(extccomp.CC[extccomp.cCompiler].name),
toRope(getCompileCFileCmd(cfile))]) rope(getCompileCFileCmd(cfile))]
proc getFileHeader(cfile: string): PRope = proc getFileHeader(cfile: string): Rope =
result = getCopyright(cfile) result = getCopyright(cfile)
addIntTypes(result) addIntTypes(result)
proc genFilenames(m: BModule): PRope = proc genFilenames(m: BModule): Rope =
discard cgsym(m, "dbgRegisterFilename") discard cgsym(m, "dbgRegisterFilename")
result = nil result = nil
for i in 0.. <fileInfos.len: for i in 0.. <fileInfos.len:
result.appf("dbgRegisterFilename($1);$N", fileInfos[i].projPath.makeCString) result.addf("dbgRegisterFilename($1);$N", [fileInfos[i].projPath.makeCString])
proc genMainProc(m: BModule) = proc genMainProc(m: BModule) =
const const
@ -917,7 +919,7 @@ proc genMainProc(m: BModule) =
MainProcs & MainProcs &
"}$N$N" "}$N$N"
var nimMain, otherMain: TFormatStr var nimMain, otherMain: FormatStr
if platform.targetOS == osWindows and if platform.targetOS == osWindows and
gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}: gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}:
if optGenGuiApp in gGlobalOptions: if optGenGuiApp in gGlobalOptions:
@ -938,10 +940,10 @@ proc genMainProc(m: BModule) =
otherMain = PosixCMain otherMain = PosixCMain
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint") if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
if optEndb in gOptions: if optEndb in gOptions:
gBreakpoints.app(m.genFilenames) gBreakpoints.add(m.genFilenames)
let initStackBottomCall = let initStackBottomCall =
if platform.targetOS == osStandalone: "".toRope if platform.targetOS == osStandalone: "".rope
else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N") else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N")
inc(m.labels) inc(m.labels)
appcg(m, m.s[cfsProcs], PreMainBody, [ appcg(m, m.s[cfsProcs], PreMainBody, [
@ -949,56 +951,56 @@ proc genMainProc(m: BModule) =
if emulatedThreadVars() and platform.targetOS != osStandalone: if emulatedThreadVars() and platform.targetOS != osStandalone:
ropecg(m, "\t#initThreadVarsEmulation();$N") ropecg(m, "\t#initThreadVarsEmulation();$N")
else: else:
"".toRope, "".rope,
initStackBottomCall]) initStackBottomCall])
appcg(m, m.s[cfsProcs], nimMain, [mainModInit, initStackBottomCall, toRope(m.labels)]) appcg(m, m.s[cfsProcs], nimMain, [mainModInit, initStackBottomCall, rope(m.labels)])
if optNoMain notin gGlobalOptions: if optNoMain notin gGlobalOptions:
appcg(m, m.s[cfsProcs], otherMain, []) appcg(m, m.s[cfsProcs], otherMain, [])
proc getSomeInitName(m: PSym, suffix: string): PRope = proc getSomeInitName(m: PSym, suffix: string): Rope =
assert m.kind == skModule assert m.kind == skModule
assert m.owner.kind == skPackage assert m.owner.kind == skPackage
if {sfSystemModule, sfMainModule} * m.flags == {}: if {sfSystemModule, sfMainModule} * m.flags == {}:
result = m.owner.name.s.mangle.toRope result = m.owner.name.s.mangle.rope
result.app "_" result.add "_"
result.app m.name.s result.add m.name.s
result.app suffix result.add suffix
proc getInitName(m: PSym): PRope = getSomeInitName(m, "Init") proc getInitName(m: PSym): Rope = getSomeInitName(m, "Init")
proc getDatInitName(m: PSym): PRope = getSomeInitName(m, "DatInit") proc getDatInitName(m: PSym): Rope = getSomeInitName(m, "DatInit")
proc registerModuleToMain(m: PSym) = proc registerModuleToMain(m: PSym) =
var var
init = m.getInitName init = m.getInitName
datInit = m.getDatInitName datInit = m.getDatInitName
appf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [init]) addf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [init])
appf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [datInit]) addf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [datInit])
if sfSystemModule notin m.flags: if sfSystemModule notin m.flags:
appf(mainDatInit, "\t$1();$N", [datInit]) addf(mainDatInit, "\t$1();$N", [datInit])
let initCall = ropef("\t$1();$N", [init]) let initCall = "\t$1();$N" % [init]
if sfMainModule in m.flags: if sfMainModule in m.flags:
app(mainModInit, initCall) add(mainModInit, initCall)
else: else:
app(otherModsInit, initCall) add(otherModsInit, initCall)
proc genInitCode(m: BModule) = proc genInitCode(m: BModule) =
var initname = getInitName(m.module) var initname = getInitName(m.module)
var prc = ropef("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", [initname]) var prc = "NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N" % [initname]
if m.typeNodes > 0: if m.typeNodes > 0:
appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n",
[m.typeNodesName, toRope(m.typeNodes)]) [m.typeNodesName, rope(m.typeNodes)])
if m.nimTypes > 0: if m.nimTypes > 0:
appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n", appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n",
[m.nimTypesName, toRope(m.nimTypes)]) [m.nimTypesName, rope(m.nimTypes)])
app(prc, initGCFrame(m.initProc)) add(prc, initGCFrame(m.initProc))
app(prc, genSectionStart(cpsLocals)) add(prc, genSectionStart(cpsLocals))
app(prc, m.preInitProc.s(cpsLocals)) add(prc, m.preInitProc.s(cpsLocals))
app(prc, m.initProc.s(cpsLocals)) add(prc, m.initProc.s(cpsLocals))
app(prc, m.postInitProc.s(cpsLocals)) add(prc, m.postInitProc.s(cpsLocals))
app(prc, genSectionEnd(cpsLocals)) add(prc, genSectionEnd(cpsLocals))
if optStackTrace in m.initProc.options and not m.frameDeclared: if optStackTrace in m.initProc.options and not m.frameDeclared:
# BUT: the generated init code might depend on a current frame, so # BUT: the generated init code might depend on a current frame, so
@ -1006,58 +1008,58 @@ proc genInitCode(m: BModule) =
m.frameDeclared = true m.frameDeclared = true
if not m.preventStackTrace: if not m.preventStackTrace:
var procname = makeCString(m.module.name.s) var procname = makeCString(m.module.name.s)
app(prc, initFrame(m.initProc, procname, m.module.info.quotedFilename)) add(prc, initFrame(m.initProc, procname, m.module.info.quotedFilename))
else: else:
app(prc, ~"\tTFrame F; F.len = 0;$N") add(prc, ~"\tTFrame F; F.len = 0;$N")
app(prc, genSectionStart(cpsInit)) add(prc, genSectionStart(cpsInit))
app(prc, m.preInitProc.s(cpsInit)) add(prc, m.preInitProc.s(cpsInit))
app(prc, m.initProc.s(cpsInit)) add(prc, m.initProc.s(cpsInit))
app(prc, m.postInitProc.s(cpsInit)) add(prc, m.postInitProc.s(cpsInit))
app(prc, genSectionEnd(cpsInit)) add(prc, genSectionEnd(cpsInit))
app(prc, genSectionStart(cpsStmts)) add(prc, genSectionStart(cpsStmts))
app(prc, m.preInitProc.s(cpsStmts)) add(prc, m.preInitProc.s(cpsStmts))
app(prc, m.initProc.s(cpsStmts)) add(prc, m.initProc.s(cpsStmts))
app(prc, m.postInitProc.s(cpsStmts)) add(prc, m.postInitProc.s(cpsStmts))
app(prc, genSectionEnd(cpsStmts)) add(prc, genSectionEnd(cpsStmts))
if optStackTrace in m.initProc.options and not m.preventStackTrace: if optStackTrace in m.initProc.options and not m.preventStackTrace:
app(prc, deinitFrame(m.initProc)) add(prc, deinitFrame(m.initProc))
app(prc, deinitGCFrame(m.initProc)) add(prc, deinitGCFrame(m.initProc))
appf(prc, "}$N$N") addf(prc, "}$N$N", [])
prc.appf("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", prc.addf("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N",
[getDatInitName(m.module)]) [getDatInitName(m.module)])
for i in cfsTypeInit1..cfsDynLibInit: for i in cfsTypeInit1..cfsDynLibInit:
app(prc, genSectionStart(i)) add(prc, genSectionStart(i))
app(prc, m.s[i]) add(prc, m.s[i])
app(prc, genSectionEnd(i)) add(prc, genSectionEnd(i))
appf(prc, "}$N$N") addf(prc, "}$N$N", [])
# we cannot simply add the init proc to ``m.s[cfsProcs]`` anymore because # we cannot simply add the init proc to ``m.s[cfsProcs]`` anymore because
# that would lead to a *nesting* of merge sections which the merger does # that would lead to a *nesting* of merge sections which the merger does
# not support. So we add it to another special section: ``cfsInitProc`` # not support. So we add it to another special section: ``cfsInitProc``
app(m.s[cfsInitProc], prc) add(m.s[cfsInitProc], prc)
for i, el in pairs(m.extensionLoaders): for i, el in pairs(m.extensionLoaders):
if el != nil: if el != nil:
let ex = ropef("N_NIMCALL(void, nimLoadProcs$1)(void) {$2}$N$N", let ex = "N_NIMCALL(void, nimLoadProcs$1)(void) {$2}$N$N" %
(i.ord - '0'.ord).toRope, el) [(i.ord - '0'.ord).rope, el]
app(m.s[cfsInitProc], ex) add(m.s[cfsInitProc], ex)
proc genModule(m: BModule, cfile: string): PRope = proc genModule(m: BModule, cfile: string): Rope =
result = getFileHeader(cfile) result = getFileHeader(cfile)
result.app(genMergeInfo(m)) result.add(genMergeInfo(m))
generateHeaders(m) generateHeaders(m)
generateThreadLocalStorage(m) generateThreadLocalStorage(m)
for i in countup(cfsHeaders, cfsProcs): for i in countup(cfsHeaders, cfsProcs):
app(result, genSectionStart(i)) add(result, genSectionStart(i))
app(result, m.s[i]) add(result, m.s[i])
app(result, genSectionEnd(i)) add(result, genSectionEnd(i))
app(result, m.s[cfsInitProc]) add(result, m.s[cfsInitProc])
proc newPreInitProc(m: BModule): BProc = proc newPreInitProc(m: BModule): BProc =
result = newProc(nil, m) result = newProc(nil, m)
@ -1169,22 +1171,22 @@ proc myOpen(module: PSym): PPassContext =
proc writeHeader(m: BModule) = proc writeHeader(m: BModule) =
var result = getCopyright(m.filename) var result = getCopyright(m.filename)
var guard = ropef("__$1__", m.filename.splitFile.name.toRope) var guard = "__$1__" % [m.filename.splitFile.name.rope]
result.appf("#ifndef $1$n#define $1$n", guard) result.addf("#ifndef $1$n#define $1$n", [guard])
addIntTypes(result) addIntTypes(result)
generateHeaders(m) generateHeaders(m)
generateThreadLocalStorage(m) generateThreadLocalStorage(m)
for i in countup(cfsHeaders, cfsProcs): for i in countup(cfsHeaders, cfsProcs):
app(result, genSectionStart(i)) add(result, genSectionStart(i))
app(result, m.s[i]) add(result, m.s[i])
app(result, genSectionEnd(i)) add(result, genSectionEnd(i))
app(result, m.s[cfsInitProc]) add(result, m.s[cfsInitProc])
if optGenDynLib in gGlobalOptions: if optGenDynLib in gGlobalOptions:
result.app("N_LIB_IMPORT ") result.add("N_LIB_IMPORT ")
result.appf("N_CDECL(void, NimMain)(void);$n") result.addf("N_CDECL(void, NimMain)(void);$n", [])
result.appf("#endif /* $1 */$n", guard) result.addf("#endif /* $1 */$n", [guard])
writeRope(result, m.filename) writeRope(result, m.filename)
proc getCFile(m: BModule): string = proc getCFile(m: BModule): string =
@ -1221,7 +1223,7 @@ proc finishModule(m: BModule) =
dec(gForwardedProcsCounter, i) dec(gForwardedProcsCounter, i)
setLen(m.forwardedProcs, 0) setLen(m.forwardedProcs, 0)
proc shouldRecompile(code: PRope, cfile: string): bool = proc shouldRecompile(code: Rope, cfile: string): bool =
result = true result = true
if optForceFullMake notin gGlobalOptions: if optForceFullMake notin gGlobalOptions:
var objFile = toObjFile(cfile) var objFile = toObjFile(cfile)
@ -1246,7 +1248,7 @@ proc writeModule(m: BModule, pending: bool) =
finishTypeDescriptions(m) finishTypeDescriptions(m)
if sfMainModule in m.module.flags: if sfMainModule in m.module.flags:
# generate main file: # generate main file:
app(m.s[cfsProcHeaders], mainModProcs) add(m.s[cfsProcHeaders], mainModProcs)
generateThreadVarsSize(m) generateThreadVarsSize(m)
var code = genModule(m, cfile) var code = genModule(m, cfile)

View file

@ -15,7 +15,7 @@ import
from msgs import TLineInfo from msgs import TLineInfo
type type
TLabel* = PRope # for the C generator a label is just a rope TLabel* = Rope # for the C generator a label is just a rope
TCFileSection* = enum # the sections a generated C file consists of TCFileSection* = enum # the sections a generated C file consists of
cfsMergeInfo, # section containing merge information cfsMergeInfo, # section containing merge information
cfsHeaders, # section for C include file headers cfsHeaders, # section for C include file headers
@ -45,17 +45,17 @@ type
ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64, ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
ctArray, ctPtrToArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc, ctArray, ctPtrToArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc,
ctCString ctCString
TCFileSections* = array[TCFileSection, PRope] # represents a generated C file TCFileSections* = array[TCFileSection, Rope] # represents a generated C file
TCProcSection* = enum # the sections a generated C proc consists of TCProcSection* = enum # the sections a generated C proc consists of
cpsLocals, # section of local variables for C proc cpsLocals, # section of local variables for C proc
cpsInit, # section for init of variables for C proc cpsInit, # section for init of variables for C proc
cpsStmts # section of local statements for C proc cpsStmts # section of local statements for C proc
TCProcSections* = array[TCProcSection, PRope] # represents a generated C proc TCProcSections* = array[TCProcSection, Rope] # represents a generated C proc
BModule* = ref TCGen BModule* = ref TCGen
BProc* = ref TCProc BProc* = ref TCProc
TBlock*{.final.} = object TBlock*{.final.} = object
id*: int # the ID of the label; positive means that it id*: int # the ID of the label; positive means that it
label*: PRope # generated text for the label label*: Rope # generated text for the label
# nil if label is not used # nil if label is not used
sections*: TCProcSections # the code beloging sections*: TCProcSections # the code beloging
isLoop*: bool # whether block is a loop isLoop*: bool # whether block is a loop
@ -73,7 +73,7 @@ type
inExceptBlock*: int # are we currently inside an except block? inExceptBlock*: int # are we currently inside an except block?
# leaving such scopes by raise or by return must # leaving such scopes by raise or by return must
# execute any applicable finally blocks # execute any applicable finally blocks
finallySafePoints*: seq[PRope] # For correctly cleaning up exceptions when finallySafePoints*: seq[Rope] # For correctly cleaning up exceptions when
# using return in finally statements # using return in finally statements
labels*: Natural # for generating unique labels in the C proc labels*: Natural # for generating unique labels in the C proc
blocks*: seq[TBlock] # nested blocks blocks*: seq[TBlock] # nested blocks
@ -89,7 +89,7 @@ type
# requires 'T x = T()' to become 'T x; x = T()' # requires 'T x = T()' to become 'T x; x = T()'
# (yes, C++ is weird like that) # (yes, C++ is weird like that)
gcFrameId*: Natural # for the GC stack marking gcFrameId*: Natural # for the GC stack marking
gcFrameType*: PRope # the struct {} we put the GC markers into gcFrameType*: Rope # the struct {} we put the GC markers into
TTypeSeq* = seq[PType] TTypeSeq* = seq[PType]
TCGen = object of TPassContext # represents a C source file TCGen = object of TPassContext # represents a C source file
@ -118,24 +118,24 @@ type
dataCache*: TNodeTable dataCache*: TNodeTable
forwardedProcs*: TSymSeq # keep forwarded procs here forwardedProcs*: TSymSeq # keep forwarded procs here
typeNodes*, nimTypes*: int # used for type info generation typeNodes*, nimTypes*: int # used for type info generation
typeNodesName*, nimTypesName*: PRope # used for type info generation typeNodesName*, nimTypesName*: Rope # used for type info generation
labels*: Natural # for generating unique module-scope names labels*: Natural # for generating unique module-scope names
extensionLoaders*: array['0'..'9', PRope] # special procs for the extensionLoaders*: array['0'..'9', Rope] # special procs for the
# OpenGL wrapper # OpenGL wrapper
injectStmt*: PRope injectStmt*: Rope
var var
mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: PRope mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope
# varuious parts of the main module # varuious parts of the main module
gMapping*: PRope # the generated mapping file (if requested) gMapping*: Rope # the generated mapping file (if requested)
gModules*: seq[BModule] = @[] # list of all compiled modules gModules*: seq[BModule] = @[] # list of all compiled modules
gForwardedProcsCounter*: int = 0 gForwardedProcsCounter*: int = 0
proc s*(p: BProc, s: TCProcSection): var PRope {.inline.} = proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} =
# section in the current block # section in the current block
result = p.blocks[p.blocks.len - 1].sections[s] result = p.blocks[p.blocks.len - 1].sections[s]
proc procSec*(p: BProc, s: TCProcSection): var PRope {.inline.} = proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} =
# top level proc sections # top level proc sections
result = p.blocks[0].sections[s] result = p.blocks[0].sections[s]

View file

@ -9,41 +9,41 @@
# This module implements a dependency file generator. # This module implements a dependency file generator.
import import
os, options, ast, astalgo, msgs, ropes, idents, passes, importer os, options, ast, astalgo, msgs, ropes, idents, passes, importer
proc generateDot*(project: string) proc generateDot*(project: string)
type type
TGen = object of TPassContext TGen = object of TPassContext
module*: PSym module*: PSym
PGen = ref TGen PGen = ref TGen
var gDotGraph: PRope # the generated DOT file; we need a global variable var gDotGraph: Rope # the generated DOT file; we need a global variable
proc addDependencyAux(importing, imported: string) = proc addDependencyAux(importing, imported: string) =
appf(gDotGraph, "$1 -> $2;$n", [toRope(importing), toRope(imported)]) addf(gDotGraph, "$1 -> $2;$n", [rope(importing), rope(imported)])
# s1 -> s2_4[label="[0-9]"]; # s1 -> s2_4[label="[0-9]"];
proc addDotDependency(c: PPassContext, n: PNode): PNode = proc addDotDependency(c: PPassContext, n: PNode): PNode =
result = n result = n
var g = PGen(c) var g = PGen(c)
case n.kind case n.kind
of nkImportStmt: of nkImportStmt:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var imported = getModuleName(n.sons[i]) var imported = getModuleName(n.sons[i])
addDependencyAux(g.module.name.s, imported) addDependencyAux(g.module.name.s, imported)
of nkFromStmt, nkImportExceptStmt: of nkFromStmt, nkImportExceptStmt:
var imported = getModuleName(n.sons[0]) var imported = getModuleName(n.sons[0])
addDependencyAux(g.module.name.s, imported) addDependencyAux(g.module.name.s, imported)
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i]) for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i])
else: else:
discard discard
proc generateDot(project: string) = proc generateDot(project: string) =
writeRope(ropef("digraph $1 {$n$2}$n", [ writeRope("digraph $1 {$n$2}$n" % [
toRope(changeFileExt(extractFilename(project), "")), gDotGraph]), rope(changeFileExt(extractFilename(project), "")), gDotGraph],
changeFileExt(project, "dot")) changeFileExt(project, "dot"))
proc myOpen(module: PSym): PPassContext = proc myOpen(module: PSym): PPassContext =

View file

@ -17,9 +17,9 @@ import
importer, sempass2, json, xmltree, cgi, typesrenderer importer, sempass2, json, xmltree, cgi, typesrenderer
type type
TSections = array[TSymKind, PRope] TSections = array[TSymKind, Rope]
TDocumentor = object of rstgen.TRstGenerator TDocumentor = object of rstgen.TRstGenerator
modDesc: PRope # module description modDesc: Rope # module description
id: int # for generating IDs id: int # for generating IDs
toc, section: TSections toc, section: TSections
indexValFilename: string indexValFilename: string
@ -82,9 +82,9 @@ proc newDocumentor*(filename: string, config: StringTableRef): PDoc =
result.seenSymbols = newStringTable(modeCaseInsensitive) result.seenSymbols = newStringTable(modeCaseInsensitive)
result.id = 100 result.id = 100
proc dispA(dest: var PRope, xml, tex: string, args: openArray[PRope]) = proc dispA(dest: var Rope, xml, tex: string, args: openArray[Rope]) =
if gCmd != cmdRst2tex: appf(dest, xml, args) if gCmd != cmdRst2tex: addf(dest, xml, args)
else: appf(dest, tex, args) else: addf(dest, tex, args)
proc getVarIdx(varnames: openArray[string], id: string): int = proc getVarIdx(varnames: openArray[string], id: string): int =
for i in countup(0, high(varnames)): for i in countup(0, high(varnames)):
@ -92,8 +92,8 @@ proc getVarIdx(varnames: openArray[string], id: string): int =
return i return i
result = -1 result = -1
proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openArray[string], proc ropeFormatNamedVars(frmt: FormatStr, varnames: openArray[string],
varvalues: openArray[PRope]): PRope = varvalues: openArray[Rope]): Rope =
var i = 0 var i = 0
var L = len(frmt) var L = len(frmt)
result = nil result = nil
@ -103,11 +103,11 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openArray[string],
inc(i) # skip '$' inc(i) # skip '$'
case frmt[i] case frmt[i]
of '#': of '#':
app(result, varvalues[num]) add(result, varvalues[num])
inc(num) inc(num)
inc(i) inc(i)
of '$': of '$':
app(result, "$") add(result, "$")
inc(i) inc(i)
of '0'..'9': of '0'..'9':
var j = 0 var j = 0
@ -117,7 +117,7 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openArray[string],
if (i > L + 0 - 1) or not (frmt[i] in {'0'..'9'}): break if (i > L + 0 - 1) or not (frmt[i] in {'0'..'9'}): break
if j > high(varvalues) + 1: internalError("ropeFormatNamedVars") if j > high(varvalues) + 1: internalError("ropeFormatNamedVars")
num = j num = j
app(result, varvalues[j - 1]) add(result, varvalues[j - 1])
of 'A'..'Z', 'a'..'z', '\x80'..'\xFF': of 'A'..'Z', 'a'..'z', '\x80'..'\xFF':
var id = "" var id = ""
while true: while true:
@ -125,7 +125,7 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openArray[string],
inc(i) inc(i)
if not (frmt[i] in {'A'..'Z', '_', 'a'..'z', '\x80'..'\xFF'}): break if not (frmt[i] in {'A'..'Z', '_', 'a'..'z', '\x80'..'\xFF'}): break
var idx = getVarIdx(varnames, id) var idx = getVarIdx(varnames, id)
if idx >= 0: app(result, varvalues[idx]) if idx >= 0: add(result, varvalues[idx])
else: rawMessage(errUnknownSubstitionVar, id) else: rawMessage(errUnknownSubstitionVar, id)
of '{': of '{':
var id = "" var id = ""
@ -137,14 +137,14 @@ proc ropeFormatNamedVars(frmt: TFormatStr, varnames: openArray[string],
inc(i) # skip } inc(i) # skip }
# search for the variable: # search for the variable:
var idx = getVarIdx(varnames, id) var idx = getVarIdx(varnames, id)
if idx >= 0: app(result, varvalues[idx]) if idx >= 0: add(result, varvalues[idx])
else: rawMessage(errUnknownSubstitionVar, id) else: rawMessage(errUnknownSubstitionVar, id)
else: internalError("ropeFormatNamedVars") else: internalError("ropeFormatNamedVars")
var start = i var start = i
while i < L: while i < L:
if frmt[i] != '$': inc(i) if frmt[i] != '$': inc(i)
else: break else: break
if i - 1 >= start: app(result, substr(frmt, start, i - 1)) if i - 1 >= start: add(result, substr(frmt, start, i - 1))
proc genComment(d: PDoc, n: PNode): string = proc genComment(d: PDoc, n: PNode): string =
result = "" result = ""
@ -154,9 +154,9 @@ proc genComment(d: PDoc, n: PNode): string =
toLinenumber(n.info), toColumn(n.info), toLinenumber(n.info), toColumn(n.info),
dummyHasToc, d.options + {roSkipPounds}), result) dummyHasToc, d.options + {roSkipPounds}), result)
proc genRecComment(d: PDoc, n: PNode): PRope = proc genRecComment(d: PDoc, n: PNode): Rope =
if n == nil: return nil if n == nil: return nil
result = genComment(d, n).toRope result = genComment(d, n).rope
if result == nil: if result == nil:
if n.kind notin {nkEmpty..nkNilLit}: if n.kind notin {nkEmpty..nkNilLit}:
for i in countup(0, len(n)-1): for i in countup(0, len(n)-1):
@ -331,9 +331,9 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
if not isVisible(nameNode): return if not isVisible(nameNode): return
let let
name = getName(d, nameNode) name = getName(d, nameNode)
nameRope = name.toRope nameRope = name.rope
plainDocstring = getPlainDocstring(n) # call here before genRecComment! plainDocstring = getPlainDocstring(n) # call here before genRecComment!
var result: PRope = nil var result: Rope = nil
var literal, plainName = "" var literal, plainName = ""
var kind = tkEof var kind = tkEof
var comm = genRecComment(d, n) # call this here for the side-effect! var comm = genRecComment(d, n) # call this here for the side-effect!
@ -356,69 +356,69 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
break break
of tkComment: of tkComment:
dispA(result, "<span class=\"Comment\">$1</span>", "\\spanComment{$1}", dispA(result, "<span class=\"Comment\">$1</span>", "\\spanComment{$1}",
[toRope(esc(d.target, literal))]) [rope(esc(d.target, literal))])
of tokKeywordLow..tokKeywordHigh: of tokKeywordLow..tokKeywordHigh:
dispA(result, "<span class=\"Keyword\">$1</span>", "\\spanKeyword{$1}", dispA(result, "<span class=\"Keyword\">$1</span>", "\\spanKeyword{$1}",
[toRope(literal)]) [rope(literal)])
of tkOpr: of tkOpr:
dispA(result, "<span class=\"Operator\">$1</span>", "\\spanOperator{$1}", dispA(result, "<span class=\"Operator\">$1</span>", "\\spanOperator{$1}",
[toRope(esc(d.target, literal))]) [rope(esc(d.target, literal))])
of tkStrLit..tkTripleStrLit: of tkStrLit..tkTripleStrLit:
dispA(result, "<span class=\"StringLit\">$1</span>", dispA(result, "<span class=\"StringLit\">$1</span>",
"\\spanStringLit{$1}", [toRope(esc(d.target, literal))]) "\\spanStringLit{$1}", [rope(esc(d.target, literal))])
of tkCharLit: of tkCharLit:
dispA(result, "<span class=\"CharLit\">$1</span>", "\\spanCharLit{$1}", dispA(result, "<span class=\"CharLit\">$1</span>", "\\spanCharLit{$1}",
[toRope(esc(d.target, literal))]) [rope(esc(d.target, literal))])
of tkIntLit..tkUInt64Lit: of tkIntLit..tkUInt64Lit:
dispA(result, "<span class=\"DecNumber\">$1</span>", dispA(result, "<span class=\"DecNumber\">$1</span>",
"\\spanDecNumber{$1}", [toRope(esc(d.target, literal))]) "\\spanDecNumber{$1}", [rope(esc(d.target, literal))])
of tkFloatLit..tkFloat128Lit: of tkFloatLit..tkFloat128Lit:
dispA(result, "<span class=\"FloatNumber\">$1</span>", dispA(result, "<span class=\"FloatNumber\">$1</span>",
"\\spanFloatNumber{$1}", [toRope(esc(d.target, literal))]) "\\spanFloatNumber{$1}", [rope(esc(d.target, literal))])
of tkSymbol: of tkSymbol:
dispA(result, "<span class=\"Identifier\">$1</span>", dispA(result, "<span class=\"Identifier\">$1</span>",
"\\spanIdentifier{$1}", [toRope(esc(d.target, literal))]) "\\spanIdentifier{$1}", [rope(esc(d.target, literal))])
of tkSpaces, tkInvalid: of tkSpaces, tkInvalid:
app(result, literal) add(result, literal)
of tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi, of tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi,
tkBracketDotLe, tkBracketDotRi, tkCurlyDotLe, tkCurlyDotRi, tkParDotLe, tkBracketDotLe, tkBracketDotRi, tkCurlyDotLe, tkCurlyDotRi, tkParDotLe,
tkParDotRi, tkComma, tkSemiColon, tkColon, tkEquals, tkDot, tkDotDot, tkParDotRi, tkComma, tkSemiColon, tkColon, tkEquals, tkDot, tkDotDot,
tkAccent, tkColonColon, tkAccent, tkColonColon,
tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr: tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr:
dispA(result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}", dispA(result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
[toRope(esc(d.target, literal))]) [rope(esc(d.target, literal))])
inc(d.id) inc(d.id)
let let
plainNameRope = toRope(xmltree.escape(plainName.strip)) plainNameRope = rope(xmltree.escape(plainName.strip))
cleanPlainSymbol = renderPlainSymbolName(nameNode) cleanPlainSymbol = renderPlainSymbolName(nameNode)
complexSymbol = complexName(k, n, cleanPlainSymbol) complexSymbol = complexName(k, n, cleanPlainSymbol)
plainSymbolRope = toRope(cleanPlainSymbol) plainSymbolRope = rope(cleanPlainSymbol)
plainSymbolEncRope = toRope(encodeUrl(cleanPlainSymbol)) plainSymbolEncRope = rope(encodeUrl(cleanPlainSymbol))
itemIDRope = toRope(d.id) itemIDRope = rope(d.id)
symbolOrId = d.newUniquePlainSymbol(complexSymbol) symbolOrId = d.newUniquePlainSymbol(complexSymbol)
symbolOrIdRope = symbolOrId.toRope symbolOrIdRope = symbolOrId.rope
symbolOrIdEncRope = encodeUrl(symbolOrId).toRope symbolOrIdEncRope = encodeUrl(symbolOrId).rope
var seeSrcRope: PRope = nil var seeSrcRope: Rope = nil
let docItemSeeSrc = getConfigVar("doc.item.seesrc") let docItemSeeSrc = getConfigVar("doc.item.seesrc")
if docItemSeeSrc.len > 0 and options.docSeeSrcUrl.len > 0: if docItemSeeSrc.len > 0 and options.docSeeSrcUrl.len > 0:
# XXX toFilename doesn't really work. We need to ensure that this keeps # XXX toFilename doesn't really work. We need to ensure that this keeps
# returning a relative path. # returning a relative path.
let urlRope = ropeFormatNamedVars(options.docSeeSrcUrl, let urlRope = ropeFormatNamedVars(options.docSeeSrcUrl,
["path", "line"], [n.info.toFilename.toRope, toRope($n.info.line)]) ["path", "line"], [n.info.toFilename.rope, rope($n.info.line)])
dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc, dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,
["path", "line", "url"], [n.info.toFilename.toRope, ["path", "line", "url"], [n.info.toFilename.rope,
toRope($n.info.line), urlRope])]) rope($n.info.line), urlRope])])
app(d.section[k], ropeFormatNamedVars(getConfigVar("doc.item"), add(d.section[k], ropeFormatNamedVars(getConfigVar("doc.item"),
["name", "header", "desc", "itemID", "header_plain", "itemSym", ["name", "header", "desc", "itemID", "header_plain", "itemSym",
"itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "seeSrc"], "itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "seeSrc"],
[nameRope, result, comm, itemIDRope, plainNameRope, plainSymbolRope, [nameRope, result, comm, itemIDRope, plainNameRope, plainSymbolRope,
symbolOrIdRope, plainSymbolEncRope, symbolOrIdEncRope, seeSrcRope])) symbolOrIdRope, plainSymbolEncRope, symbolOrIdEncRope, seeSrcRope]))
app(d.toc[k], ropeFormatNamedVars(getConfigVar("doc.item.toc"), add(d.toc[k], ropeFormatNamedVars(getConfigVar("doc.item.toc"),
["name", "header", "desc", "itemID", "header_plain", "itemSym", ["name", "header", "desc", "itemID", "header_plain", "itemSym",
"itemSymOrID", "itemSymEnc", "itemSymOrIDEnc"], "itemSymOrID", "itemSymEnc", "itemSymOrIDEnc"],
[toRope(getName(d, nameNode, d.splitAfter)), result, comm, [rope(getName(d, nameNode, d.splitAfter)), result, comm,
itemIDRope, plainNameRope, plainSymbolRope, symbolOrIdRope, itemIDRope, plainNameRope, plainSymbolRope, symbolOrIdRope,
plainSymbolEncRope, symbolOrIdEncRope])) plainSymbolEncRope, symbolOrIdEncRope]))
@ -453,14 +453,14 @@ proc checkForFalse(n: PNode): bool =
proc traceDeps(d: PDoc, n: PNode) = proc traceDeps(d: PDoc, n: PNode) =
const k = skModule const k = skModule
if d.section[k] != nil: app(d.section[k], ", ") if d.section[k] != nil: add(d.section[k], ", ")
dispA(d.section[k], dispA(d.section[k],
"<a class=\"reference external\" href=\"$1.html\">$1</a>", "<a class=\"reference external\" href=\"$1.html\">$1</a>",
"$1", [toRope(getModuleName(n))]) "$1", [rope(getModuleName(n))])
proc generateDoc*(d: PDoc, n: PNode) = proc generateDoc*(d: PDoc, n: PNode) =
case n.kind case n.kind
of nkCommentStmt: app(d.modDesc, genComment(d, n)) of nkCommentStmt: add(d.modDesc, genComment(d, n))
of nkProcDef: of nkProcDef:
when useEffectSystem: documentRaises(n) when useEffectSystem: documentRaises(n)
genItem(d, n, n.sons[namePos], skProc) genItem(d, n, n.sons[namePos], skProc)
@ -540,28 +540,28 @@ proc genSection(d: PDoc, kind: TSymKind) =
"Iterators", "Iterators", "Converters", "Macros", "Templates" "Iterators", "Iterators", "Converters", "Macros", "Templates"
] ]
if d.section[kind] == nil: return if d.section[kind] == nil: return
var title = sectionNames[kind].toRope var title = sectionNames[kind].rope
d.section[kind] = ropeFormatNamedVars(getConfigVar("doc.section"), [ d.section[kind] = ropeFormatNamedVars(getConfigVar("doc.section"), [
"sectionid", "sectionTitle", "sectionTitleID", "content"], [ "sectionid", "sectionTitle", "sectionTitleID", "content"], [
ord(kind).toRope, title, toRope(ord(kind) + 50), d.section[kind]]) ord(kind).rope, title, rope(ord(kind) + 50), d.section[kind]])
d.toc[kind] = ropeFormatNamedVars(getConfigVar("doc.section.toc"), [ d.toc[kind] = ropeFormatNamedVars(getConfigVar("doc.section.toc"), [
"sectionid", "sectionTitle", "sectionTitleID", "content"], [ "sectionid", "sectionTitle", "sectionTitleID", "content"], [
ord(kind).toRope, title, toRope(ord(kind) + 50), d.toc[kind]]) ord(kind).rope, title, rope(ord(kind) + 50), d.toc[kind]])
proc genOutFile(d: PDoc): PRope = proc genOutFile(d: PDoc): Rope =
var var
code, content: PRope code, content: Rope
title = "" title = ""
var j = 0 var j = 0
var tmp = "" var tmp = ""
renderTocEntries(d[], j, 1, tmp) renderTocEntries(d[], j, 1, tmp)
var toc = tmp.toRope var toc = tmp.rope
for i in countup(low(TSymKind), high(TSymKind)): for i in countup(low(TSymKind), high(TSymKind)):
genSection(d, i) genSection(d, i)
app(toc, d.toc[i]) add(toc, d.toc[i])
if toc != nil: if toc != nil:
toc = ropeFormatNamedVars(getConfigVar("doc.toc"), ["content"], [toc]) toc = ropeFormatNamedVars(getConfigVar("doc.toc"), ["content"], [toc])
for i in countup(low(TSymKind), high(TSymKind)): app(code, d.section[i]) for i in countup(low(TSymKind), high(TSymKind)): add(code, d.section[i])
# Extract the title. Non API modules generate an entry in the index table. # Extract the title. Non API modules generate an entry in the index table.
if d.meta[metaTitle].len != 0: if d.meta[metaTitle].len != 0:
@ -574,16 +574,16 @@ proc genOutFile(d: PDoc): PRope =
let bodyname = if d.hasToc: "doc.body_toc" else: "doc.body_no_toc" let bodyname = if d.hasToc: "doc.body_toc" else: "doc.body_no_toc"
content = ropeFormatNamedVars(getConfigVar(bodyname), ["title", content = ropeFormatNamedVars(getConfigVar(bodyname), ["title",
"tableofcontents", "moduledesc", "date", "time", "content"], "tableofcontents", "moduledesc", "date", "time", "content"],
[title.toRope, toc, d.modDesc, toRope(getDateStr()), [title.rope, toc, d.modDesc, rope(getDateStr()),
toRope(getClockStr()), code]) rope(getClockStr()), code])
if optCompileOnly notin gGlobalOptions: if optCompileOnly notin gGlobalOptions:
# XXX what is this hack doing here? 'optCompileOnly' means raw output!? # XXX what is this hack doing here? 'optCompileOnly' means raw output!?
code = ropeFormatNamedVars(getConfigVar("doc.file"), ["title", code = ropeFormatNamedVars(getConfigVar("doc.file"), ["title",
"tableofcontents", "moduledesc", "date", "time", "tableofcontents", "moduledesc", "date", "time",
"content", "author", "version", "analytics"], "content", "author", "version", "analytics"],
[title.toRope, toc, d.modDesc, toRope(getDateStr()), [title.rope, toc, d.modDesc, rope(getDateStr()),
toRope(getClockStr()), content, d.meta[metaAuthor].toRope, rope(getClockStr()), content, d.meta[metaAuthor].rope,
d.meta[metaVersion].toRope, d.analytics.toRope]) d.meta[metaVersion].rope, d.analytics.rope])
else: else:
code = content code = content
result = code result = code
@ -618,7 +618,7 @@ proc commandRstAux(filename, outExt: string) =
#d.modDesc = newMutableRope(30_000) #d.modDesc = newMutableRope(30_000)
renderRstToOut(d[], rst, modDesc) renderRstToOut(d[], rst, modDesc)
#freezeMutableRope(d.modDesc) #freezeMutableRope(d.modDesc)
d.modDesc = toRope(modDesc) d.modDesc = rope(modDesc)
writeOutput(d, filename, outExt) writeOutput(d, filename, outExt)
generateIndex(d) generateIndex(d)
@ -635,7 +635,7 @@ proc commandJSON*() =
var d = newDocumentor(gProjectFull, options.gConfigVars) var d = newDocumentor(gProjectFull, options.gConfigVars)
d.hasToc = true d.hasToc = true
var json = generateJson(d, ast) var json = generateJson(d, ast)
var content = toRope(pretty(json)) var content = rope(pretty(json))
if optStdout in gGlobalOptions: if optStdout in gGlobalOptions:
writeRope(stdout, content) writeRope(stdout, content)
@ -644,12 +644,12 @@ proc commandJSON*() =
writeRope(content, getOutFile(gProjectFull, JsonExt), useWarning = false) writeRope(content, getOutFile(gProjectFull, JsonExt), useWarning = false)
proc commandBuildIndex*() = proc commandBuildIndex*() =
var content = mergeIndexes(gProjectFull).toRope var content = mergeIndexes(gProjectFull).rope
let code = ropeFormatNamedVars(getConfigVar("doc.file"), ["title", let code = ropeFormatNamedVars(getConfigVar("doc.file"), ["title",
"tableofcontents", "moduledesc", "date", "time", "tableofcontents", "moduledesc", "date", "time",
"content", "author", "version", "analytics"], "content", "author", "version", "analytics"],
["Index".toRope, nil, nil, toRope(getDateStr()), ["Index".rope, nil, nil, rope(getDateStr()),
toRope(getClockStr()), content, nil, nil, nil]) rope(getClockStr()), content, nil, nil, nil])
# no analytics because context is not available # no analytics because context is not available
writeRope(code, getOutFile("theindex", HtmlExt)) writeRope(code, getOutFile("theindex", HtmlExt))

View file

@ -449,7 +449,7 @@ proc execExternalProgram*(cmd: string, prettyCmd = "") =
if execWithEcho(cmd, prettyCmd) != 0: if execWithEcho(cmd, prettyCmd) != 0:
rawMessage(errExecutionOfProgramFailed, "") rawMessage(errExecutionOfProgramFailed, "")
proc generateScript(projectFile: string, script: PRope) = proc generateScript(projectFile: string, script: Rope) =
let (dir, name, ext) = splitFile(projectFile) let (dir, name, ext) = splitFile(projectFile)
writeRope(script, dir / addFileExt("compile_" & name, writeRope(script, dir / addFileExt("compile_" & name,
platform.OS[targetOS].scriptExt)) platform.OS[targetOS].scriptExt))
@ -604,7 +604,7 @@ proc addExternalFileToCompile*(filename: string) =
if optForceFullMake in gGlobalOptions or externalFileChanged(filename): if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
appendStr(externalToCompile, filename) appendStr(externalToCompile, filename)
proc compileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq, proc compileCFile(list: TLinkedList, script: var Rope, cmds: var TStringSeq,
prettyCmds: var TStringSeq, isExternal: bool) = prettyCmds: var TStringSeq, isExternal: bool) =
var it = PStrEntry(list.head) var it = PStrEntry(list.head)
while it != nil: while it != nil:
@ -615,8 +615,8 @@ proc compileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
let (dir, name, ext) = splitFile(it.data) let (dir, name, ext) = splitFile(it.data)
add(prettyCmds, "CC: " & name) add(prettyCmds, "CC: " & name)
if optGenScript in gGlobalOptions: if optGenScript in gGlobalOptions:
app(script, compileCmd) add(script, compileCmd)
app(script, tnl) add(script, tnl)
it = PStrEntry(it.next) it = PStrEntry(it.next)
proc callCCompiler*(projectfile: string) = proc callCCompiler*(projectfile: string) =
@ -627,7 +627,7 @@ proc callCCompiler*(projectfile: string) =
# generated # generated
fileCounter = 0 fileCounter = 0
var c = cCompiler var c = cCompiler
var script: PRope = nil var script: Rope = nil
var cmds: TStringSeq = @[] var cmds: TStringSeq = @[]
var prettyCmds: TStringSeq = @[] var prettyCmds: TStringSeq = @[]
let prettyCb = proc (idx: int) = let prettyCb = proc (idx: int) =
@ -710,30 +710,30 @@ proc callCCompiler*(projectfile: string) =
else: else:
linkCmd = "" linkCmd = ""
if optGenScript in gGlobalOptions: if optGenScript in gGlobalOptions:
app(script, linkCmd) add(script, linkCmd)
app(script, tnl) add(script, tnl)
generateScript(projectfile, script) generateScript(projectfile, script)
proc genMappingFiles(list: TLinkedList): PRope = proc genMappingFiles(list: TLinkedList): Rope =
var it = PStrEntry(list.head) var it = PStrEntry(list.head)
while it != nil: while it != nil:
appf(result, "--file:r\"$1\"$N", [toRope(it.data)]) addf(result, "--file:r\"$1\"$N", [rope(it.data)])
it = PStrEntry(it.next) it = PStrEntry(it.next)
proc writeMapping*(gSymbolMapping: PRope) = proc writeMapping*(gSymbolMapping: Rope) =
if optGenMapping notin gGlobalOptions: return if optGenMapping notin gGlobalOptions: return
var code = toRope("[C_Files]\n") var code = rope("[C_Files]\n")
app(code, genMappingFiles(toCompile)) add(code, genMappingFiles(toCompile))
app(code, genMappingFiles(externalToCompile)) add(code, genMappingFiles(externalToCompile))
app(code, "\n[C_Compiler]\nFlags=") add(code, "\n[C_Compiler]\nFlags=")
app(code, strutils.escape(getCompileOptions())) add(code, strutils.escape(getCompileOptions()))
app(code, "\n[Linker]\nFlags=") add(code, "\n[Linker]\nFlags=")
app(code, strutils.escape(getLinkOptions() & " " & add(code, strutils.escape(getLinkOptions() & " " &
getConfigVar(cCompiler, ".options.linker"))) getConfigVar(cCompiler, ".options.linker")))
app(code, "\n[Environment]\nlibpath=") add(code, "\n[Environment]\nlibpath=")
app(code, strutils.escape(libpath)) add(code, strutils.escape(libpath))
appf(code, "\n[Symbols]$n$1", [gSymbolMapping]) addf(code, "\n[Symbols]$n$1", [gSymbolMapping])
writeRope(code, joinPath(gProjectPath, "mapping.txt")) writeRope(code, joinPath(gProjectPath, "mapping.txt"))

File diff suppressed because it is too large Load diff

View file

@ -9,138 +9,138 @@
## Type info generation for the JS backend. ## Type info generation for the JS backend.
proc genTypeInfo(p: PProc, typ: PType): PRope proc genTypeInfo(p: PProc, typ: PType): Rope
proc genObjectFields(p: PProc, typ: PType, n: PNode): PRope = proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
var var
s, u: PRope s, u: Rope
length: int length: int
field: PSym field: PSym
b: PNode b: PNode
result = nil result = nil
case n.kind case n.kind
of nkRecList: of nkRecList:
length = sonsLen(n) length = sonsLen(n)
if length == 1: if length == 1:
result = genObjectFields(p, typ, n.sons[0]) result = genObjectFields(p, typ, n.sons[0])
else: else:
s = nil s = nil
for i in countup(0, length - 1): for i in countup(0, length - 1):
if i > 0: app(s, ", " & tnl) if i > 0: add(s, ", " & tnl)
app(s, genObjectFields(p, typ, n.sons[i])) add(s, genObjectFields(p, typ, n.sons[i]))
result = ropef("{kind: 2, len: $1, offset: 0, " & result = ("{kind: 2, len: $1, offset: 0, " &
"typ: null, name: null, sons: [$2]}", [toRope(length), s]) "typ: null, name: null, sons: [$2]}") % [rope(length), s]
of nkSym: of nkSym:
field = n.sym field = n.sym
s = genTypeInfo(p, field.typ) s = genTypeInfo(p, field.typ)
result = ropef("{kind: 1, offset: \"$1\", len: 0, " & result = ("{kind: 1, offset: \"$1\", len: 0, " &
"typ: $2, name: $3, sons: null}", "typ: $2, name: $3, sons: null}") %
[mangleName(field), s, makeJSString(field.name.s)]) [mangleName(field), s, makeJSString(field.name.s)]
of nkRecCase: of nkRecCase:
length = sonsLen(n) length = sonsLen(n)
if (n.sons[0].kind != nkSym): internalError(n.info, "genObjectFields") if (n.sons[0].kind != nkSym): internalError(n.info, "genObjectFields")
field = n.sons[0].sym field = n.sons[0].sym
s = genTypeInfo(p, field.typ) s = genTypeInfo(p, field.typ)
for i in countup(1, length - 1): for i in countup(1, length - 1):
b = n.sons[i] # branch b = n.sons[i] # branch
u = nil u = nil
case b.kind case b.kind
of nkOfBranch: of nkOfBranch:
if sonsLen(b) < 2: if sonsLen(b) < 2:
internalError(b.info, "genObjectFields; nkOfBranch broken") internalError(b.info, "genObjectFields; nkOfBranch broken")
for j in countup(0, sonsLen(b) - 2): for j in countup(0, sonsLen(b) - 2):
if u != nil: app(u, ", ") if u != nil: add(u, ", ")
if b.sons[j].kind == nkRange: if b.sons[j].kind == nkRange:
appf(u, "[$1, $2]", [toRope(getOrdValue(b.sons[j].sons[0])), addf(u, "[$1, $2]", [rope(getOrdValue(b.sons[j].sons[0])),
toRope(getOrdValue(b.sons[j].sons[1]))]) rope(getOrdValue(b.sons[j].sons[1]))])
else: else:
app(u, toRope(getOrdValue(b.sons[j]))) add(u, rope(getOrdValue(b.sons[j])))
of nkElse: of nkElse:
u = toRope(lengthOrd(field.typ)) u = rope(lengthOrd(field.typ))
else: internalError(n.info, "genObjectFields(nkRecCase)") else: internalError(n.info, "genObjectFields(nkRecCase)")
if result != nil: app(result, ", " & tnl) if result != nil: add(result, ", " & tnl)
appf(result, "[SetConstr($1), $2]", addf(result, "[SetConstr($1), $2]",
[u, genObjectFields(p, typ, lastSon(b))]) [u, genObjectFields(p, typ, lastSon(b))])
result = ropef("{kind: 3, offset: \"$1\", len: $3, " & result = ("{kind: 3, offset: \"$1\", len: $3, " &
"typ: $2, name: $4, sons: [$5]}", [mangleName(field), s, "typ: $2, name: $4, sons: [$5]}") % [mangleName(field), s,
toRope(lengthOrd(field.typ)), makeJSString(field.name.s), result]) rope(lengthOrd(field.typ)), makeJSString(field.name.s), result]
else: internalError(n.info, "genObjectFields") else: internalError(n.info, "genObjectFields")
proc genObjectInfo(p: PProc, typ: PType, name: PRope) = proc genObjectInfo(p: PProc, typ: PType, name: Rope) =
var s = ropef("var $1 = {size: 0, kind: $2, base: null, node: null, " & var s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n", [name, toRope(ord(typ.kind))]) "finalizer: null};$n") % [name, rope(ord(typ.kind))]
prepend(p.g.typeInfo, s) prepend(p.g.typeInfo, s)
appf(p.g.typeInfo, "var NNI$1 = $2;$n", addf(p.g.typeInfo, "var NNI$1 = $2;$n",
[toRope(typ.id), genObjectFields(p, typ, typ.n)]) [rope(typ.id), genObjectFields(p, typ, typ.n)])
appf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, toRope(typ.id)]) addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
if (typ.kind == tyObject) and (typ.sons[0] != nil): if (typ.kind == tyObject) and (typ.sons[0] != nil):
appf(p.g.typeInfo, "$1.base = $2;$n", addf(p.g.typeInfo, "$1.base = $2;$n",
[name, genTypeInfo(p, typ.sons[0])]) [name, genTypeInfo(p, typ.sons[0])])
proc genTupleFields(p: PProc, typ: PType): PRope = proc genTupleFields(p: PProc, typ: PType): Rope =
var s: PRope = nil var s: Rope = nil
for i in 0 .. <typ.len: for i in 0 .. <typ.len:
if i > 0: app(s, ", " & tnl) if i > 0: add(s, ", " & tnl)
s.appf("{kind: 1, offset: \"Field$1\", len: 0, " & s.addf("{kind: 1, offset: \"Field$1\", len: 0, " &
"typ: $2, name: \"Field$1\", sons: null}", "typ: $2, name: \"Field$1\", sons: null}",
[i.toRope, genTypeInfo(p, typ.sons[i])]) [i.rope, genTypeInfo(p, typ.sons[i])])
result = ropef("{kind: 2, len: $1, offset: 0, " & result = ("{kind: 2, len: $1, offset: 0, " &
"typ: null, name: null, sons: [$2]}", [toRope(typ.len), s]) "typ: null, name: null, sons: [$2]}") % [rope(typ.len), s]
proc genTupleInfo(p: PProc, typ: PType, name: PRope) = proc genTupleInfo(p: PProc, typ: PType, name: Rope) =
var s = ropef("var $1 = {size: 0, kind: $2, base: null, node: null, " & var s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n", [name, toRope(ord(typ.kind))]) "finalizer: null};$n") % [name, rope(ord(typ.kind))]
prepend(p.g.typeInfo, s) prepend(p.g.typeInfo, s)
appf(p.g.typeInfo, "var NNI$1 = $2;$n", addf(p.g.typeInfo, "var NNI$1 = $2;$n",
[toRope(typ.id), genTupleFields(p, typ)]) [rope(typ.id), genTupleFields(p, typ)])
appf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, toRope(typ.id)]) addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
proc genEnumInfo(p: PProc, typ: PType, name: PRope) = proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
let length = sonsLen(typ.n) let length = sonsLen(typ.n)
var s: PRope = nil var s: Rope = nil
for i in countup(0, length - 1): for i in countup(0, length - 1):
if (typ.n.sons[i].kind != nkSym): internalError(typ.n.info, "genEnumInfo") if (typ.n.sons[i].kind != nkSym): internalError(typ.n.info, "genEnumInfo")
let field = typ.n.sons[i].sym let field = typ.n.sons[i].sym
if i > 0: app(s, ", " & tnl) if i > 0: add(s, ", " & tnl)
let extName = if field.ast == nil: field.name.s else: field.ast.strVal let extName = if field.ast == nil: field.name.s else: field.ast.strVal
appf(s, "{kind: 1, offset: $1, typ: $2, name: $3, len: 0, sons: null}", addf(s, "{kind: 1, offset: $1, typ: $2, name: $3, len: 0, sons: null}",
[toRope(field.position), name, makeJSString(extName)]) [rope(field.position), name, makeJSString(extName)])
var n = ropef("var NNI$1 = {kind: 2, offset: 0, typ: null, " & var n = ("var NNI$1 = {kind: 2, offset: 0, typ: null, " &
"name: null, len: $2, sons: [$3]};$n", [toRope(typ.id), toRope(length), s]) "name: null, len: $2, sons: [$3]};$n") % [rope(typ.id), rope(length), s]
s = ropef("var $1 = {size: 0, kind: $2, base: null, node: null, " & s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n", [name, toRope(ord(typ.kind))]) "finalizer: null};$n") % [name, rope(ord(typ.kind))]
prepend(p.g.typeInfo, s) prepend(p.g.typeInfo, s)
app(p.g.typeInfo, n) add(p.g.typeInfo, n)
appf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, toRope(typ.id)]) addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
if typ.sons[0] != nil: if typ.sons[0] != nil:
appf(p.g.typeInfo, "$1.base = $2;$n", addf(p.g.typeInfo, "$1.base = $2;$n",
[name, genTypeInfo(p, typ.sons[0])]) [name, genTypeInfo(p, typ.sons[0])])
proc genTypeInfo(p: PProc, typ: PType): PRope = proc genTypeInfo(p: PProc, typ: PType): Rope =
var t = typ var t = typ
if t.kind == tyGenericInst: t = lastSon(t) if t.kind == tyGenericInst: t = lastSon(t)
result = ropef("NTI$1", [toRope(t.id)]) result = "NTI$1" % [rope(t.id)]
if containsOrIncl(p.g.typeInfoGenerated, t.id): return if containsOrIncl(p.g.typeInfoGenerated, t.id): return
case t.kind case t.kind
of tyDistinct: of tyDistinct:
result = genTypeInfo(p, typ.sons[0]) result = genTypeInfo(p, typ.sons[0])
of tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64: of tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64:
var s = ropef( var s =
"var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n", "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
[result, toRope(ord(t.kind))]) [result, rope(ord(t.kind))]
prepend(p.g.typeInfo, s) prepend(p.g.typeInfo, s)
of tyVar, tyRef, tyPtr, tySequence, tyRange, tySet: of tyVar, tyRef, tyPtr, tySequence, tyRange, tySet:
var s = ropef( var s =
"var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n", "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
[result, toRope(ord(t.kind))]) [result, rope(ord(t.kind))]
prepend(p.g.typeInfo, s) prepend(p.g.typeInfo, s)
appf(p.g.typeInfo, "$1.base = $2;$n", addf(p.g.typeInfo, "$1.base = $2;$n",
[result, genTypeInfo(p, typ.lastSon)]) [result, genTypeInfo(p, typ.lastSon)])
of tyArrayConstr, tyArray: of tyArrayConstr, tyArray:
var s = ropef( var s =
"var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n", "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
[result, toRope(ord(t.kind))]) [result, rope(ord(t.kind))]
prepend(p.g.typeInfo, s) prepend(p.g.typeInfo, s)
appf(p.g.typeInfo, "$1.base = $2;$n", addf(p.g.typeInfo, "$1.base = $2;$n",
[result, genTypeInfo(p, typ.sons[1])]) [result, genTypeInfo(p, typ.sons[1])])
of tyEnum: genEnumInfo(p, t, result) of tyEnum: genEnumInfo(p, t, result)
of tyObject: genObjectInfo(p, t, result) of tyObject: genObjectInfo(p, t, result)

View file

@ -449,10 +449,10 @@ type
fullPath: string # This is a canonical full filesystem path fullPath: string # This is a canonical full filesystem path
projPath*: string # This is relative to the project's root projPath*: string # This is relative to the project's root
shortName*: string # short name of the module shortName*: string # short name of the module
quotedName*: PRope # cached quoted short name for codegen quotedName*: Rope # cached quoted short name for codegen
# purposes # purposes
lines*: seq[PRope] # the source code of the module lines*: seq[Rope] # the source code of the module
# used for better error messages and # used for better error messages and
# embedding the original source in the # embedding the original source in the
# generated code # generated code
@ -493,7 +493,7 @@ proc toCChar*(c: char): string =
of '\'', '\"', '\\': result = '\\' & c of '\'', '\"', '\\': result = '\\' & c
else: result = $(c) else: result = $(c)
proc makeCString*(s: string): PRope = proc makeCString*(s: string): Rope =
const const
MaxLineLength = 64 MaxLineLength = 64
result = nil result = nil
@ -506,7 +506,7 @@ proc makeCString*(s: string): PRope =
add(res, '\"') add(res, '\"')
add(res, toCChar(s[i])) add(res, toCChar(s[i]))
add(res, '\"') add(res, '\"')
app(result, toRope(res)) add(result, rope(res))
proc newFileInfo(fullPath, projPath: string): TFileInfo = proc newFileInfo(fullPath, projPath: string): TFileInfo =
@ -564,7 +564,7 @@ var gCodegenLineInfo* = newLineInfo(int32(1), 1, 1)
proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} = proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} =
raise newException(ERecoverableError, msg) raise newException(ERecoverableError, msg)
proc sourceLine*(i: TLineInfo): PRope proc sourceLine*(i: TLineInfo): Rope
var var
gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)} - gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)} -
@ -848,9 +848,9 @@ template internalAssert*(e: bool): stmt =
if not e: internalError($instantiationInfo()) if not e: internalError($instantiationInfo())
proc addSourceLine*(fileIdx: int32, line: string) = proc addSourceLine*(fileIdx: int32, line: string) =
fileInfos[fileIdx].lines.add line.toRope fileInfos[fileIdx].lines.add line.rope
proc sourceLine*(i: TLineInfo): PRope = proc sourceLine*(i: TLineInfo): Rope =
if i.fileIndex < 0: return nil if i.fileIndex < 0: return nil
if not optPreserveOrigSource and fileInfos[i.fileIndex].lines.len == 0: if not optPreserveOrigSource and fileInfos[i.fileIndex].lines.len == 0:
@ -865,11 +865,11 @@ proc sourceLine*(i: TLineInfo): PRope =
result = fileInfos[i.fileIndex].lines[i.line-1] result = fileInfos[i.fileIndex].lines[i.line-1]
proc quotedFilename*(i: TLineInfo): PRope = proc quotedFilename*(i: TLineInfo): Rope =
internalAssert i.fileIndex >= 0 internalAssert i.fileIndex >= 0
result = fileInfos[i.fileIndex].quotedName result = fileInfos[i.fileIndex].quotedName
ropes.errorHandler = proc (err: TRopesError, msg: string, useWarning: bool) = ropes.errorHandler = proc (err: RopesError, msg: string, useWarning: bool) =
case err case err
of rInvalidFormatStr: of rInvalidFormatStr:
internalError("ropes: invalid format string: " & msg) internalError("ropes: invalid format string: " & msg)

View file

@ -89,7 +89,7 @@ proc pragmaAsm*(c: PContext, n: PNode): char =
invalidPragma(it) invalidPragma(it)
proc setExternName(s: PSym, extname: string) = proc setExternName(s: PSym, extname: string) =
s.loc.r = toRope(extname % s.name.s) s.loc.r = rope(extname % s.name.s)
if gCmd == cmdPretty and '$' notin extname: if gCmd == cmdPretty and '$' notin extname:
# note that '{.importc.}' is transformed into '{.importc: "$1".}' # note that '{.importc.}' is transformed into '{.importc: "$1".}'
s.loc.flags.incl(lfFullExternalName) s.loc.flags.incl(lfFullExternalName)
@ -677,7 +677,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
incl(sym.loc.flags, lfHeader) incl(sym.loc.flags, lfHeader)
incl(sym.loc.flags, lfNoDecl) incl(sym.loc.flags, lfNoDecl)
# implies nodecl, because otherwise header would not make sense # implies nodecl, because otherwise header would not make sense
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s) if sym.loc.r == nil: sym.loc.r = rope(sym.name.s)
of wDestructor: of wDestructor:
sym.flags.incl sfOverriden sym.flags.incl sfOverriden
if sym.name.s.normalize != "destroy": if sym.name.s.normalize != "destroy":
@ -879,7 +879,7 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
sfImportc in sym.flags and lib != nil: sfImportc in sym.flags and lib != nil:
incl(sym.loc.flags, lfDynamicLib) incl(sym.loc.flags, lfDynamicLib)
addToLib(lib, sym) addToLib(lib, sym)
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s) if sym.loc.r == nil: sym.loc.r = rope(sym.name.s)
proc hasPragma*(n: PNode, pragma: TSpecialWord): bool = proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
if n == nil or n.sons == nil: if n == nil or n.sons == nil:

View file

@ -277,7 +277,7 @@ proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) =
loc.t = nil loc.t = nil
if r.s[r.pos] == '!': if r.s[r.pos] == '!':
inc(r.pos) inc(r.pos)
loc.r = toRope(decodeStr(r.s, r.pos)) loc.r = rope(decodeStr(r.s, r.pos))
else: else:
loc.r = nil loc.r = nil
if r.s[r.pos] == '>': inc(r.pos) if r.s[r.pos] == '>': inc(r.pos)
@ -344,7 +344,7 @@ proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
result.kind = TLibKind(decodeVInt(r.s, r.pos)) result.kind = TLibKind(decodeVInt(r.s, r.pos))
if r.s[r.pos] != '|': internalError("decodeLib: 1") if r.s[r.pos] != '|': internalError("decodeLib: 1")
inc(r.pos) inc(r.pos)
result.name = toRope(decodeStr(r.s, r.pos)) result.name = rope(decodeStr(r.s, r.pos))
if r.s[r.pos] != '|': internalError("decodeLib: 2") if r.s[r.pos] != '|': internalError("decodeLib: 2")
inc(r.pos) inc(r.pos)
result.path = decodeNode(r, info) result.path = decodeNode(r, info)

View file

@ -76,11 +76,6 @@ type
rCannotOpenFile rCannotOpenFile
rInvalidFormatStr rInvalidFormatStr
{.deprecated: [TFormatStr: FormatStr].}
{.deprecated: [PRope: Rope].}
{.deprecated: [TRopeSeq: RopeSeq].}
{.deprecated: [TRopesError: RopesError].}
# implementation # implementation
var errorHandler*: proc(err: RopesError, msg: string, useWarning = false) var errorHandler*: proc(err: RopesError, msg: string, useWarning = false)
@ -152,12 +147,6 @@ proc rope*(i: BiggestInt): Rope =
proc rope*(f: BiggestFloat): Rope = proc rope*(f: BiggestFloat): Rope =
result = rope($f) result = rope($f)
# TODO Old names - change invokations to rope
proc toRope*(s: string): Rope {.deprecated.} =
result = rope(s)
proc toRope*(i: BiggestInt): Rope {.deprecated.} =
result = rope(i)
proc ropeSeqInsert(rs: var RopeSeq, r: Rope, at: Natural) = proc ropeSeqInsert(rs: var RopeSeq, r: Rope, at: Natural) =
var length = len(rs) var length = len(rs)
if at > length: if at > length:
@ -214,19 +203,9 @@ proc `$`*(p: Rope): string =
var resultLen = 0 var resultLen = 0
newRecRopeToStr(result, resultLen, p) newRecRopeToStr(result, resultLen, p)
# TODO Old names - change invokations to `&`
proc con*(a, b: Rope): Rope {.deprecated.} = a & b
proc con*(a: Rope, b: string): Rope {.deprecated.} = a & b
proc con*(a: string, b: Rope): Rope {.deprecated.} = a & b
proc con*(a: varargs[Rope]): Rope {.deprecated.} = `&`(a)
proc ropeConcat*(a: varargs[Rope]): Rope = proc ropeConcat*(a: varargs[Rope]): Rope =
# not overloaded version of concat to speed-up `rfmt` a little bit # not overloaded version of concat to speed-up `rfmt` a little bit
for i in countup(0, high(a)): result = con(result, a[i]) for i in countup(0, high(a)): result = result & a[i]
# TODO Old names - change invokations to add
proc app*(a: var Rope, b: Rope) {.deprecated.} = add(a, b)
proc app*(a: var Rope, b: string) {.deprecated.} = add(a, b)
proc prepend*(a: var Rope, b: Rope) = a = b & a proc prepend*(a: var Rope, b: Rope) = a = b & a
proc prepend*(a: var Rope, b: string) = a = b & a proc prepend*(a: var Rope, b: string) = a = b & a
@ -254,7 +233,7 @@ var
rnl* = tnl.newRope rnl* = tnl.newRope
softRnl* = tnl.newRope softRnl* = tnl.newRope
proc `%`*(frmt: TFormatStr, args: openArray[Rope]): Rope = proc `%`*(frmt: FormatStr, args: openArray[Rope]): Rope =
var i = 0 var i = 0
var length = len(frmt) var length = len(frmt)
result = nil result = nil
@ -311,23 +290,17 @@ proc `%`*(frmt: TFormatStr, args: openArray[Rope]): Rope =
add(result, substr(frmt, start, i - 1)) add(result, substr(frmt, start, i - 1))
assert(ropeInvariant(result)) assert(ropeInvariant(result))
proc addf*(c: var Rope, frmt: TFormatStr, args: openArray[Rope]) = proc addf*(c: var Rope, frmt: FormatStr, args: openArray[Rope]) =
add(c, frmt % args) add(c, frmt % args)
# TODO Compatibility names
proc ropef*(frmt: TFormatStr, args: varargs[Rope]): Rope {.deprecated.} =
result = frmt % args
proc appf*(c: var Rope, frmt: TFormatStr, args: varargs[Rope]) {.deprecated.} =
addf(c, frmt, args)
when true: when true:
template `~`*(r: string): Rope = r.ropef template `~`*(r: string): Rope = r % []
else: else:
{.push stack_trace: off, line_trace: off.} {.push stack_trace: off, line_trace: off.}
proc `~`*(r: static[string]): Rope = proc `~`*(r: static[string]): Rope =
# this is the new optimized "to rope" operator # this is the new optimized "to rope" operator
# the mnemonic is that `~` looks a bit like a rope :) # the mnemonic is that `~` looks a bit like a rope :)
var r {.global.} = r.ropef var r {.global.} = r % []
return r return r
{.pop.} {.pop.}

View file

@ -593,7 +593,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
f.position = pos f.position = pos
if (rec != nil) and ({sfImportc, sfExportc} * rec.flags != {}) and if (rec != nil) and ({sfImportc, sfExportc} * rec.flags != {}) and
(f.loc.r == nil): (f.loc.r == nil):
f.loc.r = toRope(f.name.s) f.loc.r = rope(f.name.s)
f.flags = f.flags + ({sfImportc, sfExportc} * rec.flags) f.flags = f.flags + ({sfImportc, sfExportc} * rec.flags)
inc(pos) inc(pos)
if containsOrIncl(check, f.name.id): if containsOrIncl(check, f.name.id):