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

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

View file

@ -187,11 +187,9 @@ type
TNodeKinds* = set[TNodeKind]
type
TSymFlag* = enum # already 29 flags!
TSymFlag* = enum # already 29 flags!
sfUsed, # read access of sym (for warnings) or simply used
sfStar, # symbol has * visibility
sfMinus, # symbol has - visibility
sfInInterface, # symbol is in interface section declared
sfExported, # symbol is exported from module
sfFromGeneric, # symbol is instantiation of a generic; this is needed
# for symbol file generation; such symbols should always
# be written into the ROD file
@ -221,7 +219,11 @@ type
sfThreadVar, # variable is a thread variable
sfMerge, # proc can be merged with itself
sfDeadCodeElim, # dead code elimination for the module is turned on
sfBorrow # proc is borrowed
sfBorrow, # proc is borrowed
sfInfixCall, # symbol needs infix call syntax in target language;
# for interfacing with C++, JS
sfNamedParamCall # symbol needs named parameter call syntax in target
# language; for interfacing with Objective C
TSymFlags* = set[TSymFlag]

View file

@ -7,6 +7,9 @@
# distribution, for details about the copyright.
#
proc lenField: PRope {.inline.} =
result = toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len")
# -------------------------- constant expressions ------------------------
proc intLiteral(i: biggestInt): PRope =
@ -682,12 +685,12 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) =
if (optBoundsCheck in p.options):
if ty.kind == tyString:
appcg(p, cpsStmts,
"if ((NU)($1) > (NU)($2->Sup.len)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a)])
"if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a), lenField()])
else:
appcg(p, cpsStmts,
"if ((NU)($1) >= (NU)($2->Sup.len)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a)])
"if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
[rdLoc(b), rdLoc(a), lenField()])
if d.k == locNone: d.s = OnHeap
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
a.r = ropef("(*$1)", [a.r])
@ -781,29 +784,12 @@ proc genEcho(p: BProc, n: PNode) =
appcg(p, cpsStmts, "printf($1$2);$n", [
makeCString(repeatStr(n.len-1, "%s") & tnl), args])
proc genCall(p: BProc, t: PNode, d: var TLoc) =
var op, a: TLoc
# this is a hotspot in the compiler
initLocExpr(p, t.sons[0], op)
var pl = con(op.r, "(")
proc fixupCall(p: BProc, t: PNode, d: var TLoc, pl: PRope) =
var pl = pl
var typ = t.sons[0].typ # getUniqueType() is too expensive here!
assert(typ.kind == tyProc)
var invalidRetType = isInvalidReturnType(typ.sons[0])
var length = sonsLen(t)
for i in countup(1, length - 1):
initLocExpr(p, t.sons[i], a) # generate expression for param
assert(sonsLen(typ) == sonsLen(typ.n))
if (i < sonsLen(typ)):
assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
else: app(pl, rdLoc(a))
else:
app(pl, rdLoc(a))
if i < length - 1: app(pl, ", ")
if typ.sons[0] != nil:
if invalidRetType:
if length > 1: app(pl, ", ")
if isInvalidReturnType(typ.sons[0]):
if sonsLen(t) > 1: app(pl, ", ")
# beware of 'result = p(result)'. We always allocate a temporary:
if d.k in {locTemp, locNone}:
# We already got a temp. Great, special case it:
@ -832,7 +818,127 @@ proc genCall(p: BProc, t: PNode, d: var TLoc) =
app(pl, ")")
app(p.s[cpsStmts], pl)
app(p.s[cpsStmts], ';' & tnl)
proc genCall(p: BProc, t: PNode, d: var TLoc) =
var op, a: TLoc
# this is a hotspot in the compiler
initLocExpr(p, t.sons[0], op)
var pl = con(op.r, "(")
var typ = t.sons[0].typ # getUniqueType() is too expensive here!
assert(typ.kind == tyProc)
var length = sonsLen(t)
for i in countup(1, length - 1):
initLocExpr(p, t.sons[i], a) # generate expression for param
assert(sonsLen(typ) == sonsLen(typ.n))
if i < sonsLen(typ):
assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
else: app(pl, rdLoc(a))
else:
app(pl, rdLoc(a))
if i < length - 1: app(pl, ", ")
fixupCall(p, t, d, pl)
proc genInfixCall(p: BProc, t: PNode, d: var TLoc) =
var op, a: TLoc
initLocExpr(p, t.sons[0], op)
var pl: PRope = nil
var typ = t.sons[0].typ # getUniqueType() is too expensive here!
assert(typ.kind == tyProc)
var length = sonsLen(t)
initLocExpr(p, t.sons[1], a) # generate expression for first param
assert(sonsLen(typ) == sonsLen(typ.n))
var param = typ.n.sons[1].sym
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
else: app(pl, rdLoc(a))
if skipTypes(param.typ, {tyGenericInst}).kind == tyPtr: app(pl, "->")
else: app(pl, ".")
app(pl, op.r)
app(pl, "(")
for i in countup(2, length - 1):
initLocExpr(p, t.sons[i], a) # generate expression for param
assert(sonsLen(typ) == sonsLen(typ.n))
if i < sonsLen(typ):
assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
else: app(pl, rdLoc(a))
else:
app(pl, rdLoc(a))
if i < length - 1: app(pl, ", ")
fixupCall(p, t, d, pl)
proc genNamedParamCall(p: BProc, t: PNode, d: var TLoc) =
# generates a crappy ObjC call
var op, a: TLoc
initLocExpr(p, t.sons[0], op)
var pl = toRope"["
var typ = t.sons[0].typ # getUniqueType() is too expensive here!
assert(typ.kind == tyProc)
var length = sonsLen(t)
assert(sonsLen(typ) == sonsLen(typ.n))
if length > 1:
initLocExpr(p, t.sons[1], a)
var param = typ.n.sons[1].sym
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
else: app(pl, rdLoc(a))
app(pl, " ")
app(pl, op.r)
if length > 2:
initLocExpr(p, t.sons[2], a)
app(pl, ": ")
var param = typ.n.sons[2].sym
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
else: app(pl, rdLoc(a))
for i in countup(3, length-1):
initLocExpr(p, t.sons[i], a) # generate expression for param
assert(sonsLen(typ) == sonsLen(typ.n))
if i >= sonsLen(typ):
InternalError(t.info, "varargs for objective C method?")
assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym
app(pl, " ")
app(pl, param.name.s)
app(pl, ": ")
if ccgIntroducedPtr(param): app(pl, addrLoc(a))
else: app(pl, rdLoc(a))
if typ.sons[0] != nil:
if isInvalidReturnType(typ.sons[0]):
if sonsLen(t) > 1: app(pl, " ")
# beware of 'result = p(result)'. We always allocate a temporary:
if d.k in {locTemp, locNone}:
# We already got a temp. Great, special case it:
if d.k == locNone: getTemp(p, typ.sons[0], d)
app(pl, "Result: ")
app(pl, addrLoc(d))
app(pl, "]")
app(p.s[cpsStmts], pl)
app(p.s[cpsStmts], ';' & tnl)
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp)
app(pl, addrLoc(tmp))
app(pl, "]")
app(p.s[cpsStmts], pl)
app(p.s[cpsStmts], ';' & tnl)
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
app(pl, "]")
if d.k == locNone: getTemp(p, typ.sons[0], d)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, nil, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
else:
app(pl, "]")
app(p.s[cpsStmts], pl)
app(p.s[cpsStmts], ';' & tnl)
proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
# <Nimrod code>
# s = 'Hello ' & name & ', how do you feel?' & 'z'
@ -865,7 +971,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
Inc(L, len(e.sons[i + 1].strVal))
else:
appf(lens, "$1->Sup.len + ", [rdLoc(a)])
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
app(p.s[cpsStmts], appends)
@ -906,7 +1012,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
Inc(L, len(e.sons[i + 2].strVal))
else:
appf(lens, "$1->Sup.len + ", [rdLoc(a)])
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
appcg(p.module, appends, "#appendString($1, $2);$n",
[rdLoc(dest), rdLoc(a)])
appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
@ -925,7 +1031,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))])
initLoc(dest, locExpr, b.t, OnHeap)
dest.r = ropef("$1->data[$1->Sup.len-1]", [rdLoc(a)])
dest.r = ropef("$1->data[$1->$2-1]", [rdLoc(a), lenField()])
genAssignment(p, dest, b, {needToCopy, afDestIsNil})
proc genReset(p: BProc, n: PNode) =
@ -984,7 +1090,8 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
r = ropecg(p.module, "(($1) && #isObj($2.m_type, $3))",
[nilCheck, r, genTypeInfo(p.module, dest)])
else:
r = ropecg(p.module, "#isObj($1.m_type, $2)", [r, genTypeInfo(p.module, dest)])
r = ropecg(p.module, "#isObj($1.m_type, $2)",
[r, genTypeInfo(p.module, dest)])
putIntoDest(p, d, getSysType(tyBool), r)
proc genOf(p: BProc, n: PNode, d: var TLoc) =
@ -1041,7 +1148,8 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
case a.t.kind
of tyOpenArray: putIntoDest(p, b, e.typ, rdLoc(a))
of tyString, tySequence:
putIntoDest(p, b, e.typ, ropef("$1->data, $1->Sup.len", [rdLoc(a)]))
putIntoDest(p, b, e.typ,
ropef("$1->data, $1->$2", [rdLoc(a), lenField()]))
of tyArray, tyArrayConstr:
putIntoDest(p, b, e.typ,
ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
@ -1080,8 +1188,12 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
if op == mHigh: unaryExpr(p, e, d, "(strlen($1)-1)")
else: unaryExpr(p, e, d, "strlen($1)")
of tyString, tySequence:
if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
else: unaryExpr(p, e, d, "$1->Sup.len")
if gCmd != cmdCompileToCpp:
if op == mHigh: unaryExpr(p, e, d, "($1->Sup.len-1)")
else: unaryExpr(p, e, d, "$1->Sup.len")
else:
if op == mHigh: unaryExpr(p, e, d, "($1->len-1)")
else: unaryExpr(p, e, d, "$1->len")
of tyArray, tyArrayConstr:
# YYY: length(sideeffect) is optimized away incorrectly?
if op == mHigh: putIntoDest(p, d, e.typ, toRope(lastOrd(Typ)))
@ -1289,7 +1401,7 @@ proc passToOpenArray(p: BProc, n: PNode, d: var TLoc) =
putIntoDest(p, d, dest, ropef("$1, $1Len0", [rdLoc(a)]))
of tyString, tySequence:
initLocExpr(p, n.sons[0], a)
putIntoDest(p, d, dest, ropef("$1->data, $1->Sup.len", [rdLoc(a)]))
putIntoDest(p, d, dest, ropef("$1->data, $1->$2", [rdLoc(a), lenField()]))
of tyArray, tyArrayConstr:
initLocExpr(p, n.sons[0], a)
putIntoDest(p, d, dest, ropef("$1, $2", [rdLoc(a), toRope(lengthOrd(a.t))]))
@ -1314,10 +1426,12 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
binaryExpr(p, e, d, "($1 == $2)")
elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
initLocExpr(p, e.sons[2], x)
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
putIntoDest(p, d, e.typ,
ropef("(($1) && ($1)->$2 == 0)", [rdLoc(x), lenField()]))
elif (b.kind in {nkStrLit..nkTripleStrLit}) and (b.strVal == ""):
initLocExpr(p, e.sons[1], x)
putIntoDest(p, d, e.typ, ropef("(($1) && ($1)->Sup.len == 0)", [rdLoc(x)]))
putIntoDest(p, d, e.typ,
ropef("(($1) && ($1)->$2 == 0)", [rdLoc(x), lenField()]))
else:
binaryExpr(p, e, d, "#eqStrings($1, $2)")
@ -1678,8 +1792,13 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
putIntoDest(p, d, e.typ, genLiteral(p, e))
of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand,
nkCallStrLit:
if (e.sons[0].kind == nkSym) and (e.sons[0].sym.magic != mNone):
if e.sons[0].kind == nkSym and e.sons[0].sym.magic != mNone:
genMagicExpr(p, e, d, e.sons[0].sym.magic)
elif e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags and
e.len >= 2:
genInfixCall(p, e, d)
elif e.sons[0].kind == nkSym and sfNamedParamCall in e.sons[0].sym.flags:
genNamedParamCall(p, e, d)
else:
genCall(p, e, d)
of nkCurly: genSetConstr(p, e, d)

View file

@ -218,10 +218,10 @@ proc genBreakStmt(p: BProc, t: PNode) =
appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.blocks[idx].id)])
proc getRaiseFrmt(p: BProc): string =
if gCmd == cmdCompileToCpp:
result = "throw #nimException($1, $2);$n"
else:
result = "#raiseException((#E_Base*)$1, $2);$n"
#if gCmd == cmdCompileToCpp:
# result = "throw #nimException($1, $2);$n"
#else:
result = "#raiseException((#E_Base*)$1, $2);$n"
proc genRaiseStmt(p: BProc, t: PNode) =
if t.sons[0].kind != nkEmpty:
@ -234,10 +234,10 @@ proc genRaiseStmt(p: BProc, t: PNode) =
else:
genLineDir(p, t)
# reraise the last exception:
if gCmd == cmdCompileToCpp:
appcg(p, cpsStmts, "throw;" & tnl)
else:
appcg(p, cpsStmts, "#reraiseException();" & tnl)
#if gCmd == cmdCompileToCpp:
# appcg(p, cpsStmts, "throw;" & tnl)
#else:
appcg(p, cpsStmts, "#reraiseException();" & tnl)
proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
rangeFormat, eqFormat: TFormatStr, labl: TLabel) =
@ -491,72 +491,6 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
if rethrowFlag != nil:
appf(p.s[cpsStmts], "if ($1) { throw; }$n", [rethrowFlag])
proc genTryStmtCpp2(p: BProc, t: PNode) =
# code to generate:
#
# TSafePoint sp;
# pushSafePoint(&sp);
# sp.status = setjmp(sp.context);
# if (sp.status == 0) {
# myDiv(4, 9);
# popSafePoint();
# } else {
# popSafePoint();
# /* except DivisionByZero: */
# if (sp.status == DivisionByZero) {
# printf('Division by Zero\n');
# clearException();
# } else {
# clearException();
# }
# }
# /* finally: */
# printf('fin!\n');
# if (exception not cleared)
# propagateCurrentException();
genLineDir(p, t)
var safePoint = getTempName()
discard cgsym(p.module, "E_Base")
appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
"$1.status = setjmp($1.context);$n", [safePoint])
if optStackTrace in p.Options:
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
appf(p.s[cpsStmts], "if ($1.status == 0) {$n", [safePoint])
var length = sonsLen(t)
add(p.nestedTryStmts, t)
genStmts(p, t.sons[0])
appcg(p, cpsStmts, "#popSafePoint();$n} else {$n#popSafePoint();$n")
var i = 1
while (i < length) and (t.sons[i].kind == nkExceptBranch):
var blen = sonsLen(t.sons[i])
if blen == 1:
# general except section:
if i > 1: app(p.s[cpsStmts], "else {" & tnl)
genStmts(p, t.sons[i].sons[0])
appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();$n", [safePoint])
if i > 1: app(p.s[cpsStmts], '}' & tnl)
else:
var orExpr: PRope = nil
for j in countup(0, blen - 2):
assert(t.sons[i].sons[j].kind == nkType)
if orExpr != nil: app(orExpr, "||")
appcg(p.module, orExpr,
"#isObj(#getCurrentException()->Sup.m_type, $1)",
[genTypeInfo(p.module, t.sons[i].sons[j].typ)])
if i > 1: app(p.s[cpsStmts], "else ")
appf(p.s[cpsStmts], "if ($1) {$n", [orExpr])
genStmts(p, t.sons[i].sons[blen-1])
# code to clear the exception:
appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();}$n",
[safePoint])
inc(i)
app(p.s[cpsStmts], '}' & tnl) # end of if statement
discard pop(p.nestedTryStmts)
if i < length and t.sons[i].kind == nkFinally:
genStmts(p, t.sons[i].sons[0])
appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
proc genTryStmt(p: BProc, t: PNode) =
# code to generate:
#
@ -655,7 +589,7 @@ proc genEmit(p: BProc, t: PNode) =
var s = genAsmOrEmitStmt(p, t.sons[1])
if p.prc == nil:
# top level emit pragma?
app(p.module.s[cfsProcs], s)
app(p.module.s[cfsProcHeaders], s)
else:
app(p.s[cpsStmts], s)
@ -768,8 +702,9 @@ proc genStmts(p: BProc, t: PNode) =
initLocExpr(p, t.sons[0], a)
of nkAsmStmt: genAsmStmt(p, t)
of nkTryStmt:
if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t)
else: genTryStmt(p, t)
#if gCmd == cmdCompileToCpp: genTryStmtCpp(p, t)
#else:
genTryStmt(p, t)
of nkRaiseStmt: genRaiseStmt(p, t)
of nkTypeSection:
# we have to emit the type information for object types here to support

View file

@ -271,9 +271,10 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
var r = rdLoc(a)
if not takeAddr: r = ropef("(*$1)", [r])
var s = skipTypes(t, abstractInst)
while (s.kind == tyObject) and (s.sons[0] != nil):
app(r, ".Sup")
s = skipTypes(s.sons[0], abstractInst)
if gCmd != cmdCompileToCpp:
while (s.kind == tyObject) and (s.sons[0] != nil):
app(r, ".Sup")
s = skipTypes(s.sons[0], abstractInst)
appcg(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
of frEmbedded:
# worst case for performance:

View file

@ -68,7 +68,8 @@ Options:
AdvancedUsage = """
Advanced commands:
compileToC, cc compile project with C code generator
compileToOC, oc compile project to Objective C code
compileToCpp, cpp compile project to C++ code
compileToOC, objc compile project to Objective C code
rst2html convert a reStructuredText file to HTML
rst2tex convert a reStructuredText file to TeX
run run the project (with Tiny C backend; buggy!)

View file

@ -287,7 +287,7 @@ proc isVisible(n: PNode): bool =
var v = n.sons[0].ident
result = (v.id == ord(wStar)) or (v.id == ord(wMinus))
elif n.kind == nkSym:
result = sfInInterface in n.sym.flags
result = sfExported in n.sym.flags
elif n.kind == nkPragmaExpr:
result = isVisible(n.sons[0])

View file

@ -1349,10 +1349,10 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
of nkNilLit:
if mapType(n.typ) == etyBaseIndex:
r.kind = etyBaseIndex
r.com = toRope("null")
r.res = toRope("0")
r.com = toRope"null"
r.res = toRope"0"
else:
r.res = toRope("null")
r.res = toRope"null"
of nkStrLit..nkTripleStrLit:
if skipTypes(n.typ, abstractVarRange).kind == tyString:
useMagic(p, "cstrToNimstr")
@ -1361,11 +1361,11 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
r.res = makeCString(n.strVal)
of nkFloatLit..nkFloat64Lit:
f = n.floatVal
if f != f: r.res = toRope("NaN")
elif f == 0.0: r.res = toRope("0.0")
if f != f: r.res = toRope"NaN"
elif f == 0.0: r.res = toRope"0.0"
elif f == 0.5 * f:
if f > 0.0: r.res = toRope("Infinity")
else: r.res = toRope("-Infinity")
if f > 0.0: r.res = toRope"Infinity"
else: r.res = toRope"-Infinity"
else: r.res = toRope(f.ToStrMaxPrecision)
of nkBlockExpr: genBlock(p, n, r)
of nkIfExpr: genIfExpr(p, n, r)

View file

@ -35,7 +35,7 @@ type
tkBind, tkBlock, tkBreak, tkCase, tkCast,
tkConst, tkContinue, tkConverter, tkDiscard, tkDistinct, tkDiv, tkElif,
tkElse, tkEnd, tkEnum, tkExcept, tkFinally, tkFor, tkFrom, tkGeneric, tkIf,
tkImplies, tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator,
tkImport, tkIn, tkInclude, tkIs, tkIsnot, tkIterator,
tkLambda, tkLet,
tkMacro, tkMethod, tkMod, tkNil, tkNot, tkNotin, tkObject, tkOf, tkOr,
tkOut, tkProc, tkPtr, tkRaise, tkRef, tkReturn, tkShl, tkShr, tkTemplate,
@ -63,7 +63,7 @@ const
"bind", "block", "break", "case", "cast",
"const", "continue", "converter", "discard", "distinct", "div", "elif",
"else", "end", "enum", "except", "finally", "for", "from", "generic", "if",
"implies", "import", "in", "include", "is", "isnot", "iterator",
"import", "in", "include", "is", "isnot", "iterator",
"lambda", "let",
"macro", "method", "mod", "nil", "not", "notin", "object", "of", "or",
"out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "template",

View file

@ -55,7 +55,7 @@ proc CloseScope*(tab: var TSymTab) =
while s != nil:
if sfForward in s.flags:
LocalError(s.info, errImplOfXexpected, getSymRepr(s))
elif {sfUsed, sfInInterface} * s.flags == {} and optHints in s.options:
elif {sfUsed, sfExported} * s.flags == {} and optHints in s.options:
# BUGFIX: check options in s!
if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}:
Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
@ -74,7 +74,7 @@ proc addDeclAt*(c: PContext, sym: PSym, at: Natural) =
LocalError(sym.info, errAttemptToRedefine, sym.Name.s)
proc AddInterfaceDeclAux(c: PContext, sym: PSym) =
if (sfInInterface in sym.flags):
if sfExported in sym.flags:
# add to interface:
if c.module == nil: InternalError(sym.info, "AddInterfaceDeclAux")
StrTableAdd(c.module.tab, sym)

View file

@ -199,12 +199,12 @@ proc MainCommand(cmd, filename: string) =
gCmd = cmdCompileToC
wantFile(filename)
CommandCompileToC(filename)
of "compiletocpp":
of "cpp", "compiletocpp":
extccomp.cExt = ".cpp"
gCmd = cmdCompileToCpp
wantFile(filename)
CommandCompileToC(filename)
of "oc", "compiletooc":
of "objc", "compiletooc":
extccomp.cExt = ".m"
gCmd = cmdCompileToOC
wantFile(filename)

View file

@ -80,6 +80,17 @@ Files: "lib/ecmas/*.nim"
[Other]
Files: "examples/*.nim"
Files: "examples/gtk/*.nim"
Files: "examples/0mq/*.nim"
Files: "examples/c++iface/*.nim"
Files: "examples/objciface/*.nim"
Files: "examples/lazarus/*.nim"
Files: "examples/lazarus/*.lpi"
Files: "examples/lazarus/*.lpr"
Files: "examples/lazarus/*.txt"
Files: "examples/lazarus/*.lfm"
Files: "examples/lazarus/*.pas"
Files: "examples/*.html"
Files: "examples/*.txt"
Files: "examples/*.cfg"

View file

@ -22,7 +22,7 @@ const
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
wCompilerProc, wPure, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow, wExtern, wImportCompilerProc, wThread}
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC}
converterPragmas* = procPragmas
methodPragmas* = procPragmas
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
@ -87,6 +87,18 @@ proc processImportCompilerProc(s: PSym, extname: string) =
excl(s.flags, sfForward)
incl(s.loc.flags, lfImportCompilerProc)
proc processImportCpp(s: PSym, extname: string) =
setExternName(s, extname)
incl(s.flags, sfImportc)
incl(s.flags, sfInfixCall)
excl(s.flags, sfForward)
proc processImportObjC(s: PSym, extname: string) =
setExternName(s, extname)
incl(s.flags, sfImportc)
incl(s.flags, sfNamedParamCall)
excl(s.flags, sfForward)
proc getStrLitNode(c: PContext, n: PNode): PNode =
if n.kind != nkExprColonExpr:
GlobalError(n.info, errStringLiteralExpected)
@ -410,7 +422,11 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
of wImportCompilerProc:
processImportCompilerProc(sym, getOptionalStr(c, it, sym.name.s))
of wExtern: setExternName(sym, expectStrLit(c, it))
of wAlign:
of wImportCpp:
processImportCpp(sym, getOptionalStr(c, it, sym.name.s))
of wImportObjC:
processImportObjC(sym, getOptionalStr(c, it, sym.name.s))
of wAlign:
if sym.typ == nil: invalidPragma(it)
var align = expectIntLit(c, it)
if not IsPowerOfTwo(align) and align != 0:

View file

@ -265,7 +265,7 @@ proc symStack(w: PRodWriter) =
addToIndex(w.index, s.id, L) #intSetIncl(debugWritten, s.id);
app(w.data, encodeSym(w, s))
app(w.data, rodNL)
if sfInInterface in s.flags:
if sfExported in s.flags:
appf(w.interf, "$1 $2" & rodNL, [encode(s.name.s), encodeInt(s.id)])
if sfCompilerProc in s.flags:
appf(w.compilerProcs, "$1 $2" & rodNL,
@ -305,7 +305,7 @@ proc rawAddInterfaceSym(w: PRodWriter, s: PSym) =
proc addInterfaceSym(w: PRodWriter, s: PSym) =
if w == nil: return
if {sfInInterface, sfCompilerProc} * s.flags != {}:
if {sfExported, sfCompilerProc} * s.flags != {}:
rawAddInterfaceSym(w, s)
proc addStmt(w: PRodWriter, n: PNode) =

View file

@ -658,7 +658,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
if ty.sons[0] == nil: break
ty = skipTypes(ty.sons[0], {tyGenericInst})
if f != nil:
if {sfStar, sfMinus} * f.flags != {} or getModule(f).id == c.module.id:
if sfExported in f.flags or getModule(f).id == c.module.id:
# is the access to a public field or in the same module?
n.sons[0] = makeDeref(n.sons[0])
n.sons[1] = newSymNode(f) # we now have the correct field

View file

@ -212,7 +212,7 @@ proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
if isTopLevel(c):
result = semIdentWithPragma(c, kind, n, {sfStar, sfMinus})
result = semIdentWithPragma(c, kind, n, {sfExported})
incl(result.flags, sfGlobal)
else:
result = semIdentWithPragma(c, kind, n, {})
@ -257,7 +257,6 @@ proc semVar(c: PContext, n: PNode): PNode =
addSon(result, b)
for j in countup(0, length-3):
var v = semIdentDef(c, a.sons[j], skVar)
if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)
addInterfaceDecl(c, v)
if a.kind != nkVarTuple:
v.typ = typ
@ -300,7 +299,6 @@ proc semConst(c: PContext, n: PNode): PNode =
GlobalError(a.info, errXisNoType, typeToString(typ))
v.typ = typ
v.ast = def # no need to copy
if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)
addInterfaceDecl(c, v)
var b = newNodeI(nkConstDef, a.info)
addSon(b, newSymNode(v))
@ -463,7 +461,6 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
if a.kind != nkTypeDef: IllFormedAst(a)
checkSonsLen(a, 3)
var s = semIdentDef(c, a.sons[0], skType)
if s.flags * {sfStar, sfMinus} != {}: incl(s.flags, sfInInterface)
s.typ = newTypeS(tyForward, c)
s.typ.sym = s # process pragmas:
if a.sons[0].kind == nkPragmaExpr:
@ -619,7 +616,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
checkSonsLen(n, codePos + 1)
var s = semIdentDef(c, n.sons[0], kind)
n.sons[namePos] = newSymNode(s)
if sfStar in s.flags: incl(s.flags, sfInInterface)
s.ast = n
pushOwner(s)
openScope(c.tab)

View file

@ -158,15 +158,13 @@ proc transformToExpr(n: PNode): PNode =
nil
proc semTemplateDef(c: PContext, n: PNode): PNode =
var
s: PSym
var s: PSym
if c.p.owner.kind == skModule:
s = semIdentVis(c, skTemplate, n.sons[0], {sfStar})
s = semIdentVis(c, skTemplate, n.sons[0], {sfExported})
incl(s.flags, sfGlobal)
else:
else:
s = semIdentVis(c, skTemplate, n.sons[0], {})
if sfStar in s.flags:
incl(s.flags, sfInInterface) # check parameter list:
# check parameter list:
pushOwner(s)
openScope(c.tab)
n.sons[namePos] = newSymNode(s) # check that no pragmas exist:

View file

@ -50,8 +50,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
x = counter
else:
x = getOrdValue(v)
if i != 1:
if (x != counter): incl(result.flags, tfEnumHasHoles)
if i != 1:
if x != counter: incl(result.flags, tfEnumHasHoles)
if x < counter:
GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
e.ast = strVal # might be nil
@ -63,9 +63,9 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
else: illFormedAst(n)
e.typ = result
e.position = int(counter)
if (result.sym != nil) and (sfInInterface in result.sym.flags):
if result.sym != nil and sfExported in result.sym.flags:
incl(e.flags, sfUsed) # BUGFIX
incl(e.flags, sfInInterface) # BUGFIX
incl(e.flags, sfExported) # BUGFIX
StrTableAdd(c.module.tab, e) # BUGFIX
addSon(result.n, newSymNode(e))
addDeclAt(c, e, c.tab.tos - 1)
@ -240,15 +240,13 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
if sonsLen(n) == 2 and n.sons[0].kind == nkIdent:
result = newSymS(kind, n.sons[1], c)
var v = n.sons[0].ident
if (sfStar in allowed) and (v.id == ord(wStar)):
incl(result.flags, sfStar)
elif (sfMinus in allowed) and (v.id == ord(wMinus)):
incl(result.flags, sfMinus)
else:
if sfExported in allowed and v.id == ord(wStar):
incl(result.flags, sfExported)
else:
LocalError(n.sons[0].info, errInvalidVisibilityX, v.s)
else:
else:
illFormedAst(n)
else:
else:
result = newSymS(kind, n, c)
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
@ -422,7 +420,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
GlobalError(n.info, errTypeExpected)
typ = semTypeNode(c, n.sons[length-2], nil)
for i in countup(0, sonsLen(n) - 3):
f = semIdentWithPragma(c, skField, n.sons[i], {sfStar, sfMinus})
f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
f.typ = typ
f.position = pos
if (rectype != nil) and ({sfImportc, sfExportc} * rectype.flags != {}) and

View file

@ -131,8 +131,6 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
case t.kind
of tyGenericParam:
result = lookupTypeVar(cl, t)
if result.kind == tyGenericInvokation:
result = handleGenericInvokation(cl, result)
of tyGenericInvokation:
result = handleGenericInvokation(cl, t)
of tyGenericBody:

View file

@ -76,15 +76,15 @@ proc copyCandidate(a: var TCandidate, b: TCandidate) =
a.baseTypeMatch = b.baseTypeMatch
copyIdTable(a.bindings, b.bindings)
proc cmpCandidates*(a, b: TCandidate): int =
proc cmpCandidates*(a, b: TCandidate): int =
result = a.exactMatches - b.exactMatches
if result != 0: return
if result != 0: return
result = a.genericMatches - b.genericMatches
if result != 0: return
if result != 0: return
result = a.subtypeMatches - b.subtypeMatches
if result != 0: return
if result != 0: return
result = a.intConvMatches - b.intConvMatches
if result != 0: return
if result != 0: return
result = a.convMatches - b.convMatches
proc writeMatches(c: TCandidate) =
@ -397,13 +397,13 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
InternalError("wrong instantiated type!")
if typeRel(mapping, f.sons[i], a.sons[i]) < isGeneric: return
result = isGeneric
else:
else:
result = typeRel(mapping, f.sons[0], a)
if result != isNone:
if result != isNone:
# we steal the generic parameters from the tyGenericBody:
for i in countup(1, sonsLen(f) - 1):
for i in countup(1, sonsLen(f) - 1):
var x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
if (x == nil) or (x.kind == tyGenericParam):
if x == nil or x.kind == tyGenericParam:
InternalError("wrong instantiated type!")
idTablePut(mapping, f.sons[i], x)
of tyGenericParam:
@ -522,7 +522,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
arg: PNode): PNode =
if (arg == nil) or (arg.kind != nkSymChoice):
if arg == nil or arg.kind != nkSymChoice:
result = ParamTypesMatchAux(c, m, f, a, arg)
else:
# CAUTION: The order depends on the used hashing scheme. Thus it is
@ -555,8 +555,6 @@ proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
x = z
elif cmp == 0:
y = z # z is as good as x
else:
nil
if x.state == csEmpty:
result = nil
elif (y.state == csMatch) and (cmpCandidates(x, y) == 0):
@ -620,7 +618,7 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
m.baseTypeMatch = false
var arg = ParamTypesMatch(c, m, formal.typ,
n.sons[a].typ, n.sons[a].sons[1])
if (arg == nil):
if arg == nil:
m.state = csNoMatch
return
if m.baseTypeMatch:

View file

@ -25,7 +25,7 @@ type
wAddr, wAnd, wAs, wAsm, wAtomic,
wBind, wBlock, wBreak, wCase, wCast, wConst,
wContinue, wConverter, wDiscard, wDistinct, wDiv, wElif, wElse, wEnd, wEnum,
wExcept, wFinally, wFor, wFrom, wGeneric, wIf, wImplies, wImport, wIn,
wExcept, wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn,
wInclude, wIs, wIsnot, wIterator, wLambda, wLet,
wMacro, wMethod, wMod, wNil,
wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn,
@ -34,6 +34,7 @@ type
wColon, wColonColon, wEquals, wDot, wDotDot, wStar, wMinus,
wMagic, wThread, wFinal, wProfiler, wObjChecks,
wImportCpp, wImportObjC,
wImportCompilerProc,
wImportc, wExportc, wExtern,
wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader,
@ -51,7 +52,7 @@ type
wPragma,
wCompileTime, wGc, wRefc, wBoehm, wA, wOpt, wO, wApp, wConsole, wGui,
wPassc, wT, wPassl, wL, wListcmd, wGendoc, wGenmapping, wOs, wCpu,
wGenerate, wG, wC, wCpp, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
wGenerate, wG, wC, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced, wSkipcfg, wSkipProjCfg,
wCc, wGenscript, wCheckPoint, wThreadAnalysis, wNoMain, wSubsChar,
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
@ -72,7 +73,7 @@ const
"bind", "block", "break", "case", "cast",
"const", "continue", "converter", "discard", "distinct", "div", "elif",
"else", "end", "enum", "except", "finally", "for", "from", "generic", "if",
"implies", "import", "in", "include", "is", "isnot", "iterator",
"import", "in", "include", "is", "isnot", "iterator",
"lambda", "let",
"macro", "method", "mod", "nil", "not", "notin", "object", "of", "or",
"out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "template",
@ -81,6 +82,8 @@ const
":", "::", "=", ".", "..", "*", "-",
"magic", "thread", "final", "profiler", "objchecks",
"importcpp", "importobjc",
"importcompilerproc", "importc", "exportc", "extern",
"align", "nodecl", "pure", "volatile", "register", "sideeffect",
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
@ -99,7 +102,7 @@ const
"pragma",
"compiletime", "gc", "refc", "boehm", "a", "opt", "o", "app", "console",
"gui", "passc", "t", "passl", "l", "listcmd", "gendoc", "genmapping", "os",
"cpu", "generate", "g", "c", "cpp", "borrow", "run", "r", "verbosity", "v",
"cpu", "generate", "g", "c", "borrow", "run", "r", "verbosity", "v",
"help", "h", "symbolfiles", "fieldchecks", "x", "version", "advanced",
"skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "threadanalysis",
"nomain", "subschar", "acyclic", "shallow", "unroll", "linearscanend",