mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 04:02:41 +00:00
support for C++ code generation; importcpp and importobjc pragmas
This commit is contained in:
@@ -187,11 +187,9 @@ type
|
||||
TNodeKinds* = set[TNodeKind]
|
||||
|
||||
type
|
||||
TSymFlag* = enum # already 29 flags!
|
||||
TSymFlag* = enum # already 29 flags!
|
||||
sfUsed, # read access of sym (for warnings) or simply used
|
||||
sfStar, # symbol has * visibility
|
||||
sfMinus, # symbol has - visibility
|
||||
sfInInterface, # symbol is in interface section declared
|
||||
sfExported, # symbol is exported from module
|
||||
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
||||
# for symbol file generation; such symbols should always
|
||||
# be written into the ROD file
|
||||
@@ -221,7 +219,11 @@ type
|
||||
sfThreadVar, # variable is a thread variable
|
||||
sfMerge, # proc can be merged with itself
|
||||
sfDeadCodeElim, # dead code elimination for the module is turned on
|
||||
sfBorrow # proc is borrowed
|
||||
sfBorrow, # proc is borrowed
|
||||
sfInfixCall, # symbol needs infix call syntax in target language;
|
||||
# for interfacing with C++, JS
|
||||
sfNamedParamCall # symbol needs named parameter call syntax in target
|
||||
# language; for interfacing with Objective C
|
||||
|
||||
TSymFlags* = set[TSymFlag]
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
proc lenField: PRope {.inline.} =
|
||||
result = toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len")
|
||||
|
||||
# -------------------------- constant expressions ------------------------
|
||||
|
||||
proc intLiteral(i: biggestInt): PRope =
|
||||
@@ -682,12 +685,12 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
|
||||
if (optBoundsCheck in p.options):
|
||||
if ty.kind == tyString:
|
||||
appcg(p, cpsStmts,
|
||||
"if ((NU)($1) > (NU)($2->Sup.len)) #raiseIndexError();$n",
|
||||
[rdLoc(b), rdLoc(a)])
|
||||
"if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
|
||||
[rdLoc(b), rdLoc(a), lenField()])
|
||||
else:
|
||||
appcg(p, cpsStmts,
|
||||
"if ((NU)($1) >= (NU)($2->Sup.len)) #raiseIndexError();$n",
|
||||
[rdLoc(b), rdLoc(a)])
|
||||
"if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
||||
[rdLoc(b), rdLoc(a), lenField()])
|
||||
if d.k == locNone: d.s = OnHeap
|
||||
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
||||
a.r = ropef("(*$1)", [a.r])
|
||||
@@ -781,29 +784,12 @@ proc genEcho(p: BProc, n: PNode) =
|
||||
appcg(p, cpsStmts, "printf($1$2);$n", [
|
||||
makeCString(repeatStr(n.len-1, "%s") & tnl), args])
|
||||
|
||||
proc genCall(p: BProc, t: PNode, d: var TLoc) =
|
||||
var op, a: TLoc
|
||||
# this is a hotspot in the compiler
|
||||
initLocExpr(p, t.sons[0], op)
|
||||
var pl = con(op.r, "(")
|
||||
proc fixupCall(p: BProc, t: PNode, d: var TLoc, pl: PRope) =
|
||||
var pl = pl
|
||||
var typ = t.sons[0].typ # getUniqueType() is too expensive here!
|
||||
assert(typ.kind == tyProc)
|
||||
var invalidRetType = isInvalidReturnType(typ.sons[0])
|
||||
var length = sonsLen(t)
|
||||
for i in countup(1, length - 1):
|
||||
initLocExpr(p, t.sons[i], a) # generate expression for param
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
if (i < sonsLen(typ)):
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
var param = typ.n.sons[i].sym
|
||||
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
|
||||
else: app(pl, rdLoc(a))
|
||||
else:
|
||||
app(pl, rdLoc(a))
|
||||
if i < length - 1: app(pl, ", ")
|
||||
if typ.sons[0] != nil:
|
||||
if invalidRetType:
|
||||
if length > 1: app(pl, ", ")
|
||||
if isInvalidReturnType(typ.sons[0]):
|
||||
if sonsLen(t) > 1: app(pl, ", ")
|
||||
# beware of 'result = p(result)'. We always allocate a temporary:
|
||||
if d.k in {locTemp, locNone}:
|
||||
# We already got a temp. Great, special case it:
|
||||
@@ -832,7 +818,127 @@ proc genCall(p: BProc, t: PNode, d: var TLoc) =
|
||||
app(pl, ")")
|
||||
app(p.s[cpsStmts], pl)
|
||||
app(p.s[cpsStmts], ';' & tnl)
|
||||
|
||||
proc genCall(p: BProc, t: PNode, d: var TLoc) =
|
||||
var op, a: TLoc
|
||||
# this is a hotspot in the compiler
|
||||
initLocExpr(p, t.sons[0], op)
|
||||
var pl = con(op.r, "(")
|
||||
var typ = t.sons[0].typ # getUniqueType() is too expensive here!
|
||||
assert(typ.kind == tyProc)
|
||||
var length = sonsLen(t)
|
||||
for i in countup(1, length - 1):
|
||||
initLocExpr(p, t.sons[i], a) # generate expression for param
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
if i < sonsLen(typ):
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
var param = typ.n.sons[i].sym
|
||||
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
|
||||
else: app(pl, rdLoc(a))
|
||||
else:
|
||||
app(pl, rdLoc(a))
|
||||
if i < length - 1: app(pl, ", ")
|
||||
fixupCall(p, t, d, pl)
|
||||
|
||||
proc genInfixCall(p: BProc, t: PNode, d: var TLoc) =
|
||||
var op, a: TLoc
|
||||
initLocExpr(p, t.sons[0], op)
|
||||
var pl: PRope = nil
|
||||
var typ = t.sons[0].typ # getUniqueType() is too expensive here!
|
||||
assert(typ.kind == tyProc)
|
||||
var length = sonsLen(t)
|
||||
initLocExpr(p, t.sons[1], a) # generate expression for first param
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
|
||||
var param = typ.n.sons[1].sym
|
||||
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
|
||||
else: app(pl, rdLoc(a))
|
||||
|
||||
if skipTypes(param.typ, {tyGenericInst}).kind == tyPtr: app(pl, "->")
|
||||
else: app(pl, ".")
|
||||
app(pl, op.r)
|
||||
app(pl, "(")
|
||||
for i in countup(2, length - 1):
|
||||
initLocExpr(p, t.sons[i], a) # generate expression for param
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
if i < sonsLen(typ):
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
var param = typ.n.sons[i].sym
|
||||
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
|
||||
else: app(pl, rdLoc(a))
|
||||
else:
|
||||
app(pl, rdLoc(a))
|
||||
if i < length - 1: app(pl, ", ")
|
||||
fixupCall(p, t, d, pl)
|
||||
|
||||
proc genNamedParamCall(p: BProc, t: PNode, d: var TLoc) =
|
||||
# generates a crappy ObjC call
|
||||
var op, a: TLoc
|
||||
initLocExpr(p, t.sons[0], op)
|
||||
var pl = toRope"["
|
||||
var typ = t.sons[0].typ # getUniqueType() is too expensive here!
|
||||
assert(typ.kind == tyProc)
|
||||
var length = sonsLen(t)
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
|
||||
if length > 1:
|
||||
initLocExpr(p, t.sons[1], a)
|
||||
var param = typ.n.sons[1].sym
|
||||
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
|
||||
else: app(pl, rdLoc(a))
|
||||
app(pl, " ")
|
||||
app(pl, op.r)
|
||||
if length > 2:
|
||||
initLocExpr(p, t.sons[2], a)
|
||||
app(pl, ": ")
|
||||
var param = typ.n.sons[2].sym
|
||||
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
|
||||
else: app(pl, rdLoc(a))
|
||||
for i in countup(3, length-1):
|
||||
initLocExpr(p, t.sons[i], a) # generate expression for param
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
if i >= sonsLen(typ):
|
||||
InternalError(t.info, "varargs for objective C method?")
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
var param = typ.n.sons[i].sym
|
||||
app(pl, " ")
|
||||
app(pl, param.name.s)
|
||||
app(pl, ": ")
|
||||
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
|
||||
else: app(pl, rdLoc(a))
|
||||
if typ.sons[0] != nil:
|
||||
if isInvalidReturnType(typ.sons[0]):
|
||||
if sonsLen(t) > 1: app(pl, " ")
|
||||
# beware of 'result = p(result)'. We always allocate a temporary:
|
||||
if d.k in {locTemp, locNone}:
|
||||
# We already got a temp. Great, special case it:
|
||||
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
||||
app(pl, "Result: ")
|
||||
app(pl, addrLoc(d))
|
||||
app(pl, "]")
|
||||
app(p.s[cpsStmts], pl)
|
||||
app(p.s[cpsStmts], ';' & tnl)
|
||||
else:
|
||||
var tmp: TLoc
|
||||
getTemp(p, typ.sons[0], tmp)
|
||||
app(pl, addrLoc(tmp))
|
||||
app(pl, "]")
|
||||
app(p.s[cpsStmts], pl)
|
||||
app(p.s[cpsStmts], ';' & tnl)
|
||||
genAssignment(p, d, tmp, {}) # no need for deep copying
|
||||
else:
|
||||
app(pl, "]")
|
||||
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
||||
assert(d.t != nil) # generate an assignment to d:
|
||||
var list: TLoc
|
||||
initLoc(list, locCall, nil, OnUnknown)
|
||||
list.r = pl
|
||||
genAssignment(p, d, list, {}) # no need for deep copying
|
||||
else:
|
||||
app(pl, "]")
|
||||
app(p.s[cpsStmts], pl)
|
||||
app(p.s[cpsStmts], ';' & tnl)
|
||||
|
||||
proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||
# <Nimrod code>
|
||||
# s = 'Hello ' & name & ', how do you feel?' & 'z'
|
||||
@@ -865,7 +971,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
|
||||
Inc(L, len(e.sons[i + 1].strVal))
|
||||
else:
|
||||
appf(lens, "$1->Sup.len + ", [rdLoc(a)])
|
||||
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
|
||||
appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
|
||||
appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
|
||||
app(p.s[cpsStmts], appends)
|
||||
@@ -906,7 +1012,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
|
||||
Inc(L, len(e.sons[i + 2].strVal))
|
||||
else:
|
||||
appf(lens, "$1->Sup.len + ", [rdLoc(a)])
|
||||
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
|
||||
appcg(p.module, appends, "#appendString($1, $2);$n",
|
||||
[rdLoc(dest), rdLoc(a)])
|
||||
appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
|
||||
@@ -925,7 +1031,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
|
||||
getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))])
|
||||
initLoc(dest, locExpr, b.t, OnHeap)
|
||||
dest.r = ropef("$1->data[$1->Sup.len-1]", [rdLoc(a)])
|
||||
dest.r = ropef("$1->data[$1->$2-1]", [rdLoc(a), lenField()])
|
||||
genAssignment(p, dest, b, {needToCopy, afDestIsNil})
|
||||
|
||||
proc genReset(p: BProc, n: PNode) =
|
||||
@@ -984,7 +1090,8 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||
r = ropecg(p.module, "(($1) && #isObj($2.m_type, $3))",
|
||||
[nilCheck, r, genTypeInfo(p.module, dest)])
|
||||
else:
|
||||
r = ropecg(p.module, "#isObj($1.m_type, $2)", [r, genTypeInfo(p.module, dest)])
|
||||
r = ropecg(p.module, "#isObj($1.m_type, $2)",
|
||||
[r, genTypeInfo(p.module, dest)])
|
||||
putIntoDest(p, d, getSysType(tyBool), r)
|
||||
|
||||
proc genOf(p: BProc, n: PNode, d: var TLoc) =
|
||||
@@ -1041,7 +1148,8 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||
case a.t.kind
|
||||
of tyOpenArray: putIntoDest(p, b, e.typ, rdLoc(a))
|
||||
of tyString, tySequence:
|
||||
putIntoDest(p, b, e.typ, ropef("$1->data, $1->Sup.len", [rdLoc(a)]))
|
||||
putIntoDest(p, b, e.typ,
|
||||
ropef("$1->data, $1->$2", [rdLoc(a), lenField()]))
|
||||
of tyArray, tyArrayConstr:
|
||||
putIntoDest(p, b, e.typ,
|
||||
ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
|
||||
@@ -1080,8 +1188,12 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
|
||||
else: unaryExpr(p, e, d, "strlen($1)")
|
||||
of tyString, tySequence:
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
|
||||
else: unaryExpr(p, e, d, "$1->Sup.len")
|
||||
if gCmd != cmdCompileToCpp:
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
|
||||
else: unaryExpr(p, e, d, "$1->Sup.len")
|
||||
else:
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1->len-1)")
|
||||
else: unaryExpr(p, e, d, "$1->len")
|
||||
of tyArray, tyArrayConstr:
|
||||
# YYY: length(sideeffect) is optimized away incorrectly?
|
||||
if op == mHigh: putIntoDest(p, d, e.typ, toRope(lastOrd(Typ)))
|
||||
@@ -1289,7 +1401,7 @@ proc passToOpenArray(p: BProc, n: PNode, d: var TLoc) =
|
||||
putIntoDest(p, d, dest, ropef("$1, $1Len0", [rdLoc(a)]))
|
||||
of tyString, tySequence:
|
||||
initLocExpr(p, n.sons[0], a)
|
||||
putIntoDest(p, d, dest, ropef("$1->data, $1->Sup.len", [rdLoc(a)]))
|
||||
putIntoDest(p, d, dest, ropef("$1->data, $1->$2", [rdLoc(a), lenField()]))
|
||||
of tyArray, tyArrayConstr:
|
||||
initLocExpr(p, n.sons[0], a)
|
||||
putIntoDest(p, d, dest, ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
|
||||
@@ -1314,10 +1426,12 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
|
||||
binaryExpr(p, e, d, "($1 == $2)")
|
||||
elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
|
||||
initLocExpr(p, e.sons[2], x)
|
||||
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
|
||||
putIntoDest(p, d, e.typ,
|
||||
ropef("(($1) && ($1)->$2 == 0)", [rdLoc(x), lenField()]))
|
||||
elif (b.kind in {nkStrLit..nkTripleStrLit}) and (b.strVal == ""):
|
||||
initLocExpr(p, e.sons[1], x)
|
||||
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
|
||||
putIntoDest(p, d, e.typ,
|
||||
ropef("(($1) && ($1)->$2 == 0)", [rdLoc(x), lenField()]))
|
||||
else:
|
||||
binaryExpr(p, e, d, "#eqStrings($1, $2)")
|
||||
|
||||
@@ -1678,8 +1792,13 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
|
||||
putIntoDest(p, d, e.typ, genLiteral(p, e))
|
||||
of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||
nkCallStrLit:
|
||||
if (e.sons[0].kind == nkSym) and (e.sons[0].sym.magic != mNone):
|
||||
if e.sons[0].kind == nkSym and e.sons[0].sym.magic != mNone:
|
||||
genMagicExpr(p, e, d, e.sons[0].sym.magic)
|
||||
elif e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags and
|
||||
e.len >= 2:
|
||||
genInfixCall(p, e, d)
|
||||
elif e.sons[0].kind == nkSym and sfNamedParamCall in e.sons[0].sym.flags:
|
||||
genNamedParamCall(p, e, d)
|
||||
else:
|
||||
genCall(p, e, d)
|
||||
of nkCurly: genSetConstr(p, e, d)
|
||||
|
||||
@@ -218,10 +218,10 @@ proc genBreakStmt(p: BProc, t: PNode) =
|
||||
appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.blocks[idx].id)])
|
||||
|
||||
proc getRaiseFrmt(p: BProc): string =
|
||||
if gCmd == cmdCompileToCpp:
|
||||
result = "throw #nimException($1, $2);$n"
|
||||
else:
|
||||
result = "#raiseException((#E_Base*)$1, $2);$n"
|
||||
#if gCmd == cmdCompileToCpp:
|
||||
# result = "throw #nimException($1, $2);$n"
|
||||
#else:
|
||||
result = "#raiseException((#E_Base*)$1, $2);$n"
|
||||
|
||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
if t.sons[0].kind != nkEmpty:
|
||||
@@ -234,10 +234,10 @@ proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
else:
|
||||
genLineDir(p, t)
|
||||
# reraise the last exception:
|
||||
if gCmd == cmdCompileToCpp:
|
||||
appcg(p, cpsStmts, "throw;" & tnl)
|
||||
else:
|
||||
appcg(p, cpsStmts, "#reraiseException();" & tnl)
|
||||
#if gCmd == cmdCompileToCpp:
|
||||
# appcg(p, cpsStmts, "throw;" & tnl)
|
||||
#else:
|
||||
appcg(p, cpsStmts, "#reraiseException();" & tnl)
|
||||
|
||||
proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
||||
rangeFormat, eqFormat: TFormatStr, labl: TLabel) =
|
||||
@@ -491,72 +491,6 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
|
||||
if rethrowFlag != nil:
|
||||
appf(p.s[cpsStmts], "if ($1) { throw; }$n", [rethrowFlag])
|
||||
|
||||
proc genTryStmtCpp2(p: BProc, t: PNode) =
|
||||
# code to generate:
|
||||
#
|
||||
# TSafePoint sp;
|
||||
# pushSafePoint(&sp);
|
||||
# sp.status = setjmp(sp.context);
|
||||
# if (sp.status == 0) {
|
||||
# myDiv(4, 9);
|
||||
# popSafePoint();
|
||||
# } else {
|
||||
# popSafePoint();
|
||||
# /* except DivisionByZero: */
|
||||
# if (sp.status == DivisionByZero) {
|
||||
# printf('Division by Zero\n');
|
||||
# clearException();
|
||||
# } else {
|
||||
# clearException();
|
||||
# }
|
||||
# }
|
||||
# /* finally: */
|
||||
# printf('fin!\n');
|
||||
# if (exception not cleared)
|
||||
# propagateCurrentException();
|
||||
genLineDir(p, t)
|
||||
var safePoint = getTempName()
|
||||
discard cgsym(p.module, "E_Base")
|
||||
appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
|
||||
appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
|
||||
"$1.status = setjmp($1.context);$n", [safePoint])
|
||||
if optStackTrace in p.Options:
|
||||
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
|
||||
appf(p.s[cpsStmts], "if ($1.status == 0) {$n", [safePoint])
|
||||
var length = sonsLen(t)
|
||||
add(p.nestedTryStmts, t)
|
||||
genStmts(p, t.sons[0])
|
||||
appcg(p, cpsStmts, "#popSafePoint();$n} else {$n#popSafePoint();$n")
|
||||
var i = 1
|
||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||
var blen = sonsLen(t.sons[i])
|
||||
if blen == 1:
|
||||
# general except section:
|
||||
if i > 1: app(p.s[cpsStmts], "else {" & tnl)
|
||||
genStmts(p, t.sons[i].sons[0])
|
||||
appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();$n", [safePoint])
|
||||
if i > 1: app(p.s[cpsStmts], '}' & tnl)
|
||||
else:
|
||||
var orExpr: PRope = nil
|
||||
for j in countup(0, blen - 2):
|
||||
assert(t.sons[i].sons[j].kind == nkType)
|
||||
if orExpr != nil: app(orExpr, "||")
|
||||
appcg(p.module, orExpr,
|
||||
"#isObj(#getCurrentException()->Sup.m_type, $1)",
|
||||
[genTypeInfo(p.module, t.sons[i].sons[j].typ)])
|
||||
if i > 1: app(p.s[cpsStmts], "else ")
|
||||
appf(p.s[cpsStmts], "if ($1) {$n", [orExpr])
|
||||
genStmts(p, t.sons[i].sons[blen-1])
|
||||
# code to clear the exception:
|
||||
appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();}$n",
|
||||
[safePoint])
|
||||
inc(i)
|
||||
app(p.s[cpsStmts], '}' & tnl) # end of if statement
|
||||
discard pop(p.nestedTryStmts)
|
||||
if i < length and t.sons[i].kind == nkFinally:
|
||||
genStmts(p, t.sons[i].sons[0])
|
||||
appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
|
||||
|
||||
proc genTryStmt(p: BProc, t: PNode) =
|
||||
# code to generate:
|
||||
#
|
||||
@@ -655,7 +589,7 @@ proc genEmit(p: BProc, t: PNode) =
|
||||
var s = genAsmOrEmitStmt(p, t.sons[1])
|
||||
if p.prc == nil:
|
||||
# top level emit pragma?
|
||||
app(p.module.s[cfsProcs], s)
|
||||
app(p.module.s[cfsProcHeaders], s)
|
||||
else:
|
||||
app(p.s[cpsStmts], s)
|
||||
|
||||
@@ -768,8 +702,9 @@ proc genStmts(p: BProc, t: PNode) =
|
||||
initLocExpr(p, t.sons[0], a)
|
||||
of nkAsmStmt: genAsmStmt(p, t)
|
||||
of nkTryStmt:
|
||||
if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t)
|
||||
else: genTryStmt(p, t)
|
||||
#if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t)
|
||||
#else:
|
||||
genTryStmt(p, t)
|
||||
of nkRaiseStmt: genRaiseStmt(p, t)
|
||||
of nkTypeSection:
|
||||
# we have to emit the type information for object types here to support
|
||||
|
||||
@@ -271,9 +271,10 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
|
||||
var r = rdLoc(a)
|
||||
if not takeAddr: r = ropef("(*$1)", [r])
|
||||
var s = skipTypes(t, abstractInst)
|
||||
while (s.kind == tyObject) and (s.sons[0] != nil):
|
||||
app(r, ".Sup")
|
||||
s = skipTypes(s.sons[0], abstractInst)
|
||||
if gCmd != cmdCompileToCpp:
|
||||
while (s.kind == tyObject) and (s.sons[0] != nil):
|
||||
app(r, ".Sup")
|
||||
s = skipTypes(s.sons[0], abstractInst)
|
||||
appcg(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
|
||||
of frEmbedded:
|
||||
# worst case for performance:
|
||||
|
||||
@@ -68,7 +68,8 @@ Options:
|
||||
AdvancedUsage = """
|
||||
Advanced commands:
|
||||
compileToC, cc compile project with C code generator
|
||||
compileToOC, oc compile project to Objective C code
|
||||
compileToCpp, cpp compile project to C++ code
|
||||
compileToOC, objc compile project to Objective C code
|
||||
rst2html convert a reStructuredText file to HTML
|
||||
rst2tex convert a reStructuredText file to TeX
|
||||
run run the project (with Tiny C backend; buggy!)
|
||||
|
||||
@@ -287,7 +287,7 @@ proc isVisible(n: PNode): bool =
|
||||
var v = n.sons[0].ident
|
||||
result = (v.id == ord(wStar)) or (v.id == ord(wMinus))
|
||||
elif n.kind == nkSym:
|
||||
result = sfInInterface in n.sym.flags
|
||||
result = sfExported in n.sym.flags
|
||||
elif n.kind == nkPragmaExpr:
|
||||
result = isVisible(n.sons[0])
|
||||
|
||||
|
||||
@@ -1349,10 +1349,10 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
of nkNilLit:
|
||||
if mapType(n.typ) == etyBaseIndex:
|
||||
r.kind = etyBaseIndex
|
||||
r.com = toRope("null")
|
||||
r.res = toRope("0")
|
||||
r.com = toRope"null"
|
||||
r.res = toRope"0"
|
||||
else:
|
||||
r.res = toRope("null")
|
||||
r.res = toRope"null"
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
if skipTypes(n.typ, abstractVarRange).kind == tyString:
|
||||
useMagic(p, "cstrToNimstr")
|
||||
@@ -1361,11 +1361,11 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
r.res = makeCString(n.strVal)
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
f = n.floatVal
|
||||
if f != f: r.res = toRope("NaN")
|
||||
elif f == 0.0: r.res = toRope("0.0")
|
||||
if f != f: r.res = toRope"NaN"
|
||||
elif f == 0.0: r.res = toRope"0.0"
|
||||
elif f == 0.5 * f:
|
||||
if f > 0.0: r.res = toRope("Infinity")
|
||||
else: r.res = toRope("-Infinity")
|
||||
if f > 0.0: r.res = toRope"Infinity"
|
||||
else: r.res = toRope"-Infinity"
|
||||
else: r.res = toRope(f.ToStrMaxPrecision)
|
||||
of nkBlockExpr: genBlock(p, n, r)
|
||||
of nkIfExpr: genIfExpr(p, n, r)
|
||||
|
||||
@@ -35,7 +35,7 @@ type
|
||||
tkBind, tkBlock, tkBreak, tkCase, tkCast,
|
||||
tkConst, tkContinue, tkConverter, tkDiscard, tkDistinct, tkDiv, tkElif,
|
||||
tkElse, tkEnd, tkEnum, tkExcept, tkFinally, tkFor, tkFrom, tkGeneric, tkIf,
|
||||
tkImplies, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator,
|
||||
tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator,
|
||||
tkLambda, tkLet,
|
||||
tkMacro, tkMethod, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr,
|
||||
tkOut, tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkTemplate,
|
||||
@@ -63,7 +63,7 @@ const
|
||||
"bind", "block", "break", "case", "cast",
|
||||
"const", "continue", "converter", "discard", "distinct", "div", "elif",
|
||||
"else", "end", "enum", "except", "finally", "for", "from", "generic", "if",
|
||||
"implies", "import", "in", "include", "is", "isnot", "iterator",
|
||||
"import", "in", "include", "is", "isnot", "iterator",
|
||||
"lambda", "let",
|
||||
"macro", "method", "mod", "nil", "not", "notin", "object", "of", "or",
|
||||
"out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "template",
|
||||
|
||||
@@ -55,7 +55,7 @@ proc CloseScope*(tab: var TSymTab) =
|
||||
while s != nil:
|
||||
if sfForward in s.flags:
|
||||
LocalError(s.info, errImplOfXexpected, getSymRepr(s))
|
||||
elif {sfUsed, sfInInterface} * s.flags == {} and optHints in s.options:
|
||||
elif {sfUsed, sfExported} * s.flags == {} and optHints in s.options:
|
||||
# BUGFIX: check options in s!
|
||||
if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}:
|
||||
Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
|
||||
@@ -74,7 +74,7 @@ proc addDeclAt*(c: PContext, sym: PSym, at: Natural) =
|
||||
LocalError(sym.info, errAttemptToRedefine, sym.Name.s)
|
||||
|
||||
proc AddInterfaceDeclAux(c: PContext, sym: PSym) =
|
||||
if (sfInInterface in sym.flags):
|
||||
if sfExported in sym.flags:
|
||||
# add to interface:
|
||||
if c.module == nil: InternalError(sym.info, "AddInterfaceDeclAux")
|
||||
StrTableAdd(c.module.tab, sym)
|
||||
|
||||
@@ -199,12 +199,12 @@ proc MainCommand(cmd, filename: string) =
|
||||
gCmd = cmdCompileToC
|
||||
wantFile(filename)
|
||||
CommandCompileToC(filename)
|
||||
of "compiletocpp":
|
||||
of "cpp", "compiletocpp":
|
||||
extccomp.cExt = ".cpp"
|
||||
gCmd = cmdCompileToCpp
|
||||
wantFile(filename)
|
||||
CommandCompileToC(filename)
|
||||
of "oc", "compiletooc":
|
||||
of "objc", "compiletooc":
|
||||
extccomp.cExt = ".m"
|
||||
gCmd = cmdCompileToOC
|
||||
wantFile(filename)
|
||||
|
||||
@@ -80,6 +80,17 @@ Files: "lib/ecmas/*.nim"
|
||||
|
||||
[Other]
|
||||
Files: "examples/*.nim"
|
||||
Files: "examples/gtk/*.nim"
|
||||
Files: "examples/0mq/*.nim"
|
||||
Files: "examples/c++iface/*.nim"
|
||||
Files: "examples/objciface/*.nim"
|
||||
Files: "examples/lazarus/*.nim"
|
||||
Files: "examples/lazarus/*.lpi"
|
||||
Files: "examples/lazarus/*.lpr"
|
||||
Files: "examples/lazarus/*.txt"
|
||||
Files: "examples/lazarus/*.lfm"
|
||||
Files: "examples/lazarus/*.pas"
|
||||
|
||||
Files: "examples/*.html"
|
||||
Files: "examples/*.txt"
|
||||
Files: "examples/*.cfg"
|
||||
|
||||
@@ -22,7 +22,7 @@ const
|
||||
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
||||
wCompilerProc, wPure, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||
wBorrow, wExtern, wImportCompilerProc, wThread}
|
||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC}
|
||||
converterPragmas* = procPragmas
|
||||
methodPragmas* = procPragmas
|
||||
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
@@ -87,6 +87,18 @@ proc processImportCompilerProc(s: PSym, extname: string) =
|
||||
excl(s.flags, sfForward)
|
||||
incl(s.loc.flags, lfImportCompilerProc)
|
||||
|
||||
proc processImportCpp(s: PSym, extname: string) =
|
||||
setExternName(s, extname)
|
||||
incl(s.flags, sfImportc)
|
||||
incl(s.flags, sfInfixCall)
|
||||
excl(s.flags, sfForward)
|
||||
|
||||
proc processImportObjC(s: PSym, extname: string) =
|
||||
setExternName(s, extname)
|
||||
incl(s.flags, sfImportc)
|
||||
incl(s.flags, sfNamedParamCall)
|
||||
excl(s.flags, sfForward)
|
||||
|
||||
proc getStrLitNode(c: PContext, n: PNode): PNode =
|
||||
if n.kind != nkExprColonExpr:
|
||||
GlobalError(n.info, errStringLiteralExpected)
|
||||
@@ -410,7 +422,11 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
of wImportCompilerProc:
|
||||
processImportCompilerProc(sym, getOptionalStr(c, it, sym.name.s))
|
||||
of wExtern: setExternName(sym, expectStrLit(c, it))
|
||||
of wAlign:
|
||||
of wImportCpp:
|
||||
processImportCpp(sym, getOptionalStr(c, it, sym.name.s))
|
||||
of wImportObjC:
|
||||
processImportObjC(sym, getOptionalStr(c, it, sym.name.s))
|
||||
of wAlign:
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
var align = expectIntLit(c, it)
|
||||
if not IsPowerOfTwo(align) and align != 0:
|
||||
|
||||
@@ -265,7 +265,7 @@ proc symStack(w: PRodWriter) =
|
||||
addToIndex(w.index, s.id, L) #intSetIncl(debugWritten, s.id);
|
||||
app(w.data, encodeSym(w, s))
|
||||
app(w.data, rodNL)
|
||||
if sfInInterface in s.flags:
|
||||
if sfExported in s.flags:
|
||||
appf(w.interf, "$1 $2" & rodNL, [encode(s.name.s), encodeInt(s.id)])
|
||||
if sfCompilerProc in s.flags:
|
||||
appf(w.compilerProcs, "$1 $2" & rodNL,
|
||||
@@ -305,7 +305,7 @@ proc rawAddInterfaceSym(w: PRodWriter, s: PSym) =
|
||||
|
||||
proc addInterfaceSym(w: PRodWriter, s: PSym) =
|
||||
if w == nil: return
|
||||
if {sfInInterface, sfCompilerProc} * s.flags != {}:
|
||||
if {sfExported, sfCompilerProc} * s.flags != {}:
|
||||
rawAddInterfaceSym(w, s)
|
||||
|
||||
proc addStmt(w: PRodWriter, n: PNode) =
|
||||
|
||||
@@ -658,7 +658,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if ty.sons[0] == nil: break
|
||||
ty = skipTypes(ty.sons[0], {tyGenericInst})
|
||||
if f != nil:
|
||||
if {sfStar, sfMinus} * f.flags != {} or getModule(f).id == c.module.id:
|
||||
if sfExported in f.flags or getModule(f).id == c.module.id:
|
||||
# is the access to a public field or in the same module?
|
||||
n.sons[0] = makeDeref(n.sons[0])
|
||||
n.sons[1] = newSymNode(f) # we now have the correct field
|
||||
|
||||
@@ -212,7 +212,7 @@ proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
|
||||
|
||||
proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
|
||||
if isTopLevel(c):
|
||||
result = semIdentWithPragma(c, kind, n, {sfStar, sfMinus})
|
||||
result = semIdentWithPragma(c, kind, n, {sfExported})
|
||||
incl(result.flags, sfGlobal)
|
||||
else:
|
||||
result = semIdentWithPragma(c, kind, n, {})
|
||||
@@ -257,7 +257,6 @@ proc semVar(c: PContext, n: PNode): PNode =
|
||||
addSon(result, b)
|
||||
for j in countup(0, length-3):
|
||||
var v = semIdentDef(c, a.sons[j], skVar)
|
||||
if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)
|
||||
addInterfaceDecl(c, v)
|
||||
if a.kind != nkVarTuple:
|
||||
v.typ = typ
|
||||
@@ -300,7 +299,6 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
GlobalError(a.info, errXisNoType, typeToString(typ))
|
||||
v.typ = typ
|
||||
v.ast = def # no need to copy
|
||||
if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)
|
||||
addInterfaceDecl(c, v)
|
||||
var b = newNodeI(nkConstDef, a.info)
|
||||
addSon(b, newSymNode(v))
|
||||
@@ -463,7 +461,6 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
|
||||
if a.kind != nkTypeDef: IllFormedAst(a)
|
||||
checkSonsLen(a, 3)
|
||||
var s = semIdentDef(c, a.sons[0], skType)
|
||||
if s.flags * {sfStar, sfMinus} != {}: incl(s.flags, sfInInterface)
|
||||
s.typ = newTypeS(tyForward, c)
|
||||
s.typ.sym = s # process pragmas:
|
||||
if a.sons[0].kind == nkPragmaExpr:
|
||||
@@ -619,7 +616,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
checkSonsLen(n, codePos + 1)
|
||||
var s = semIdentDef(c, n.sons[0], kind)
|
||||
n.sons[namePos] = newSymNode(s)
|
||||
if sfStar in s.flags: incl(s.flags, sfInInterface)
|
||||
s.ast = n
|
||||
pushOwner(s)
|
||||
openScope(c.tab)
|
||||
|
||||
@@ -158,15 +158,13 @@ proc transformToExpr(n: PNode): PNode =
|
||||
nil
|
||||
|
||||
proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
var
|
||||
s: PSym
|
||||
var s: PSym
|
||||
if c.p.owner.kind == skModule:
|
||||
s = semIdentVis(c, skTemplate, n.sons[0], {sfStar})
|
||||
s = semIdentVis(c, skTemplate, n.sons[0], {sfExported})
|
||||
incl(s.flags, sfGlobal)
|
||||
else:
|
||||
else:
|
||||
s = semIdentVis(c, skTemplate, n.sons[0], {})
|
||||
if sfStar in s.flags:
|
||||
incl(s.flags, sfInInterface) # check parameter list:
|
||||
# check parameter list:
|
||||
pushOwner(s)
|
||||
openScope(c.tab)
|
||||
n.sons[namePos] = newSymNode(s) # check that no pragmas exist:
|
||||
|
||||
@@ -50,8 +50,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
x = counter
|
||||
else:
|
||||
x = getOrdValue(v)
|
||||
if i != 1:
|
||||
if (x != counter): incl(result.flags, tfEnumHasHoles)
|
||||
if i != 1:
|
||||
if x != counter: incl(result.flags, tfEnumHasHoles)
|
||||
if x < counter:
|
||||
GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
|
||||
e.ast = strVal # might be nil
|
||||
@@ -63,9 +63,9 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
else: illFormedAst(n)
|
||||
e.typ = result
|
||||
e.position = int(counter)
|
||||
if (result.sym != nil) and (sfInInterface in result.sym.flags):
|
||||
if result.sym != nil and sfExported in result.sym.flags:
|
||||
incl(e.flags, sfUsed) # BUGFIX
|
||||
incl(e.flags, sfInInterface) # BUGFIX
|
||||
incl(e.flags, sfExported) # BUGFIX
|
||||
StrTableAdd(c.module.tab, e) # BUGFIX
|
||||
addSon(result.n, newSymNode(e))
|
||||
addDeclAt(c, e, c.tab.tos - 1)
|
||||
@@ -240,15 +240,13 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||
if sonsLen(n) == 2 and n.sons[0].kind == nkIdent:
|
||||
result = newSymS(kind, n.sons[1], c)
|
||||
var v = n.sons[0].ident
|
||||
if (sfStar in allowed) and (v.id == ord(wStar)):
|
||||
incl(result.flags, sfStar)
|
||||
elif (sfMinus in allowed) and (v.id == ord(wMinus)):
|
||||
incl(result.flags, sfMinus)
|
||||
else:
|
||||
if sfExported in allowed and v.id == ord(wStar):
|
||||
incl(result.flags, sfExported)
|
||||
else:
|
||||
LocalError(n.sons[0].info, errInvalidVisibilityX, v.s)
|
||||
else:
|
||||
else:
|
||||
illFormedAst(n)
|
||||
else:
|
||||
else:
|
||||
result = newSymS(kind, n, c)
|
||||
|
||||
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
|
||||
@@ -422,7 +420,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
GlobalError(n.info, errTypeExpected)
|
||||
typ = semTypeNode(c, n.sons[length-2], nil)
|
||||
for i in countup(0, sonsLen(n) - 3):
|
||||
f = semIdentWithPragma(c, skField, n.sons[i], {sfStar, sfMinus})
|
||||
f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
|
||||
f.typ = typ
|
||||
f.position = pos
|
||||
if (rectype != nil) and ({sfImportc, sfExportc} * rectype.flags != {}) and
|
||||
|
||||
@@ -131,8 +131,6 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
|
||||
case t.kind
|
||||
of tyGenericParam:
|
||||
result = lookupTypeVar(cl, t)
|
||||
if result.kind == tyGenericInvokation:
|
||||
result = handleGenericInvokation(cl, result)
|
||||
of tyGenericInvokation:
|
||||
result = handleGenericInvokation(cl, t)
|
||||
of tyGenericBody:
|
||||
|
||||
@@ -76,15 +76,15 @@ proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
||||
a.baseTypeMatch = b.baseTypeMatch
|
||||
copyIdTable(a.bindings, b.bindings)
|
||||
|
||||
proc cmpCandidates*(a, b: TCandidate): int =
|
||||
proc cmpCandidates*(a, b: TCandidate): int =
|
||||
result = a.exactMatches - b.exactMatches
|
||||
if result != 0: return
|
||||
if result != 0: return
|
||||
result = a.genericMatches - b.genericMatches
|
||||
if result != 0: return
|
||||
if result != 0: return
|
||||
result = a.subtypeMatches - b.subtypeMatches
|
||||
if result != 0: return
|
||||
if result != 0: return
|
||||
result = a.intConvMatches - b.intConvMatches
|
||||
if result != 0: return
|
||||
if result != 0: return
|
||||
result = a.convMatches - b.convMatches
|
||||
|
||||
proc writeMatches(c: TCandidate) =
|
||||
@@ -397,13 +397,13 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||
InternalError("wrong instantiated type!")
|
||||
if typeRel(mapping, f.sons[i], a.sons[i]) < isGeneric: return
|
||||
result = isGeneric
|
||||
else:
|
||||
else:
|
||||
result = typeRel(mapping, f.sons[0], a)
|
||||
if result != isNone:
|
||||
if result != isNone:
|
||||
# we steal the generic parameters from the tyGenericBody:
|
||||
for i in countup(1, sonsLen(f) - 1):
|
||||
for i in countup(1, sonsLen(f) - 1):
|
||||
var x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
|
||||
if (x == nil) or (x.kind == tyGenericParam):
|
||||
if x == nil or x.kind == tyGenericParam:
|
||||
InternalError("wrong instantiated type!")
|
||||
idTablePut(mapping, f.sons[i], x)
|
||||
of tyGenericParam:
|
||||
@@ -522,7 +522,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||
|
||||
proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
arg: PNode): PNode =
|
||||
if (arg == nil) or (arg.kind != nkSymChoice):
|
||||
if arg == nil or arg.kind != nkSymChoice:
|
||||
result = ParamTypesMatchAux(c, m, f, a, arg)
|
||||
else:
|
||||
# CAUTION: The order depends on the used hashing scheme. Thus it is
|
||||
@@ -555,8 +555,6 @@ proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
x = z
|
||||
elif cmp == 0:
|
||||
y = z # z is as good as x
|
||||
else:
|
||||
nil
|
||||
if x.state == csEmpty:
|
||||
result = nil
|
||||
elif (y.state == csMatch) and (cmpCandidates(x, y) == 0):
|
||||
@@ -620,7 +618,7 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
|
||||
m.baseTypeMatch = false
|
||||
var arg = ParamTypesMatch(c, m, formal.typ,
|
||||
n.sons[a].typ, n.sons[a].sons[1])
|
||||
if (arg == nil):
|
||||
if arg == nil:
|
||||
m.state = csNoMatch
|
||||
return
|
||||
if m.baseTypeMatch:
|
||||
|
||||
@@ -25,7 +25,7 @@ type
|
||||
wAddr, wAnd, wAs, wAsm, wAtomic,
|
||||
wBind, wBlock, wBreak, wCase, wCast, wConst,
|
||||
wContinue, wConverter, wDiscard, wDistinct, wDiv, wElif, wElse, wEnd, wEnum,
|
||||
wExcept, wFinally, wFor, wFrom, wGeneric, wIf, wImplies, wImport, wIn,
|
||||
wExcept, wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn,
|
||||
wInclude, wIs, wIsnot, wIterator, wLambda, wLet,
|
||||
wMacro, wMethod, wMod, wNil,
|
||||
wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn,
|
||||
@@ -34,6 +34,7 @@ type
|
||||
|
||||
wColon, wColonColon, wEquals, wDot, wDotDot, wStar, wMinus,
|
||||
wMagic, wThread, wFinal, wProfiler, wObjChecks,
|
||||
wImportCpp, wImportObjC,
|
||||
wImportCompilerProc,
|
||||
wImportc, wExportc, wExtern,
|
||||
wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader,
|
||||
@@ -51,7 +52,7 @@ type
|
||||
wPragma,
|
||||
wCompileTime, wGc, wRefc, wBoehm, wA, wOpt, wO, wApp, wConsole, wGui,
|
||||
wPassc, wT, wPassl, wL, wListcmd, wGendoc, wGenmapping, wOs, wCpu,
|
||||
wGenerate, wG, wC, wCpp, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
|
||||
wGenerate, wG, wC, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
|
||||
wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced, wSkipcfg, wSkipProjCfg,
|
||||
wCc, wGenscript, wCheckPoint, wThreadAnalysis, wNoMain, wSubsChar,
|
||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
||||
@@ -72,7 +73,7 @@ const
|
||||
"bind", "block", "break", "case", "cast",
|
||||
"const", "continue", "converter", "discard", "distinct", "div", "elif",
|
||||
"else", "end", "enum", "except", "finally", "for", "from", "generic", "if",
|
||||
"implies", "import", "in", "include", "is", "isnot", "iterator",
|
||||
"import", "in", "include", "is", "isnot", "iterator",
|
||||
"lambda", "let",
|
||||
"macro", "method", "mod", "nil", "not", "notin", "object", "of", "or",
|
||||
"out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "template",
|
||||
@@ -81,6 +82,8 @@ const
|
||||
|
||||
":", "::", "=", ".", "..", "*", "-",
|
||||
"magic", "thread", "final", "profiler", "objchecks",
|
||||
|
||||
"importcpp", "importobjc",
|
||||
"importcompilerproc", "importc", "exportc", "extern",
|
||||
"align", "nodecl", "pure", "volatile", "register", "sideeffect",
|
||||
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
|
||||
@@ -99,7 +102,7 @@ const
|
||||
"pragma",
|
||||
"compiletime", "gc", "refc", "boehm", "a", "opt", "o", "app", "console",
|
||||
"gui", "passc", "t", "passl", "l", "listcmd", "gendoc", "genmapping", "os",
|
||||
"cpu", "generate", "g", "c", "cpp", "borrow", "run", "r", "verbosity", "v",
|
||||
"cpu", "generate", "g", "c", "borrow", "run", "r", "verbosity", "v",
|
||||
"help", "h", "symbolfiles", "fieldchecks", "x", "version", "advanced",
|
||||
"skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "threadanalysis",
|
||||
"nomain", "subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Advanced commands:
|
||||
//compileToC, cc compile project with C code generator
|
||||
//compileToOC, oc compile project to Objective C code
|
||||
//compileToCpp, cpp compile project to C++ code
|
||||
//compileToOC, objc compile project to Objective C code
|
||||
//rst2html convert a reStructuredText file to HTML
|
||||
//rst2tex convert a reStructuredText file to TeX
|
||||
//run run the project (with Tiny C backend; buggy!)
|
||||
|
||||
@@ -4,7 +4,7 @@ case cast const continue converter
|
||||
discard distinct div
|
||||
elif else end enum except
|
||||
finally for from generic
|
||||
if implies import in include is isnot iterator
|
||||
if import in include is isnot iterator
|
||||
lambda let
|
||||
macro method mod
|
||||
nil not notin
|
||||
|
||||
@@ -192,6 +192,85 @@ Example:
|
||||
embedsC()
|
||||
|
||||
|
||||
ImportCpp pragma
|
||||
----------------
|
||||
The `importcpp`:idx: pragma can be used to import `C++`:idx: methods. The
|
||||
generated code then uses the C++ method calling syntax: ``obj->method(arg)``.
|
||||
In addition with the ``header`` and ``emit`` pragmas this allows *sloppy*
|
||||
interfacing with libraries written in C++:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
# Horrible example of how to interface with a C++ engine ... ;-)
|
||||
|
||||
{.link: "/usr/lib/libIrrlicht.so".}
|
||||
|
||||
{.emit: """
|
||||
using namespace irr;
|
||||
using namespace core;
|
||||
using namespace scene;
|
||||
using namespace video;
|
||||
using namespace io;
|
||||
using namespace gui;
|
||||
""".}
|
||||
|
||||
const
|
||||
irr = "<irrlicht/irrlicht.h>"
|
||||
|
||||
type
|
||||
TIrrlichtDevice {.final, header: irr, importc: "IrrlichtDevice".} = object
|
||||
PIrrlichtDevice = ptr TIrrlichtDevice
|
||||
|
||||
proc createDevice(): PIrrlichtDevice {.
|
||||
header: irr, importc: "createDevice".}
|
||||
proc run(device: PIrrlichtDevice): bool {.
|
||||
header: irr, importcpp: "run".}
|
||||
|
||||
|
||||
ImportObjC pragma
|
||||
-----------------
|
||||
The `importobjc`:idx: pragma can be used to import `Objective C`:idx: methods.
|
||||
The generated code then uses the Objective C method calling
|
||||
syntax: ``[obj method param1: arg]``.
|
||||
In addition with the ``header`` and ``emit`` pragmas this allows *sloppy*
|
||||
interfacing with libraries written in Objective C:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
# horrible example of how to interface with GNUStep ...
|
||||
|
||||
{.passL: "-lobjc".}
|
||||
{.emit: """
|
||||
#include <objc/Object.h>
|
||||
@interface Greeter:Object
|
||||
{
|
||||
}
|
||||
|
||||
- (void)greet:(long)x y:(long)dummy;
|
||||
@end
|
||||
|
||||
#include <stdio.h>
|
||||
@implementation Greeter
|
||||
|
||||
- (void)greet:(long)x y:(long)dummy
|
||||
{
|
||||
printf("Hello, World!\n");
|
||||
}
|
||||
@end
|
||||
|
||||
#include <stdlib.h>
|
||||
""".}
|
||||
|
||||
type
|
||||
TId {.importc: "id", header: "<objc/Object.h>", final.} = distinct int
|
||||
|
||||
proc newGreeter: TId {.importobjc: "Greeter new", nodecl.}
|
||||
proc greet(self: TId, x, y: int) {.importobjc: "greet", nodecl.}
|
||||
proc free(self: TId) {.importobjc: "free", nodecl.}
|
||||
|
||||
var g = newGreeter()
|
||||
g.greet(12, 34)
|
||||
g.free()
|
||||
|
||||
|
||||
LineDir option
|
||||
--------------
|
||||
The `lineDir`:idx: option can be turned on or off. If turned on the
|
||||
|
||||
114
examples/c++iface/irrlichtex.nim
Normal file
114
examples/c++iface/irrlichtex.nim
Normal file
@@ -0,0 +1,114 @@
|
||||
# Horrible example of how to interface with a C++ engine ... ;-)
|
||||
|
||||
{.link: "/usr/lib/libIrrlicht.so".}
|
||||
|
||||
{.emit: """
|
||||
using namespace irr;
|
||||
using namespace core;
|
||||
using namespace scene;
|
||||
using namespace video;
|
||||
using namespace io;
|
||||
using namespace gui;
|
||||
""".}
|
||||
|
||||
const
|
||||
irr = "<irrlicht/irrlicht.h>"
|
||||
|
||||
type
|
||||
TDimension2d {.final, header: irr, importc: "dimension2d".} = object
|
||||
Tvector3df {.final, header: irr, importc: "vector3df".} = object
|
||||
TColor {.final, header: irr, importc: "SColor".} = object
|
||||
|
||||
TIrrlichtDevice {.final, header: irr, importc: "IrrlichtDevice".} = object
|
||||
TIVideoDriver {.final, header: irr, importc: "IVideoDriver".} = object
|
||||
TISceneManager {.final, header: irr, importc: "ISceneManager".} = object
|
||||
TIGUIEnvironment {.final, header: irr, importc: "IGUIEnvironment".} = object
|
||||
TIAnimatedMesh {.final, header: irr, importc: "IAnimatedMesh".} = object
|
||||
TIAnimatedMeshSceneNode {.final, header: irr,
|
||||
importc: "IAnimatedMeshSceneNode".} = object
|
||||
TITexture {.final, header: irr, importc: "ITexture".} = object
|
||||
|
||||
PIrrlichtDevice = ptr TIrrlichtDevice
|
||||
PIVideoDriver = ptr TIVideoDriver
|
||||
PISceneManager = ptr TISceneManager
|
||||
PIGUIEnvironment = ptr TIGUIEnvironment
|
||||
PIAnimatedMesh = ptr TIAnimatedMesh
|
||||
PIAnimatedMeshSceneNode = ptr TIAnimatedMeshSceneNode
|
||||
PITexture = ptr TITexture
|
||||
|
||||
proc dimension2d(x, y: cint): TDimension2d {.
|
||||
header: irr, importc: "dimension2d<u32>".}
|
||||
proc vector3df(x,y,z: cint): Tvector3df {.
|
||||
header: irr, importc: "vector3df".}
|
||||
proc SColor(r,g,b,a: cint): TColor {.
|
||||
header: irr, importc: "SColor".}
|
||||
|
||||
proc createDevice(): PIrrlichtDevice {.
|
||||
header: irr, importc: "createDevice".}
|
||||
proc run(device: PIrrlichtDevice): bool {.
|
||||
header: irr, importcpp: "run".}
|
||||
|
||||
proc getVideoDriver(dev: PIrrlichtDevice): PIVideoDriver {.
|
||||
header: irr, importcpp: "getVideoDriver".}
|
||||
proc getSceneManager(dev: PIrrlichtDevice): PISceneManager {.
|
||||
header: irr, importcpp: "getSceneManager".}
|
||||
proc getGUIEnvironment(dev: PIrrlichtDevice): PIGUIEnvironment {.
|
||||
header: irr, importcpp: "getGUIEnvironment".}
|
||||
|
||||
proc getMesh(smgr: PISceneManager, path: cstring): PIAnimatedMesh {.
|
||||
header: irr, importcpp: "getMesh".}
|
||||
|
||||
proc drawAll(smgr: PISceneManager) {.
|
||||
header: irr, importcpp: "drawAll".}
|
||||
proc drawAll(guienv: PIGUIEnvironment) {.
|
||||
header: irr, importcpp: "drawAll".}
|
||||
|
||||
proc drop(dev: PIrrlichtDevice) {.
|
||||
header: irr, importcpp: "drop".}
|
||||
|
||||
proc getTexture(driver: PIVideoDriver, path: cstring): PITexture {.
|
||||
header: irr, importcpp: "getTexture".}
|
||||
proc endScene(driver: PIVideoDriver) {.
|
||||
header: irr, importcpp: "endScene".}
|
||||
proc beginScene(driver: PIVideoDriver, a, b: bool, c: TColor) {.
|
||||
header: irr, importcpp: "beginScene".}
|
||||
|
||||
proc addAnimatedMeshSceneNode(
|
||||
smgr: PISceneManager, mesh: PIAnimatedMesh): PIAnimatedMeshSceneNode {.
|
||||
header: irr, importcpp: "addAnimatedMeshSceneNode".}
|
||||
|
||||
proc setMaterialTexture(n: PIAnimatedMeshSceneNode, x: cint, t: PITexture) {.
|
||||
header: irr, importcpp: "setMaterialTexture".}
|
||||
proc addCameraSceneNode(smgr: PISceneManager, x: cint, a, b: TVector3df) {.
|
||||
header: irr, importcpp: "addCameraSceneNode".}
|
||||
|
||||
|
||||
var device = createDevice()
|
||||
if device == nil: quit "device is nil"
|
||||
|
||||
var driver = device.getVideoDriver()
|
||||
var smgr = device.getSceneManager()
|
||||
var guienv = device.getGUIEnvironment()
|
||||
|
||||
var mesh = smgr.getMesh("/home/andreas/download/irrlicht-1.7.2/media/sydney.md2")
|
||||
if mesh == nil:
|
||||
device.drop()
|
||||
quit "no mesh!"
|
||||
|
||||
var node = smgr.addAnimatedMeshSceneNode(mesh)
|
||||
|
||||
if node != nil:
|
||||
#node->setMaterialFlag(EMF_LIGHTING, false)
|
||||
#node->setMD2Animation(scene::EMAT_STAND)
|
||||
node.setMaterialTexture(0,
|
||||
driver.getTexture(
|
||||
"/home/andreas/download/irrlicht-1.7.2/media/media/sydney.bmp"))
|
||||
|
||||
smgr.addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0))
|
||||
while device.run():
|
||||
driver.beginScene(true, true, SColor(255,100,101,140))
|
||||
smgr.drawAll()
|
||||
guienv.drawAll()
|
||||
driver.endScene()
|
||||
device.drop()
|
||||
|
||||
40
examples/objciface/gnustepex.nim
Normal file
40
examples/objciface/gnustepex.nim
Normal file
@@ -0,0 +1,40 @@
|
||||
# horrible example of how to interface with GNUStep ...
|
||||
|
||||
{.passL: "-lobjc".}
|
||||
{.emit: """
|
||||
|
||||
#include <objc/Object.h>
|
||||
|
||||
@interface Greeter:Object
|
||||
{
|
||||
}
|
||||
|
||||
- (void)greet:(long)x y:(long)dummy;
|
||||
|
||||
@end
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@implementation Greeter
|
||||
|
||||
- (void)greet:(long)x y:(long)dummy
|
||||
{
|
||||
printf("Hello, World!\n");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#include <stdlib.h>
|
||||
""".}
|
||||
|
||||
type
|
||||
TId {.importc: "id", header: "<objc/Object.h>", final.} = distinct int
|
||||
|
||||
proc newGreeter: TId {.importobjc: "Greeter new", nodecl.}
|
||||
proc greet(self: TId, x, y: int) {.importobjc: "greet", nodecl.}
|
||||
proc free(self: TId) {.importobjc: "free", nodecl.}
|
||||
|
||||
var g = newGreeter()
|
||||
g.greet(12, 34)
|
||||
g.free()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
Nimrod's Runtime Library
|
||||
(c) Copyright 2010 Andreas Rumpf
|
||||
(c) Copyright 2011 Andreas Rumpf
|
||||
|
||||
See the file "copying.txt", included in this
|
||||
distribution, for details about the copyright.
|
||||
@@ -281,6 +281,7 @@ static unsigned long nimInf[2]={0xffffffff, 0x7fffffff};
|
||||
# define NIM_FALSE false
|
||||
# endif
|
||||
# define NIM_BOOL bool
|
||||
# define NIM_NIL 0
|
||||
#else
|
||||
# ifdef bool
|
||||
# define NIM_BOOL bool
|
||||
@@ -293,10 +294,9 @@ static unsigned long nimInf[2]={0xffffffff, 0x7fffffff};
|
||||
# ifndef NIM_FALSE
|
||||
# define NIM_FALSE ((NIM_BOOL) 0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so
|
||||
# define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so
|
||||
the generated code does not rely on it anymore */
|
||||
#endif
|
||||
|
||||
#if defined(__BORLANDC__) || defined(__DMC__) \
|
||||
|| defined(__WATCOMC__) || defined(_MSC_VER)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
cmd: "nimrod cc --hints:on --threads:on $# $#"
|
||||
"""
|
||||
|
||||
type
|
||||
TThreadFuncArgs[T] = object of TObject
|
||||
a: proc(): T {.thread.}
|
||||
|
||||
1
todo.txt
1
todo.txt
@@ -19,6 +19,7 @@ version 0.9.0
|
||||
- tests: run the GC tests
|
||||
- change overloading resolution
|
||||
- implement closures; implement proper coroutines
|
||||
- make exceptions compatible with C++ exceptions
|
||||
|
||||
Bugs
|
||||
----
|
||||
|
||||
@@ -31,6 +31,7 @@ Changes affecting backwards compatibility
|
||||
- Moved ``strutils.validEmailAddress`` to ``matchers.validEmailAddress``.
|
||||
- The pointer dereference operator ``^`` has been removed, so that ``^``
|
||||
can now be a user-defined operator.
|
||||
- ``implies`` is no keyword anymore.
|
||||
- The ``is`` operator is now the ``of`` operator.
|
||||
- The ``is`` operator is now used to check type equivalence in generic code.
|
||||
|
||||
@@ -47,6 +48,13 @@ Language Additions
|
||||
Compiler Additions
|
||||
------------------
|
||||
|
||||
- The compiler can generate C++ code for easier interfacing with C++.
|
||||
- The compiler can generate Objective C code for easier interfacing with
|
||||
Objective C.
|
||||
- The new pragmas ``importcpp`` and ``importobjc`` make interfacing with C++
|
||||
and Objective C somewhat easier.
|
||||
|
||||
|
||||
Library Additions
|
||||
-----------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user