summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/ast.nim12
-rwxr-xr-xcompiler/ccgexprs.nim167
-rwxr-xr-xcompiler/ccgstmts.nim89
-rwxr-xr-xcompiler/cgen.nim7
-rwxr-xr-xcompiler/commands.nim3
-rwxr-xr-xcompiler/docgen.nim2
-rwxr-xr-xcompiler/ecmasgen.nim14
-rwxr-xr-xcompiler/lexer.nim4
-rwxr-xr-xcompiler/lookups.nim4
-rwxr-xr-xcompiler/main.nim4
-rwxr-xr-xcompiler/nimrod.ini11
-rwxr-xr-xcompiler/pragmas.nim20
-rwxr-xr-xcompiler/rodwrite.nim4
-rwxr-xr-xcompiler/semexprs.nim2
-rwxr-xr-xcompiler/semstmts.nim6
-rwxr-xr-xcompiler/semtempl.nim10
-rwxr-xr-xcompiler/semtypes.nim22
-rwxr-xr-xcompiler/semtypinst.nim2
-rwxr-xr-xcompiler/sigmatch.nim24
-rwxr-xr-xcompiler/wordrecg.nim11
-rwxr-xr-xdoc/advopt.txt3
-rwxr-xr-xdoc/keywords.txt2
-rwxr-xr-xdoc/nimrodc.txt79
-rw-r--r--examples/c++iface/irrlichtex.nim114
-rw-r--r--examples/objciface/gnustepex.nim40
-rwxr-xr-xlib/nimbase.h8
-rw-r--r--tests/accept/compile/tthread_generic.nim4
-rwxr-xr-xtodo.txt1
-rwxr-xr-xweb/news.txt8
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
 -----------------