mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
'constructor' pragma for C++ support
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user