implemented mixed mode codegen

This commit is contained in:
Araq 2014-10-03 01:21:35 +02:00
commit e65c296bcc
15 changed files with 133 additions and 95 deletions

View file

@ -291,6 +291,8 @@ const
sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't
# require RC ops # require RC ops
sfCompileToCpp* = sfInfixCall # compile the module as C++ code
sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code
const const
# getting ready for the future expr/stmt merge # getting ready for the future expr/stmt merge

View file

@ -103,9 +103,9 @@ proc openArrayLoc(p: BProc, n: PNode): PRope =
result = ropef("$1, $1Len0", [rdLoc(a)]) result = ropef("$1, $1Len0", [rdLoc(a)])
of tyString, tySequence: of tyString, tySequence:
if skipTypes(n.typ, abstractInst).kind == tyVar: if skipTypes(n.typ, abstractInst).kind == tyVar:
result = ropef("(*$1)->data, (*$1)->$2", [a.rdLoc, lenField()]) result = ropef("(*$1)->data, (*$1)->$2", [a.rdLoc, lenField(p)])
else: else:
result = ropef("$1->data, $1->$2", [a.rdLoc, lenField()]) result = ropef("$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 = ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))])
else: internalError("openArrayLoc: " & typeToString(a.t)) else: internalError("openArrayLoc: " & typeToString(a.t))

View file

@ -721,7 +721,7 @@ 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 gCmd != cmdCompileToCpp: app(r, ".Sup") if not p.module.compileToCpp: app(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")
@ -773,7 +773,7 @@ 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 gCmd != cmdCompileToCpp: app(r, ".Sup") if not p.module.compileToCpp: app(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:
@ -840,11 +840,11 @@ proc genSeqElem(p: BProc, e: PNode, d: var TLoc) =
if ty.kind == tyString: if ty.kind == tyString:
linefmt(p, cpsStmts, linefmt(p, cpsStmts,
"if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n", "if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
rdLoc(b), rdLoc(a), lenField()) rdLoc(b), rdLoc(a), lenField(p))
else: else:
linefmt(p, cpsStmts, linefmt(p, cpsStmts,
"if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n", "if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
rdLoc(b), rdLoc(a), lenField()) rdLoc(b), rdLoc(a), lenField(p))
if d.k == locNone: d.s = OnHeap if d.k == locNone: d.s = OnHeap
d.heapRoot = a.r d.heapRoot = a.r
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}: if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
@ -937,7 +937,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
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()]) appf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)])
app(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a))) app(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, toRope(L))
app(p.s(cpsStmts), appends) app(p.s(cpsStmts), appends)
@ -977,7 +977,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
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()]) appf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)])
app(appends, rfmt(p.module, "#appendString($1, $2);$n", app(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",
@ -990,7 +990,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
# seq &= x --> # seq &= x -->
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x)); # seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
# seq->data[seq->len-1] = x; # seq->data[seq->len-1] = x;
let seqAppendPattern = if gCmd != cmdCompileToCpp: let seqAppendPattern = if not p.module.compileToCpp:
"$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n" "$1 = ($2) #incrSeq(&($1)->Sup, sizeof($3));$n"
else: else:
"$1 = ($2) #incrSeq($1, sizeof($3));$n" "$1 = ($2) #incrSeq($1, sizeof($3));$n"
@ -1003,7 +1003,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
getTypeDesc(p.module, skipTypes(e.sons[2].typ, abstractVar))]) getTypeDesc(p.module, skipTypes(e.sons[2].typ, abstractVar))])
keepAlive(p, a) keepAlive(p, a)
initLoc(dest, locExpr, b.t, OnHeap) initLoc(dest, locExpr, b.t, OnHeap)
dest.r = rfmt(nil, "$1->data[$1->$2-1]", rdLoc(a), lenField()) dest.r = rfmt(nil, "$1->data[$1->$2-1]", rdLoc(a), lenField(p))
genAssignment(p, dest, b, {needToCopy, afDestIsNil}) genAssignment(p, dest, b, {needToCopy, afDestIsNil})
gcUsage(e) gcUsage(e)
@ -1097,7 +1097,7 @@ 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 gCmd != cmdCompileToCpp: app(tmp2.r, ".Sup") if not p.module.compileToCpp: app(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:
@ -1198,8 +1198,8 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
if t.kind != tyVar: nilCheck = r if t.kind != tyVar: nilCheck = r
r = rfmt(nil, "(*$1)", r) r = rfmt(nil, "(*$1)", r)
t = skipTypes(t.lastSon, typedescInst) t = skipTypes(t.lastSon, typedescInst)
if gCmd != cmdCompileToCpp: 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") app(r, ~".Sup")
t = skipTypes(t.sons[0], typedescInst) t = skipTypes(t.sons[0], typedescInst)
if isObjLackingTypeField(t): if isObjLackingTypeField(t):
@ -1244,7 +1244,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
putIntoDest(p, b, e.typ, ropef("$1, $1Len0", [rdLoc(a)])) putIntoDest(p, b, e.typ, ropef("$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()])) ropef("$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))])) ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
@ -1287,7 +1287,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)") if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
else: unaryExpr(p, e, d, "strlen($1)") else: unaryExpr(p, e, d, "strlen($1)")
of tyString, tySequence: of tyString, tySequence:
if gCmd != cmdCompileToCpp: if not p.module.compileToCpp:
if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)") if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
else: unaryExpr(p, e, d, "$1->Sup.len") else: unaryExpr(p, e, d, "$1->Sup.len")
else: else:
@ -1305,7 +1305,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b) initLocExpr(p, e.sons[2], b)
var t = skipTypes(e.sons[1].typ, abstractVar) var t = skipTypes(e.sons[1].typ, abstractVar)
let setLenPattern = if gCmd != cmdCompileToCpp: let setLenPattern = if not p.module.compileToCpp:
"$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n" "$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n"
else: else:
"$1 = ($3) #setLengthSeq($1, sizeof($4), $2);$n" "$1 = ($3) #setLengthSeq($1, sizeof($4), $2);$n"
@ -1561,11 +1561,11 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""): elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
initLocExpr(p, e.sons[2], x) initLocExpr(p, e.sons[2], x)
putIntoDest(p, d, e.typ, putIntoDest(p, d, e.typ,
rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField())) rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p)))
elif (b.kind in {nkStrLit..nkTripleStrLit}) and (b.strVal == ""): elif (b.kind in {nkStrLit..nkTripleStrLit}) and (b.strVal == ""):
initLocExpr(p, e.sons[1], x) initLocExpr(p, e.sons[1], x)
putIntoDest(p, d, e.typ, putIntoDest(p, d, e.typ,
rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField())) rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p)))
else: else:
binaryExpr(p, e, d, "#eqStrings($1, $2)") binaryExpr(p, e, d, "#eqStrings($1, $2)")
@ -1824,7 +1824,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
if t.kind != tyVar: nilCheck = r if t.kind != tyVar: nilCheck = r
r = ropef("(*$1)", [r]) r = ropef("(*$1)", [r])
t = skipTypes(t.lastSon, abstractInst) t = skipTypes(t.lastSon, abstractInst)
if gCmd != cmdCompileToCpp: 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") app(r, ".Sup")
t = skipTypes(t.sons[0], abstractInst) t = skipTypes(t.sons[0], abstractInst)
@ -1842,7 +1842,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
[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 gCmd == cmdCompileToCpp: if p.module.compileToCpp:
expr(p, n.sons[0], d) # downcast does C++ for us expr(p, n.sons[0], d) # downcast does C++ for us
else: else:
var dest = skipTypes(n.typ, abstractPtrs) var dest = skipTypes(n.typ, abstractPtrs)
@ -2028,7 +2028,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
initLocExpr(p, n.sons[0], a) initLocExpr(p, n.sons[0], a)
of nkAsmStmt: genAsmStmt(p, n) of nkAsmStmt: genAsmStmt(p, n)
of nkTryStmt: of nkTryStmt:
if gCmd == cmdCompileToCpp: genTryCpp(p, n, d) if p.module.compileToCpp: genTryCpp(p, n, d)
else: genTry(p, n, d) else: genTry(p, n, d)
of nkRaiseStmt: genRaiseStmt(p, n) of nkRaiseStmt: genRaiseStmt(p, n)
of nkTypeSection: of nkTypeSection:

View file

@ -249,7 +249,7 @@ proc readMergeInfo*(cfilename: string, m: BModule) =
break break
type type
TMergeSections = object {.pure.} TMergeSections = object
f: TCFileSections f: TCFileSections
p: TCProcSections p: TCProcSections

View file

@ -289,8 +289,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
var alreadyPoppedCnt = p.inExceptBlock var alreadyPoppedCnt = p.inExceptBlock
for i in countup(1, howManyTrys): for i in countup(1, howManyTrys):
if not p.module.compileToCpp:
if gCmd != cmdCompileToCpp:
# Pop safe points generated by try # Pop safe points generated by try
if alreadyPoppedCnt > 0: if alreadyPoppedCnt > 0:
dec alreadyPoppedCnt dec alreadyPoppedCnt
@ -312,7 +311,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
for i in countdown(howManyTrys-1, 0): for i in countdown(howManyTrys-1, 0):
p.nestedTryStmts.add(stack[i]) p.nestedTryStmts.add(stack[i])
if gCmd != cmdCompileToCpp: if not p.module.compileToCpp:
# Pop exceptions that was handled by the # Pop exceptions that was handled by the
# except-blocks we are in # except-blocks we are in
for i in countdown(howManyExcepts-1, 0): for i in countdown(howManyExcepts-1, 0):
@ -496,7 +495,7 @@ proc genBreakStmt(p: BProc, t: PNode) =
lineF(p, cpsStmts, "goto $1;$n", [label]) lineF(p, cpsStmts, "goto $1;$n", [label])
proc getRaiseFrmt(p: BProc): string = proc getRaiseFrmt(p: BProc): string =
if gCmd == cmdCompileToCpp: if p.module.compileToCpp:
result = "throw NimException($1, $2);$n" result = "throw NimException($1, $2);$n"
elif getCompilerProc("Exception") != nil: elif getCompilerProc("Exception") != nil:
result = "#raiseException((#Exception*)$1, $2);$n" result = "#raiseException((#Exception*)$1, $2);$n"
@ -517,10 +516,10 @@ proc genRaiseStmt(p: BProc, t: PNode) =
var typ = skipTypes(t.sons[0].typ, abstractPtrs) var typ = skipTypes(t.sons[0].typ, abstractPtrs)
genLineDir(p, t) genLineDir(p, t)
lineCg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)]) lineCg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
else: else:
genLineDir(p, t) genLineDir(p, t)
# reraise the last exception: # reraise the last exception:
if gCmd == cmdCompileToCpp: if p.module.compileToCpp:
line(p, cpsStmts, ~"throw;$n") line(p, cpsStmts, ~"throw;$n")
else: else:
linefmt(p, cpsStmts, "#reraiseException();$n") linefmt(p, cpsStmts, "#reraiseException();$n")

View file

@ -49,8 +49,8 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) =
genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t) genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t)
else: internalError(n.info, "genTraverseProc()") else: internalError(n.info, "genTraverseProc()")
proc parentObj(accessor: PRope): PRope {.inline.} = proc parentObj(accessor: PRope; m: BModule): PRope {.inline.} =
if gCmd != cmdCompileToCpp: if not m.compileToCpp:
result = ropef("$1.Sup", accessor) result = ropef("$1.Sup", accessor)
else: else:
result = accessor result = accessor
@ -71,7 +71,7 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
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, typ.sons[i]) genTraverseProc(c, accessor.parentObj(c.p.module), typ.sons[i])
if typ.n != nil: genTraverseProc(c, accessor, typ.n) if typ.n != nil: genTraverseProc(c, accessor, typ.n)
of tyTuple: of tyTuple:
let typ = getUniqueType(typ) let typ = getUniqueType(typ)
@ -91,7 +91,7 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: PRope, typ: PType) =
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 gCmd != cmdCompileToCpp: "Sup.len" else: "len")) i.r, accessor, toRope(if c.p.module.compileToCpp: "len" else: "Sup.len"))
genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0]) genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0])
lineF(p, cpsStmts, "}$n") lineF(p, cpsStmts, "}$n")

View file

@ -342,8 +342,8 @@ proc getTypePre(m: BModule, typ: PType): PRope =
proc structOrUnion(t: PType): PRope = proc structOrUnion(t: PType): PRope =
(if tfUnion in t.flags: toRope("union") else: toRope("struct")) (if tfUnion in t.flags: toRope("union") else: toRope("struct"))
proc getForwardStructFormat(): string = proc getForwardStructFormat(m: BModule): string =
if gCmd == cmdCompileToCpp: 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): PRope =
@ -355,7 +355,7 @@ 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(), appf(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 & ')')
@ -442,7 +442,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: PRope,
else: else:
appcg(m, result, " {$n#TNimType* m_type;$n", [name, attribute]) appcg(m, result, " {$n#TNimType* m_type;$n", [name, attribute])
hasField = true hasField = true
elif gCmd == cmdCompileToCpp: elif m.compileToCpp:
appcg(m, result, " : public $1 {$n", appcg(m, result, " : public $1 {$n",
[getTypeDescAux(m, typ.sons[0], check)]) [getTypeDescAux(m, typ.sons[0], check)])
hasField = true hasField = true
@ -538,7 +538,7 @@ 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(), appf(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)
@ -550,7 +550,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
cSeq = "struct $2 {$n" & cSeq = "struct $2 {$n" &
" #TGenericSeq Sup;$n" " #TGenericSeq Sup;$n"
appcg(m, m.s[cfsSeqTypes], appcg(m, m.s[cfsSeqTypes],
(if gCmd == cmdCompileToCpp: cppSeq else: cSeq) & (if m.compileToCpp: cppSeq else: cSeq) &
" $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:
@ -570,7 +570,7 @@ 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(), appf(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:

View file

@ -171,7 +171,7 @@ proc mangle*(name: string): string =
## Lowercases the given name and manges any non-alphanumeric characters ## Lowercases the given name and manges any non-alphanumeric characters
## so they are represented as `HEX____`. If the name starts with a number, ## so they are represented as `HEX____`. If the name starts with a number,
## `N` is prepended ## `N` is prepended
result = "" result = newStringOfCap(name.len)
case name[0] case name[0]
of Letters: of Letters:
result.add(name[0].toLower) result.add(name[0].toLower)

View file

@ -297,6 +297,9 @@ proc accessThreadLocalVar(p: BProc, s: PSym)
proc emulatedThreadVars(): bool {.inline.} proc emulatedThreadVars(): bool {.inline.}
proc genProc(m: BModule, prc: PSym) proc genProc(m: BModule, prc: PSym)
template compileToCpp(m: BModule): expr =
gCmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags
include "ccgtypes.nim" include "ccgtypes.nim"
# ------------------------------ Manager of temporaries ------------------ # ------------------------------ Manager of temporaries ------------------
@ -326,7 +329,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
var r = rdLoc(a) var r = rdLoc(a)
if not takeAddr: r = ropef("(*$1)", [r]) if not takeAddr: r = ropef("(*$1)", [r])
var s = skipTypes(t, abstractInst) var s = skipTypes(t, abstractInst)
if gCmd != cmdCompileToCpp: 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") app(r, ".Sup")
s = skipTypes(s.sons[0], abstractInst) s = skipTypes(s.sons[0], abstractInst)
@ -506,7 +509,7 @@ proc assignLocalVar(p: BProc, s: PSym) =
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds: #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
# app(decl, " GC_GUARD") # app(decl, " GC_GUARD")
if sfVolatile in s.flags or (p.nestedTryStmts.len > 0 and if sfVolatile in s.flags or (p.nestedTryStmts.len > 0 and
gCmd != cmdCompileToCpp): not p.module.compileToCpp):
app(decl, " volatile") app(decl, " volatile")
appf(decl, " $1;$n", [s.loc.r]) appf(decl, " $1;$n", [s.loc.r])
else: else:
@ -587,8 +590,8 @@ proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
initLoc(result, locNone, e.typ, OnUnknown) initLoc(result, locNone, e.typ, OnUnknown)
expr(p, e, result) expr(p, e, result)
proc lenField: PRope {.inline.} = proc lenField(p: BProc): PRope =
result = toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len") result = toRope(if p.module.compileToCpp: "len" else: "Sup.len")
include ccgcalls, "ccgstmts.nim", "ccgexprs.nim" include ccgcalls, "ccgstmts.nim", "ccgexprs.nim"
@ -812,7 +815,12 @@ proc genProcAux(m: BModule, prc: PSym) =
app(generatedProc, returnStmt) app(generatedProc, returnStmt)
app(generatedProc, ~"}$N") app(generatedProc, ~"}$N")
app(m.s[cfsProcs], generatedProc) app(m.s[cfsProcs], generatedProc)
proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} =
result = sfCompileToCpp in m.module.flags and
sfCompileToCpp notin sym.getModule().flags and
gCmd != cmdCompileToCpp
proc genProcPrototype(m: BModule, sym: PSym) = proc genProcPrototype(m: BModule, sym: PSym) =
useHeader(m, sym) useHeader(m, sym)
if lfNoDecl in sym.loc.flags: return if lfNoDecl in sym.loc.flags: return
@ -824,6 +832,8 @@ proc genProcPrototype(m: BModule, sym: PSym) =
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect) if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
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):
header = con("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.app(" __attribute__((naked))")
app(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header)) app(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header))
@ -915,7 +925,7 @@ proc addIntTypes(result: var PRope) {.inline.} =
appf(result, "#define NIM_INTBITS $1", [ appf(result, "#define NIM_INTBITS $1", [
platform.CPU[targetCPU].intSize.toRope]) platform.CPU[targetCPU].intSize.toRope])
proc getCopyright(cfilenoext: string): PRope = proc getCopyright(cfile: string): PRope =
if optCompileOnly in gGlobalOptions: if optCompileOnly in gGlobalOptions:
result = ropeff("/* Generated by Nim Compiler v$1 */$N" & result = ropeff("/* Generated by Nim Compiler v$1 */$N" &
"/* (c) 2014 Andreas Rumpf */$N" & "/* (c) 2014 Andreas Rumpf */$N" &
@ -935,10 +945,10 @@ proc getCopyright(cfilenoext: string): PRope =
toRope(platform.OS[targetOS].name), toRope(platform.OS[targetOS].name),
toRope(platform.CPU[targetCPU].name), toRope(platform.CPU[targetCPU].name),
toRope(extccomp.CC[extccomp.cCompiler].name), toRope(extccomp.CC[extccomp.cCompiler].name),
toRope(getCompileCFileCmd(cfilenoext))]) toRope(getCompileCFileCmd(cfile))])
proc getFileHeader(cfilenoext: string): PRope = proc getFileHeader(cfile: string): PRope =
result = getCopyright(cfilenoext) result = getCopyright(cfile)
addIntTypes(result) addIntTypes(result)
proc genFilenames(m: BModule): PRope = proc genFilenames(m: BModule): PRope =
@ -1078,9 +1088,9 @@ proc registerModuleToMain(m: PSym) =
var var
init = m.getInitName init = m.getInitName
datInit = m.getDatInitName datInit = m.getDatInitName
appff(mainModProcs, "N_NOINLINE(void, $1)(void);$N", appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N",
"declare void $1() noinline$N", [init]) "declare void $1() noinline$N", [init])
appff(mainModProcs, "N_NOINLINE(void, $1)(void);$N", appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N",
"declare void $1() noinline$N", [datInit]) "declare void $1() noinline$N", [datInit])
if sfSystemModule notin m.flags: if sfSystemModule notin m.flags:
appff(mainDatInit, "\t$1();$N", "call void ()* $1$n", [datInit]) appff(mainDatInit, "\t$1();$N", "call void ()* $1$n", [datInit])
@ -1092,7 +1102,7 @@ proc registerModuleToMain(m: PSym) =
proc genInitCode(m: BModule) = proc genInitCode(m: BModule) =
var initname = getInitName(m.module) var initname = getInitName(m.module)
var prc = ropeff("N_NOINLINE(void, $1)(void) {$N", var prc = ropeff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N",
"define void $1() noinline {$n", [initname]) "define void $1() noinline {$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",
@ -1135,7 +1145,7 @@ proc genInitCode(m: BModule) =
app(prc, deinitGCFrame(m.initProc)) app(prc, deinitGCFrame(m.initProc))
appf(prc, "}$N$N") appf(prc, "}$N$N")
prc.appff("N_NOINLINE(void, $1)(void) {$N", prc.appff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N",
"define void $1() noinline {$n", [getDatInitName(m.module)]) "define void $1() noinline {$n", [getDatInitName(m.module)])
for i in cfsTypeInit1..cfsDynLibInit: for i in cfsTypeInit1..cfsDynLibInit:
@ -1155,8 +1165,8 @@ proc genInitCode(m: BModule) =
(i.ord - '0'.ord).toRope, el) (i.ord - '0'.ord).toRope, el)
app(m.s[cfsInitProc], ex) app(m.s[cfsInitProc], ex)
proc genModule(m: BModule, cfilenoext: string): PRope = proc genModule(m: BModule, cfile: string): PRope =
result = getFileHeader(cfilenoext) result = getFileHeader(cfile)
result.app(genMergeInfo(m)) result.app(genMergeInfo(m))
generateHeaders(m) generateHeaders(m)
@ -1297,7 +1307,11 @@ proc writeHeader(m: BModule) =
writeRope(result, m.filename) writeRope(result, m.filename)
proc getCFile(m: BModule): string = proc getCFile(m: BModule): string =
result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), cExt) let ext =
if m.compileToCpp: ".cpp"
elif gCmd == cmdCompileToOC or sfCompileToObjC in m.module.flags: ".m"
else: ".c"
result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), ext)
proc myOpenCached(module: PSym, rd: PRodReader): PPassContext = proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
assert optSymbolFiles in gGlobalOptions assert optSymbolFiles in gGlobalOptions
@ -1326,10 +1340,10 @@ proc finishModule(m: BModule) =
dec(gForwardedProcsCounter, i) dec(gForwardedProcsCounter, i)
setLen(m.forwardedProcs, 0) setLen(m.forwardedProcs, 0)
proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool = proc shouldRecompile(code: PRope, cfile: string): bool =
result = true result = true
if optForceFullMake notin gGlobalOptions: if optForceFullMake notin gGlobalOptions:
var objFile = toObjFile(cfilenoext) var objFile = toObjFile(cfile)
if writeRopeIfNotEqual(code, cfile): return if writeRopeIfNotEqual(code, cfile): return
if existsFile(objFile) and os.fileNewer(objFile, cfile): result = false if existsFile(objFile) and os.fileNewer(objFile, cfile): result = false
else: else:
@ -1354,26 +1368,26 @@ proc writeModule(m: BModule, pending: bool) =
app(m.s[cfsProcHeaders], mainModProcs) app(m.s[cfsProcHeaders], mainModProcs)
generateThreadVarsSize(m) generateThreadVarsSize(m)
var code = genModule(m, cfilenoext) var code = genModule(m, cfile)
when hasTinyCBackend: when hasTinyCBackend:
if gCmd == cmdRun: if gCmd == cmdRun:
tccgen.compileCCode(ropeToStr(code)) tccgen.compileCCode(ropeToStr(code))
return return
if shouldRecompile(code, cfile, cfilenoext): if shouldRecompile(code, cfile):
addFileToCompile(cfilenoext) addFileToCompile(cfile)
elif pending and mergeRequired(m) and sfMainModule notin m.module.flags: elif pending and mergeRequired(m) and sfMainModule notin m.module.flags:
mergeFiles(cfile, m) mergeFiles(cfile, m)
genInitCode(m) genInitCode(m)
finishTypeDescriptions(m) finishTypeDescriptions(m)
var code = genModule(m, cfilenoext) var code = genModule(m, cfile)
writeRope(code, cfile) writeRope(code, cfile)
addFileToCompile(cfilenoext) addFileToCompile(cfile)
elif not existsFile(toObjFile(cfilenoext)): elif not existsFile(toObjFile(cfilenoext)):
# Consider: first compilation compiles ``system.nim`` and produces # Consider: first compilation compiles ``system.nim`` and produces
# ``system.c`` but then compilation fails due to an error. This means # ``system.c`` but then compilation fails due to an error. This means
# that ``system.o`` is missing, so we need to call the C compiler for it: # that ``system.o`` is missing, so we need to call the C compiler for it:
addFileToCompile(cfilenoext) addFileToCompile(cfile)
addFileToLink(cfilenoext) addFileToLink(cfilenoext)
@ -1385,9 +1399,9 @@ proc updateCachedModule(m: BModule) =
mergeFiles(cfile, m) mergeFiles(cfile, m)
genInitCode(m) genInitCode(m)
finishTypeDescriptions(m) finishTypeDescriptions(m)
var code = genModule(m, cfilenoext) var code = genModule(m, cfile)
writeRope(code, cfile) writeRope(code, cfile)
addFileToCompile(cfilenoext) addFileToCompile(cfile)
addFileToLink(cfilenoext) addFileToLink(cfilenoext)

View file

@ -323,10 +323,7 @@ const
var var
cCompiler* = ccGcc # the used compiler cCompiler* = ccGcc # the used compiler
gMixedMode*: bool # true if some module triggered C++ codegen
cExt* = ".c" # extension of generated C/C++ files
# (can be changed to .cpp later)
cIncludes*: seq[string] = @[] # directories to search for included files cIncludes*: seq[string] = @[] # directories to search for included files
cLibs*: seq[string] = @[] # directories to search for lib files cLibs*: seq[string] = @[] # directories to search for lib files
cLinkedLibs*: seq[string] = @[] # libraries to link cLinkedLibs*: seq[string] = @[] # libraries to link
@ -387,8 +384,6 @@ proc initVars*() =
# we need to define the symbol here, because ``CC`` may have never been set! # we need to define the symbol here, because ``CC`` may have never been set!
for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name) for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name)
defineSymbol(CC[cCompiler].name) defineSymbol(CC[cCompiler].name)
if gCmd == cmdCompileToCpp: cExt = ".cpp"
elif gCmd == cmdCompileToOC: cExt = ".m"
addCompileOption(getConfigVar(cCompiler, ".options.always")) addCompileOption(getConfigVar(cCompiler, ".options.always"))
addLinkOption(getConfigVar(cCompiler, ".options.linker")) addLinkOption(getConfigVar(cCompiler, ".options.linker"))
if len(ccompilerpath) == 0: if len(ccompilerpath) == 0:
@ -397,9 +392,9 @@ proc initVars*() =
proc completeCFilePath*(cfile: string, createSubDir: bool = true): string = proc completeCFilePath*(cfile: string, createSubDir: bool = true): string =
result = completeGeneratedFilePath(cfile, createSubDir) result = completeGeneratedFilePath(cfile, createSubDir)
proc toObjFile*(filenameWithoutExt: string): string = proc toObjFile*(filename: string): string =
# Object file for compilation # Object file for compilation
result = changeFileExt(filenameWithoutExt, CC[cCompiler].objExt) result = changeFileExt(filename, CC[cCompiler].objExt)
proc addFileToCompile*(filename: string) = proc addFileToCompile*(filename: string) =
appendStr(toCompile, filename) appendStr(toCompile, filename)
@ -497,6 +492,7 @@ proc getCompilerExe(compiler: TSystemCC): string =
proc getLinkerExe(compiler: TSystemCC): string = proc getLinkerExe(compiler: TSystemCC): string =
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler
else: compiler.getCompilerExe else: compiler.getCompilerExe
proc getCompileCFileCmd*(cfilename: string, isExternal = false): string = proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
@ -507,11 +503,11 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
if needsExeExt(): exe = addFileExt(exe, "exe") if needsExeExt(): exe = addFileExt(exe, "exe")
if optGenDynLib in gGlobalOptions and if optGenDynLib in gGlobalOptions and
ospNeedsPIC in platform.OS[targetOS].props: ospNeedsPIC in platform.OS[targetOS].props:
add(options, ' ' & CC[c].pic) add(options, ' ' & CC[c].pic)
var includeCmd, compilePattern: string var includeCmd, compilePattern: string
if not noAbsolutePaths(): if not noAbsolutePaths():
# compute include paths: # compute include paths:
includeCmd = CC[c].includeCmd & quoteShell(libpath) includeCmd = CC[c].includeCmd & quoteShell(libpath)
@ -519,26 +515,27 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
includeCmd.add([CC[c].includeCmd, includeDir.quoteShell]) includeCmd.add([CC[c].includeCmd, includeDir.quoteShell])
compilePattern = joinPath(ccompilerpath, exe) compilePattern = joinPath(ccompilerpath, exe)
else: else:
includeCmd = "" includeCmd = ""
compilePattern = c.getCompilerExe compilePattern = c.getCompilerExe
var cfile = if noAbsolutePaths(): extractFilename(cfilename) var cfile = if noAbsolutePaths(): extractFilename(cfilename)
else: cfilename else: cfilename
var objfile = if not isExternal or noAbsolutePaths(): var objfile = if not isExternal or noAbsolutePaths():
toObjFile(cfile) toObjFile(cfile)
else: else:
completeCFilePath(toObjFile(cfile)) completeCFilePath(toObjFile(cfile))
cfile = quoteShell(addFileExt(cfile, cExt))
objfile = quoteShell(objfile) objfile = quoteShell(objfile)
result = quoteShell(compilePattern % [ result = quoteShell(compilePattern % [
"file", cfile, "objfile", objfile, "options", options, "file", cfile, "objfile", objfile, "options", options,
"include", includeCmd, "nimrod", getPrefixDir(), "lib", libpath]) "include", includeCmd, "nimrod", getPrefixDir(),
"nim", getPrefixDir(), "lib", libpath])
add(result, ' ') add(result, ' ')
addf(result, CC[c].compileTmpl, [ addf(result, CC[c].compileTmpl, [
"file", cfile, "objfile", objfile, "file", cfile, "objfile", objfile,
"options", options, "include", includeCmd, "options", options, "include", includeCmd,
"nimrod", quoteShell(getPrefixDir()), "nimrod", quoteShell(getPrefixDir()),
"nim", quoteShell(getPrefixDir()),
"lib", quoteShell(libpath)]) "lib", quoteShell(libpath)])
proc footprint(filename: string): TCrc32 = proc footprint(filename: string): TCrc32 =
@ -668,7 +665,7 @@ proc callCCompiler*(projectfile: string) =
proc genMappingFiles(list: TLinkedList): PRope = proc genMappingFiles(list: TLinkedList): PRope =
var it = PStrEntry(list.head) var it = PStrEntry(list.head)
while it != nil: while it != nil:
appf(result, "--file:r\"$1\"$N", [toRope(addFileExt(it.data, cExt))]) appf(result, "--file:r\"$1\"$N", [toRope(it.data)])
it = PStrEntry(it.next) it = PStrEntry(it.next)
proc writeMapping*(gSymbolMapping: PRope) = proc writeMapping*(gSymbolMapping: PRope) =

View file

@ -272,13 +272,11 @@ proc mainCommand* =
gCmd = cmdCompileToC gCmd = cmdCompileToC
commandCompileToC() commandCompileToC()
of "cpp", "compiletocpp": of "cpp", "compiletocpp":
extccomp.cExt = ".cpp"
gCmd = cmdCompileToCpp gCmd = cmdCompileToCpp
if cCompiler == ccGcc: setCC("gcc") if cCompiler == ccGcc: setCC("gcc")
defineSymbol("cpp") defineSymbol("cpp")
commandCompileToC() commandCompileToC()
of "objc", "compiletooc": of "objc", "compiletooc":
extccomp.cExt = ".m"
gCmd = cmdCompileToOC gCmd = cmdCompileToOC
defineSymbol("objc") defineSymbol("objc")
commandCompileToC() commandCompileToC()

View file

@ -128,12 +128,17 @@ proc processImportCpp(s: PSym, extname: string) =
incl(s.flags, sfImportc) incl(s.flags, sfImportc)
incl(s.flags, sfInfixCall) incl(s.flags, sfInfixCall)
excl(s.flags, sfForward) excl(s.flags, sfForward)
let m = s.getModule()
incl(m.flags, sfCompileToCpp)
extccomp.gMixedMode = true
proc processImportObjC(s: PSym, extname: string) = proc processImportObjC(s: PSym, extname: string) =
setExternName(s, extname) setExternName(s, extname)
incl(s.flags, sfImportc) incl(s.flags, sfImportc)
incl(s.flags, sfNamedParamCall) incl(s.flags, sfNamedParamCall)
excl(s.flags, sfForward) excl(s.flags, sfForward)
let m = s.getModule()
incl(m.flags, sfCompileToObjC)
proc newEmptyStrNode(n: PNode): PNode {.noinline.} = proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
result = newNodeIT(nkStrLit, n.info, getSysType(tyString)) result = newNodeIT(nkStrLit, n.info, getSysType(tyString))

View file

@ -1,7 +1,7 @@
/* /*
Nimrod's Runtime Library Nim's Runtime Library
(c) Copyright 2013 Andreas Rumpf (c) Copyright 2014 Andreas Rumpf
See the file "copying.txt", included in this See the file "copying.txt", included in this
distribution, for details about the copyright. distribution, for details about the copyright.
@ -384,3 +384,9 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
"error: 'assert_numbits' declared as an array with a negative size" */ "error: 'assert_numbits' declared as an array with a negative size" */
typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1]; typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
#endif #endif
#ifdef __cplusplus
# define NIM_EXTERNC extern "C"
#else
# define NIM_EXTERNC
#endif

View file

@ -3,8 +3,6 @@ version 0.10
- Test nimfix on various babel packages - Test nimfix on various babel packages
- VM: Pegs do not work at compile-time
- VM: ptr/ref T cannot work in general
version 0.9.6 version 0.9.6
============= =============
@ -41,6 +39,8 @@ Misc
Bugs Bugs
==== ====
- VM: Pegs do not work at compile-time
- VM: ptr/ref T cannot work in general
- scopes are still broken for generic instantiation! - scopes are still broken for generic instantiation!
- bug: type conversions concerning proc types are weird - bug: type conversions concerning proc types are weird
- compilation of niminst takes way too long. looks like a regression - compilation of niminst takes way too long. looks like a regression

View file

@ -52,13 +52,30 @@ News
- Recursive tuple types are not allowed anymore. Use ``object`` instead. - Recursive tuple types are not allowed anymore. Use ``object`` instead.
Compiler Additions
------------------
- The compiler now supports *mixed* Objective C / C++ / C code generation:
The modules that use ``importCpp`` or ``importObjc`` are compiled to C++
or Objective C code, any other module is compiled to C code. This
improves interoperability.
Language Additions Language Additions
------------------ ------------------
- There is a new ``parallel`` statement for safe fork&join parallel computing. - There is a new ``parallel`` statement for safe fork&join parallel computing.
- ``guard`` and ``lock`` pragmas have been implemented to support safer - ``guard`` and ``lock`` pragmas have been implemented to support safer
concurrent programming. concurrent programming.
- ``system.writeFile`` can be used at compile-time. - The following procs are now available at compile-time::
math.sqrt, math.ln, math.log10, math.log2, math.exp, math.round,
math.arccos, math.arcsin, math.arctan, math.arctan2, math.cos, math.cosh,
math.hypot, math.sinh, math.sin, math.tan, math.tanh, math.pow,
math.trunc, math.floor, math.ceil, math.fmod,
os.getEnv, os.existsEnv, os.dirExists, os.fileExists,
system.writeFile
Library Additions Library Additions
----------------- -----------------