'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
|
sfThread, # proc will run as a thread
|
||||||
# variable is a thread variable
|
# variable is a thread variable
|
||||||
sfCompileTime, # proc can be evaluated at compile time
|
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
|
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;
|
sfInfixCall, # symbol needs infix call syntax in target language;
|
||||||
|
|
@ -663,7 +663,9 @@ type
|
||||||
locOther # location is something other
|
locOther # location is something other
|
||||||
TLocFlag* = enum
|
TLocFlag* = enum
|
||||||
lfIndirect, # backend introduced a pointer
|
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
|
lfNoDeepCopy, # no need for a deep copy
|
||||||
lfNoDecl, # do not declare it in C
|
lfNoDecl, # do not declare it in C
|
||||||
lfDynamicLib, # link symbol to dynamic library
|
lfDynamicLib, # link symbol to dynamic library
|
||||||
|
|
@ -915,10 +917,6 @@ const
|
||||||
|
|
||||||
skIterators* = {skIterator, skClosureIterator}
|
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
|
var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things
|
||||||
|
|
||||||
proc isCallExpr*(n: PNode): bool =
|
proc isCallExpr*(n: PNode): bool =
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,8 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||||
genVarPrototypeAux(generatedHeader, v)
|
genVarPrototypeAux(generatedHeader, v)
|
||||||
registerGcRoot(p, v)
|
registerGcRoot(p, v)
|
||||||
else:
|
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
|
if imm and p.module.compileToCpp and p.splitDecls == 0 and
|
||||||
not containsHiddenPointer(v.typ):
|
not containsHiddenPointer(v.typ):
|
||||||
# C++ really doesn't like things like 'Foo f; f = x' as that invokes a
|
# C++ really doesn't like things like 'Foo f; f = x' as that invokes a
|
||||||
|
|
@ -211,7 +212,18 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||||
genLineDir(p, a)
|
genLineDir(p, a)
|
||||||
let decl = localVarDecl(p, v)
|
let decl = localVarDecl(p, v)
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
initLocExprSingleUse(p, a.sons[2], tmp)
|
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)
|
lineF(p, cpsStmts, "$# = $#;$n", decl, tmp.rdLoc)
|
||||||
return
|
return
|
||||||
assignLocalVar(p, v)
|
assignLocalVar(p, v)
|
||||||
|
|
|
||||||
|
|
@ -358,17 +358,6 @@ proc deinitGCFrame(p: BProc): PRope =
|
||||||
result = ropecg(p.module,
|
result = ropecg(p.module,
|
||||||
"if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n")
|
"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) =
|
proc localDebugInfo(p: BProc, s: PSym) =
|
||||||
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
||||||
# XXX work around a bug: No type information for open arrays possible:
|
# 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 genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
|
||||||
proc intLiteral(i: BiggestInt): PRope
|
proc intLiteral(i: BiggestInt): PRope
|
||||||
proc genLiteral(p: BProc, n: PNode): 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) =
|
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
|
||||||
initLoc(result, locNone, e.typ, OnUnknown)
|
initLoc(result, locNone, e.typ, OnUnknown)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ const
|
||||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||||
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
||||||
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
||||||
wOverride}
|
wOverride, wConstructor}
|
||||||
converterPragmas* = procPragmas
|
converterPragmas* = procPragmas
|
||||||
methodPragmas* = procPragmas
|
methodPragmas* = procPragmas
|
||||||
templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
|
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, sfGlobal)
|
||||||
incl(sym.flags, sfPure)
|
incl(sym.flags, sfPure)
|
||||||
of wMerge:
|
of wMerge:
|
||||||
|
# only supported for backwards compat, doesn't do anything anymore
|
||||||
noVal(it)
|
noVal(it)
|
||||||
incl(sym.flags, sfMerge)
|
of wConstructor:
|
||||||
|
noVal(it)
|
||||||
|
incl(sym.flags, sfConstructor)
|
||||||
of wHeader:
|
of wHeader:
|
||||||
var lib = getLib(c, libHeader, getStrLitNode(c, it))
|
var lib = getLib(c, libHeader, getStrLitNode(c, it))
|
||||||
addToLib(lib, sym)
|
addToLib(lib, sym)
|
||||||
|
|
|
||||||
|
|
@ -579,8 +579,7 @@ proc getMergeOp(n: PNode): PSym =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix,
|
of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix,
|
||||||
nkCallStrLit:
|
nkCallStrLit:
|
||||||
if (n.sons[0].kind == nkSym) and (n.sons[0].sym.kind == skProc) and
|
if n.sons[0].kind == nkSym and n.sons[0].sym.magic == mConStrStr:
|
||||||
(sfMerge in n.sons[0].sym.flags):
|
|
||||||
result = n.sons[0].sym
|
result = n.sons[0].sym
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ type
|
||||||
|
|
||||||
wDestroy,
|
wDestroy,
|
||||||
|
|
||||||
wImmediate, wDestructor, wDelegator, wOverride,
|
wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
|
||||||
wImportCpp, wImportObjC,
|
wImportCpp, wImportObjC,
|
||||||
wImportCompilerProc,
|
wImportCompilerProc,
|
||||||
wImportc, wExportc, wIncompleteStruct, wRequiresInit,
|
wImportc, wExportc, wIncompleteStruct, wRequiresInit,
|
||||||
|
|
@ -123,7 +123,7 @@ const
|
||||||
|
|
||||||
"destroy",
|
"destroy",
|
||||||
|
|
||||||
"immediate", "destructor", "delegator", "override",
|
"immediate", "constructor", "destructor", "delegator", "override",
|
||||||
"importcpp", "importobjc",
|
"importcpp", "importobjc",
|
||||||
"importcompilerproc", "importc", "exportc", "incompletestruct",
|
"importcompilerproc", "importc", "exportc", "incompletestruct",
|
||||||
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
||||||
|
|
|
||||||
14
doc/nimc.txt
14
doc/nimc.txt
|
|
@ -545,6 +545,20 @@ instead:
|
||||||
let x = newFoo(3, 4)
|
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
|
Wrapping destructors
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue