support for C++ code generation; importcpp and importobjc pragmas

This commit is contained in:
Araq
2011-08-07 21:02:09 +02:00
parent 7748dbc0b2
commit 5131b3cea4
29 changed files with 512 additions and 189 deletions

View File

@@ -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]

View File

@@ -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)

View File

@@ -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

View File

@@ -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:

View File

@@ -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!)

View File

@@ -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])

View File

@@ -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)

View File

@@ -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",

View File

@@ -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)

View File

@@ -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)

View File

@@ -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"

View File

@@ -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:

View File

@@ -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) =

View File

@@ -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

View File

@@ -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)

View File

@@ -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:

View File

@@ -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

View File

@@ -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:

View File

@@ -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:

View File

@@ -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",

View File

@@ -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!)

View File

@@ -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

View File

@@ -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

View 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()

View 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()

View File

@@ -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)

View File

@@ -1,3 +1,7 @@
discard """
cmd: "nimrod cc --hints:on --threads:on $# $#"
"""
type
TThreadFuncArgs[T] = object of TObject
a: proc(): T {.thread.}

View File

@@ -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
----

View File

@@ -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
-----------------