'constructor' pragma for C++ support
This commit is contained in:
parent
1fc590b6ea
commit
910ef7b2d1
7 changed files with 98 additions and 82 deletions
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ type
|
|||
|
||||
wDestroy,
|
||||
|
||||
wImmediate, wDestructor, wDelegator, wOverride,
|
||||
wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
|
||||
wImportCpp, wImportObjC,
|
||||
wImportCompilerProc,
|
||||
wImportc, wExportc, wIncompleteStruct, wRequiresInit,
|
||||
|
|
@ -123,7 +123,7 @@ const
|
|||
|
||||
"destroy",
|
||||
|
||||
"immediate", "destructor", "delegator", "override",
|
||||
"immediate", "constructor", "destructor", "delegator", "override",
|
||||
"importcpp", "importobjc",
|
||||
"importcompilerproc", "importc", "exportc", "incompletestruct",
|
||||
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
||||
|
|
|
|||
16
doc/nimc.txt
16
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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue