diff options
author | Araq <rumpf_a@web.de> | 2015-03-18 00:46:10 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-03-18 11:42:37 +0100 |
commit | 910ef7b2d109f7516f8dab054bd0d41ff733047a (patch) | |
tree | 51bc150866f4d51a9974e031389831208deb3b25 | |
parent | 1fc590b6ea276eb2dedc2638fde935126b63630c (diff) | |
download | Nim-910ef7b2d109f7516f8dab054bd0d41ff733047a.tar.gz |
'constructor' pragma for C++ support
-rw-r--r-- | compiler/ast.nim | 10 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 18 | ||||
-rw-r--r-- | compiler/cgen.nim | 12 | ||||
-rw-r--r-- | compiler/pragmas.nim | 7 | ||||
-rw-r--r-- | compiler/transf.nim | 3 | ||||
-rw-r--r-- | compiler/wordrecg.nim | 114 | ||||
-rw-r--r-- | doc/nimc.txt | 16 |
7 files changed, 98 insertions, 82 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 274a49b52..660f3e45e 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -257,7 +257,7 @@ type sfThread, # proc will run as a thread # variable is a thread variable sfCompileTime, # proc can be evaluated at compile time - sfMerge, # proc can be merged with itself + sfConstructor, # proc is a C++ constructor sfDeadCodeElim, # dead code elimination for the module is turned on sfBorrow, # proc is borrowed sfInfixCall, # symbol needs infix call syntax in target language; @@ -663,7 +663,9 @@ type locOther # location is something other TLocFlag* = enum lfIndirect, # backend introduced a pointer - lfParamCopy, # backend introduced a parameter copy (LLVM) + lfFullExternalName, # only used when 'gCmd == cmdPretty': Indicates + # that the symbol has been imported via 'importc: "fullname"' and + # no format string. lfNoDeepCopy, # no need for a deep copy lfNoDecl, # do not declare it in C lfDynamicLib, # link symbol to dynamic library @@ -915,10 +917,6 @@ const skIterators* = {skIterator, skClosureIterator} - lfFullExternalName* = lfParamCopy # \ - # only used when 'gCmd == cmdPretty': Indicates that the symbol has been - # imported via 'importc: "fullname"' and no format string. - var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things proc isCallExpr*(n: PNode): bool = diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 12bf069bf..441ceb22a 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -202,7 +202,8 @@ proc genSingleVar(p: BProc, a: PNode) = genVarPrototypeAux(generatedHeader, v) registerGcRoot(p, v) else: - let imm = isAssignedImmediately(a.sons[2]) + let value = a.sons[2] + let imm = isAssignedImmediately(value) if imm and p.module.compileToCpp and p.splitDecls == 0 and not containsHiddenPointer(v.typ): # C++ really doesn't like things like 'Foo f; f = x' as that invokes a @@ -211,8 +212,19 @@ proc genSingleVar(p: BProc, a: PNode) = genLineDir(p, a) let decl = localVarDecl(p, v) var tmp: TLoc - initLocExprSingleUse(p, a.sons[2], tmp) - lineF(p, cpsStmts, "$# = $#;$n", decl, tmp.rdLoc) + if value.kind in nkCallKinds and value[0].kind == nkSym and + sfConstructor in value[0].sym.flags: + var params: PRope + let typ = skipTypes(value.sons[0].typ, abstractInst) + assert(typ.kind == tyProc) + for i in 1.. <value.len: + if params != nil: params.app(~", ") + assert(sonsLen(typ) == sonsLen(typ.n)) + app(params, genOtherArg(p, value, i, typ)) + lineF(p, cpsStmts, "$#($#);$n", decl, params) + else: + initLocExprSingleUse(p, value, tmp) + lineF(p, cpsStmts, "$# = $#;$n", decl, tmp.rdLoc) return assignLocalVar(p, v) initLocalVar(p, v, imm) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index ebe812e8b..0b0526b65 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -358,17 +358,6 @@ proc deinitGCFrame(p: BProc): PRope = result = ropecg(p.module, "if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n") -proc allocParam(p: BProc, s: PSym) = - assert(s.kind == skParam) - if lfParamCopy notin s.loc.flags: - inc(p.labels) - var tmp = con("%LOC", toRope(p.labels)) - incl(s.loc.flags, lfParamCopy) - incl(s.loc.flags, lfIndirect) - lineF(p, cpsInit, "$1 = alloca $3$n" & "store $3 $2, $3* $1$n", - [tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)]) - s.loc.r = tmp - proc localDebugInfo(p: BProc, s: PSym) = if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return # XXX work around a bug: No type information for open arrays possible: @@ -471,6 +460,7 @@ proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) proc intLiteral(i: BiggestInt): PRope proc genLiteral(p: BProc, n: PNode): PRope +proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): PRope proc initLocExpr(p: BProc, e: PNode, result: var TLoc) = initLoc(result, locNone, e.typ, OnUnknown) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 1033f72f5..056e4f4c0 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -25,7 +25,7 @@ const wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, - wOverride} + wOverride, wConstructor} converterPragmas* = procPragmas methodPragmas* = procPragmas templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, @@ -665,8 +665,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, incl(sym.flags, sfGlobal) incl(sym.flags, sfPure) of wMerge: + # only supported for backwards compat, doesn't do anything anymore noVal(it) - incl(sym.flags, sfMerge) + of wConstructor: + noVal(it) + incl(sym.flags, sfConstructor) of wHeader: var lib = getLib(c, libHeader, getStrLitNode(c, it)) addToLib(lib, sym) diff --git a/compiler/transf.nim b/compiler/transf.nim index 325ce9d5e..2143b6bec 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -579,8 +579,7 @@ proc getMergeOp(n: PNode): PSym = case n.kind of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, nkCallStrLit: - if (n.sons[0].kind == nkSym) and (n.sons[0].sym.kind == skProc) and - (sfMerge in n.sons[0].sym.flags): + if n.sons[0].kind == nkSym and n.sons[0].sym.magic == mConStrStr: result = n.sons[0].sym else: discard diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index ae036bc0c..393798947 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -13,44 +13,44 @@ # does not support strings. Without this the code would # be slow and unreadable. -import +import hashes, strutils, idents # Keywords must be kept sorted and within a range type - TSpecialWord* = enum - wInvalid, - - wAddr, wAnd, wAs, wAsm, wAtomic, - wBind, wBlock, wBreak, wCase, wCast, wConst, - wContinue, wConverter, wDefer, wDiscard, wDistinct, wDiv, wDo, + TSpecialWord* = enum + wInvalid, + + wAddr, wAnd, wAs, wAsm, wAtomic, + wBind, wBlock, wBreak, wCase, wCast, wConst, + wContinue, wConverter, wDefer, wDiscard, wDistinct, wDiv, wDo, wElif, wElse, wEnd, wEnum, wExcept, wExport, - wFinally, wFor, wFrom, wFunc, wGeneric, wIf, wImport, wIn, + wFinally, wFor, wFrom, wFunc, wGeneric, wIf, wImport, wIn, wInclude, wInterface, wIs, wIsnot, wIterator, wLet, - wMacro, wMethod, wMixin, wMod, wNil, - wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, - wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, + wMacro, wMethod, wMixin, wMod, wNil, + wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, + wShl, wShr, wStatic, wTemplate, wTry, wTuple, wType, wUsing, wVar, wWhen, wWhile, wWith, wWithout, wXor, wYield, - + wColon, wColonColon, wEquals, wDot, wDotDot, wStar, wMinus, wMagic, wThread, wFinal, wProfiler, wObjChecks, wDestroy, - - wImmediate, wDestructor, wDelegator, wOverride, + + wImmediate, wConstructor, wDestructor, wDelegator, wOverride, wImportCpp, wImportObjC, wImportCompilerProc, wImportc, wExportc, wIncompleteStruct, wRequiresInit, wAlign, wNodecl, wPure, wSideeffect, wHeader, - wNosideeffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib, - wCompilerproc, wProcVar, - wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef, - wLinedir, wStacktrace, wLinetrace, wLink, wCompile, - wLinksys, wDeprecated, wVarargs, wCallconv, wBreakpoint, wDebugger, - wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline, - wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks, + wNosideeffect, wGcSafe, wNoreturn, wMerge, wLib, wDynlib, + wCompilerproc, wProcVar, + wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef, + wLinedir, wStacktrace, wLinetrace, wLink, wCompile, + wLinksys, wDeprecated, wVarargs, wCallconv, wBreakpoint, wDebugger, + wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline, + wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks, wFloatchecks, wNanChecks, wInfChecks, wAssertions, wPatterns, wWarnings, @@ -59,11 +59,11 @@ type wPragma, wCompileTime, wNoInit, wPassc, wPassl, wBorrow, wDiscardable, - wFieldChecks, - wWatchPoint, wSubsChar, - wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, + wFieldChecks, + wWatchPoint, wSubsChar, + wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt, wExperimental, - wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, + wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wAsmNoStackFrame, wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, @@ -82,38 +82,38 @@ type wStdIn, wStdOut, wStdErr, wInOut, wByCopy, wByRef, wOneWay, - + TSpecialWords* = set[TSpecialWord] -const +const oprLow* = ord(wColon) oprHigh* = ord(wDotDot) - + nimKeywordsLow* = ord(wAsm) nimKeywordsHigh* = ord(wYield) - + ccgKeywordsLow* = ord(wAuto) ccgKeywordsHigh* = ord(wOneWay) - + cppNimSharedKeywords* = { wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport, wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing} - specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", - - "addr", "and", "as", "asm", "atomic", - "bind", "block", "break", "case", "cast", + specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", + + "addr", "and", "as", "asm", "atomic", + "bind", "block", "break", "case", "cast", "const", "continue", "converter", "defer", "discard", "distinct", "div", "do", - "elif", "else", "end", "enum", "except", "export", - "finally", "for", "from", "func", "generic", "if", + "elif", "else", "end", "enum", "except", "export", + "finally", "for", "from", "func", "generic", "if", "import", "in", "include", "interface", "is", "isnot", "iterator", "let", "macro", "method", "mixin", "mod", "nil", "not", "notin", - "object", "of", "or", + "object", "of", "or", "out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "static", - "template", "try", "tuple", "type", "using", "var", + "template", "try", "tuple", "type", "using", "var", "when", "while", "with", "without", "xor", "yield", @@ -122,22 +122,22 @@ const "magic", "thread", "final", "profiler", "objchecks", "destroy", - - "immediate", "destructor", "delegator", "override", + + "immediate", "constructor", "destructor", "delegator", "override", "importcpp", "importobjc", "importcompilerproc", "importc", "exportc", "incompletestruct", "requiresinit", "align", "nodecl", "pure", "sideeffect", - "header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib", - "compilerproc", "procvar", "fatal", "error", "warning", "hint", "line", - "push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace", - "link", "compile", "linksys", "deprecated", "varargs", - "callconv", "breakpoint", "debugger", "nimcall", "stdcall", + "header", "nosideeffect", "gcsafe", "noreturn", "merge", "lib", "dynlib", + "compilerproc", "procvar", "fatal", "error", "warning", "hint", "line", + "push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace", + "link", "compile", "linksys", "deprecated", "varargs", + "callconv", "breakpoint", "debugger", "nimcall", "stdcall", "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure", - "noconv", "on", "off", "checks", "rangechecks", "boundchecks", + "noconv", "on", "off", "checks", "rangechecks", "boundchecks", "overflowchecks", "nilchecks", "floatchecks", "nanchecks", "infchecks", - "assertions", "patterns", "warnings", "hints", + "assertions", "patterns", "warnings", "hints", "optimization", "raises", "writes", "reads", "size", "effects", "tags", "deadcodeelim", "safecode", "noforward", "pragma", @@ -149,7 +149,7 @@ const "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", "guard", "locks", - + "auto", "bool", "catch", "char", "class", "const_cast", "default", "delete", "double", "dynamic_cast", "explicit", "extern", "false", @@ -169,22 +169,22 @@ const "inout", "bycopy", "byref", "oneway", ] -proc findStr*(a: openArray[string], s: string): int = - for i in countup(low(a), high(a)): - if cmpIgnoreStyle(a[i], s) == 0: +proc findStr*(a: openArray[string], s: string): int = + for i in countup(low(a), high(a)): + if cmpIgnoreStyle(a[i], s) == 0: return i result = - 1 -proc whichKeyword*(id: PIdent): TSpecialWord = +proc whichKeyword*(id: PIdent): TSpecialWord = if id.id < 0: result = wInvalid else: result = TSpecialWord(id.id) -proc whichKeyword*(id: string): TSpecialWord = +proc whichKeyword*(id: string): TSpecialWord = result = whichKeyword(getIdent(id)) - -proc initSpecials() = + +proc initSpecials() = # initialize the keywords: - for s in countup(succ(low(specialWords)), high(specialWords)): + for s in countup(succ(low(specialWords)), high(specialWords)): getIdent(specialWords[s], hashIgnoreStyle(specialWords[s])).id = ord(s) - + initSpecials() diff --git a/doc/nimc.txt b/doc/nimc.txt index c6b0b5255..831fce567 100644 --- a/doc/nimc.txt +++ b/doc/nimc.txt @@ -545,6 +545,20 @@ instead: let x = newFoo(3, 4) +Wrapping constructors +~~~~~~~~~~~~~~~~~~~~~ + +Sometimes a C++ class has a private copy constructor and so code like +``Class c = Class(1,2);`` must not be generated but instead ``Class c(1,2);``. +For this purpose the Nim proc that wraps a C++ constructor needs to be +annotated with the `constructor`:idx: pragma. This pragma also helps to generate +faster C++ code since construction then doesn't invoke the copy constructor: + +.. code-block:: nim + # a better constructor of 'Foo': + proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)", constructor.} + + Wrapping destructors ~~~~~~~~~~~~~~~~~~~~ @@ -608,7 +622,7 @@ allows *sloppy* interfacing with libraries written in Objective C: - (void)greet:(long)x y:(long)dummy { - printf("Hello, World!\n"); + printf("Hello, World!\n"); } @end |