diff options
-rwxr-xr-x | compiler/ast.nim | 12 | ||||
-rwxr-xr-x | compiler/ccgexprs.nim | 167 | ||||
-rwxr-xr-x | compiler/ccgstmts.nim | 89 | ||||
-rwxr-xr-x | compiler/cgen.nim | 7 | ||||
-rwxr-xr-x | compiler/commands.nim | 3 | ||||
-rwxr-xr-x | compiler/docgen.nim | 2 | ||||
-rwxr-xr-x | compiler/ecmasgen.nim | 14 | ||||
-rwxr-xr-x | compiler/lexer.nim | 4 | ||||
-rwxr-xr-x | compiler/lookups.nim | 4 | ||||
-rwxr-xr-x | compiler/main.nim | 4 | ||||
-rwxr-xr-x | compiler/nimrod.ini | 11 | ||||
-rwxr-xr-x | compiler/pragmas.nim | 20 | ||||
-rwxr-xr-x | compiler/rodwrite.nim | 4 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 2 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 6 | ||||
-rwxr-xr-x | compiler/semtempl.nim | 10 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 22 | ||||
-rwxr-xr-x | compiler/semtypinst.nim | 2 | ||||
-rwxr-xr-x | compiler/sigmatch.nim | 24 | ||||
-rwxr-xr-x | compiler/wordrecg.nim | 11 | ||||
-rwxr-xr-x | doc/advopt.txt | 3 | ||||
-rwxr-xr-x | doc/keywords.txt | 2 | ||||
-rwxr-xr-x | doc/nimrodc.txt | 79 | ||||
-rw-r--r-- | examples/c++iface/irrlichtex.nim | 114 | ||||
-rw-r--r-- | examples/objciface/gnustepex.nim | 40 | ||||
-rwxr-xr-x | lib/nimbase.h | 8 | ||||
-rw-r--r-- | tests/accept/compile/tthread_generic.nim | 4 | ||||
-rwxr-xr-x | todo.txt | 1 | ||||
-rwxr-xr-x | web/news.txt | 8 |
29 files changed, 500 insertions, 177 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 817b37d60..909c7c3bf 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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] diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 7534fc4e5..7c9b346e6 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -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,6 +784,41 @@ proc genEcho(p: BProc, n: PNode) = appcg(p, cpsStmts, "printf($1$2);$n", [ makeCString(repeatStr(n.len-1, "%s") & tnl), args]) +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! + 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, 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 genCall(p: BProc, t: PNode, d: var TLoc) = var op, a: TLoc # this is a hotspot in the compiler @@ -788,12 +826,42 @@ proc genCall(p: BProc, t: PNode, d: var TLoc) = var pl = con(op.r, "(") 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)): + 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)) @@ -801,27 +869,65 @@ proc genCall(p: BProc, t: PNode, d: var TLoc) = 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 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: if d.k == locNone: getTemp(p, typ.sons[0], d) + app(pl, "Result: ") app(pl, addrLoc(d)) - app(pl, ")") + 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(pl, "]") app(p.s[cpsStmts], pl) app(p.s[cpsStmts], ';' & tnl) genAssignment(p, d, tmp, {}) # no need for deep copying else: - app(pl, ")") + app(pl, "]") if d.k == locNone: getTemp(p, typ.sons[0], d) assert(d.t != nil) # generate an assignment to d: var list: TLoc @@ -829,10 +935,10 @@ proc genCall(p: BProc, t: PNode, d: var TLoc) = list.r = pl genAssignment(p, d, list, {}) # no need for deep copying else: - app(pl, ")") + 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) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 8a05c68a4..9713dff0e 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -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 diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 431aade09..7b17e9958 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -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: diff --git a/compiler/commands.nim b/compiler/commands.nim index c5a689dfc..a4fe80702 100755 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -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!) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 0c5d41b47..c05c35b90 100755 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -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]) diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim index 2e66f61c9..8fc525a28 100755 --- a/compiler/ecmasgen.nim +++ b/compiler/ecmasgen.nim @@ -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) diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 7d6503929..496712237 100755 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -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", diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 324618447..61b8ead4c 100755 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -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) diff --git a/compiler/main.nim b/compiler/main.nim index 1ba13c649..b7670f5aa 100755 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -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) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 471790111..cb3a80a04 100755 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -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" diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 49505be49..014f431c4 100755 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -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: diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index 327083ff1..0bc73d6f1 100755 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -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) = diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 3bbc0c71f..58fbf3a25 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -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 diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 38ecffdf8..e88fed51a 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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) diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index dee703d30..e2b2a03d1 100755 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -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: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 894dec1cb..728dffc8d 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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 diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 7cdc81b94..420c84193 100755 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -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: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index ec689d315..ea40dd0c9 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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: diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 47d0fa3fc..1361475e4 100755 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -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", diff --git a/doc/advopt.txt b/doc/advopt.txt index 5b22c6b48..90fe5850f 100755 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -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!) diff --git a/doc/keywords.txt b/doc/keywords.txt index a6d96834a..75014da42 100755 --- a/doc/keywords.txt +++ b/doc/keywords.txt @@ -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 diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 71f5c0387..6961c41bd 100755 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -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 diff --git a/examples/c++iface/irrlichtex.nim b/examples/c++iface/irrlichtex.nim new file mode 100644 index 000000000..4dd1d79ee --- /dev/null +++ b/examples/c++iface/irrlichtex.nim @@ -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() + diff --git a/examples/objciface/gnustepex.nim b/examples/objciface/gnustepex.nim new file mode 100644 index 000000000..d961d3087 --- /dev/null +++ b/examples/objciface/gnustepex.nim @@ -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() + diff --git a/lib/nimbase.h b/lib/nimbase.h index fc527e0d0..2af6ed8cc 100755 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -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) diff --git a/tests/accept/compile/tthread_generic.nim b/tests/accept/compile/tthread_generic.nim index 4ef939408..beae4b652 100644 --- a/tests/accept/compile/tthread_generic.nim +++ b/tests/accept/compile/tthread_generic.nim @@ -1,3 +1,7 @@ +discard """ + cmd: "nimrod cc --hints:on --threads:on $# $#" +""" + type TThreadFuncArgs[T] = object of TObject a: proc(): T {.thread.} diff --git a/todo.txt b/todo.txt index bca290b34..56bc80a6b 100755 --- a/todo.txt +++ b/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 ---- diff --git a/web/news.txt b/web/news.txt index 7a58ee4c4..9e4a2d67c 100755 --- a/web/news.txt +++ b/web/news.txt @@ -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 ----------------- |