Nim namespace for cpp (#7453)

- new option --usenamespace to generate nim cpp code in its own namespace Nim
- minor changes for compatibility with the new Embarcadero = Borland C++-Builder (bcc)
This commit is contained in:
AdrianV 2018-04-15 13:43:01 +02:00 • committed by Andreas Rumpf
commit 0ce28d15cc
8 changed files with 44 additions and 7 deletions

View file

@ -79,6 +79,10 @@
target. To use it, compile your code with `--hotCodeReloading:on` and use a target. To use it, compile your code with `--hotCodeReloading:on` and use a
helper library such as LiveReload or BrowserSync. helper library such as LiveReload or BrowserSync.
- A new compiler option `--cppCompileToNamespace` puts the generated C++ code
into the namespace "Nim" in order to avoid naming conflicts with existing
C++ code. This is done for all Nim code - internal and exported.
- Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual - Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual
machine. machine.

View file

@ -676,6 +676,12 @@ proc generateHeaders(m: BModule) =
add(m.s[cfsHeaders], "#undef powerpc" & tnl) add(m.s[cfsHeaders], "#undef powerpc" & tnl)
add(m.s[cfsHeaders], "#undef unix" & tnl) add(m.s[cfsHeaders], "#undef unix" & tnl)
proc openNamespaceNim(): Rope =
result.add("namespace Nim {" & tnl)
proc closeNamespaceNim(): Rope =
result.add("}" & tnl)
proc closureSetup(p: BProc, prc: PSym) = proc closureSetup(p: BProc, prc: PSym) =
if tfCapturesEnv notin prc.typ.flags: return if tfCapturesEnv notin prc.typ.flags: return
# prc.ast[paramsPos].last contains the type we're after: # prc.ast[paramsPos].last contains the type we're after:
@ -918,6 +924,7 @@ proc addIntTypes(result: var Rope) {.inline.} =
addf(result, "#define NIM_NEW_MANGLING_RULES" & tnl & addf(result, "#define NIM_NEW_MANGLING_RULES" & tnl &
"#define NIM_INTBITS $1" & tnl, [ "#define NIM_INTBITS $1" & tnl, [
platform.CPU[targetCPU].intSize.rope]) platform.CPU[targetCPU].intSize.rope])
if useNimNamespace : result.add("#define USE_NIM_NAMESPACE" & tnl)
proc getCopyright(cfile: Cfile): Rope = proc getCopyright(cfile: Cfile): Rope =
if optCompileOnly in gGlobalOptions: if optCompileOnly in gGlobalOptions:
@ -1083,7 +1090,11 @@ proc genMainProc(m: BModule) =
appcg(m, m.s[cfsProcs], nimMain, appcg(m, m.s[cfsProcs], nimMain,
[m.g.mainModInit, initStackBottomCall, rope(m.labels)]) [m.g.mainModInit, initStackBottomCall, rope(m.labels)])
if optNoMain notin gGlobalOptions: if optNoMain notin gGlobalOptions:
if useNimNamespace:
m.s[cfsProcs].add closeNamespaceNim() & "using namespace Nim;" & tnl
appcg(m, m.s[cfsProcs], otherMain, []) appcg(m, m.s[cfsProcs], otherMain, [])
if useNimNamespace: m.s[cfsProcs].add openNamespaceNim()
proc getSomeInitName(m: PSym, suffix: string): Rope = proc getSomeInitName(m: PSym, suffix: string): Rope =
assert m.kind == skModule assert m.kind == skModule
@ -1191,7 +1202,9 @@ proc genModule(m: BModule, cfile: Cfile): Rope =
add(result, genSectionStart(i)) add(result, genSectionStart(i))
add(result, m.s[i]) add(result, m.s[i])
add(result, genSectionEnd(i)) add(result, genSectionEnd(i))
if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim()
add(result, m.s[cfsInitProc]) add(result, m.s[cfsInitProc])
if useNimNamespace: result.add closeNamespaceNim()
proc newPreInitProc(m: BModule): BProc = proc newPreInitProc(m: BModule): BProc =
result = newProc(nil, m) result = newProc(nil, m)
@ -1330,11 +1343,13 @@ proc writeHeader(m: BModule) =
add(result, genSectionStart(i)) add(result, genSectionStart(i))
add(result, m.s[i]) add(result, m.s[i])
add(result, genSectionEnd(i)) add(result, genSectionEnd(i))
if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim()
add(result, m.s[cfsInitProc]) add(result, m.s[cfsInitProc])
if optGenDynLib in gGlobalOptions: if optGenDynLib in gGlobalOptions:
result.add("N_LIB_IMPORT ") result.add("N_LIB_IMPORT ")
result.addf("N_CDECL(void, NimMain)(void);$n", []) result.addf("N_CDECL(void, NimMain)(void);$n", [])
if useNimNamespace: result.add closeNamespaceNim()
result.addf("#endif /* $1 */$n", [guard]) result.addf("#endif /* $1 */$n", [guard])
writeRope(result, m.filename) writeRope(result, m.filename)

View file

@ -698,6 +698,11 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
newDestructors = true newDestructors = true
defineSymbol("nimNewRuntime") defineSymbol("nimNewRuntime")
of "cppcompiletonamespace":
expectNoArg(switch, arg, pass, info)
useNimNamespace = true
defineSymbol("cppCompileToNamespace")
else: else:
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg) if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
else: invalidCmdLineOption(pass, switch, info) else: invalidCmdLineOption(pass, switch, info)

View file

@ -176,10 +176,10 @@ compiler bcc:
result = ( result = (
name: "bcc", name: "bcc",
objExt: "obj", objExt: "obj",
optSpeed: " -O2 -6 ", optSpeed: " -O3 -6 ",
optSize: " -O1 -6 ", optSize: " -O1 -6 ",
compilerExe: "bcc32", compilerExe: "bcc32c",
cppCompiler: "", cppCompiler: "cpp32c",
compileTmpl: "-c $options $include -o$objfile $file", compileTmpl: "-c $options $include -o$objfile $file",
buildGui: " -tW", buildGui: " -tW",
buildDll: " -tWD", buildDll: " -tWD",
@ -193,7 +193,9 @@ compiler bcc:
pic: "", pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n", asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2", structStmtFmt: "$1 $2",
props: {hasCpp}) props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard,
hasAttribute})
# Digital Mars C Compiler # Digital Mars C Compiler
compiler dmc: compiler dmc:

View file

@ -149,6 +149,7 @@ var
gExperimentalMode*: bool gExperimentalMode*: bool
newDestructors*: bool newDestructors*: bool
gDynlibOverrideAll*: bool gDynlibOverrideAll*: bool
useNimNamespace*: bool
type type
SymbolFilesOption* = enum SymbolFilesOption* = enum

View file

@ -76,6 +76,7 @@ Advanced options:
--NimblePath:PATH add a path for Nimble support --NimblePath:PATH add a path for Nimble support
--noNimblePath deactivate the Nimble path --noNimblePath deactivate the Nimble path
--noCppExceptions use default exception handling with C++ backend --noCppExceptions use default exception handling with C++ backend
--cppCompileToNamespace use namespace "Nim" for the generated C++ code
--excludePath:PATH exclude a path from the list of search paths --excludePath:PATH exclude a path from the list of search paths
--dynlibOverride:SYMBOL marks SYMBOL so that dynlib:SYMBOL --dynlibOverride:SYMBOL marks SYMBOL so that dynlib:SYMBOL
has no effect and can be statically linked instead; has no effect and can be statically linked instead;

View file

@ -264,6 +264,11 @@ __clang__
# define HAVE_STDINT_H # define HAVE_STDINT_H
#endif #endif
/* wrap all Nim typedefs into namespace Nim */
#ifdef USE_NIM_NAMESPACE
namespace Nim {
#endif
/* bool types (C++ has it): */ /* bool types (C++ has it): */
#ifdef __cplusplus #ifdef __cplusplus
# ifndef NIM_TRUE # ifndef NIM_TRUE
@ -413,8 +418,8 @@ typedef struct TStringDesc* string;
# endif # endif
#endif #endif
typedef struct TFrame TFrame; typedef struct TFrame_ TFrame;
struct TFrame { struct TFrame_ {
TFrame* prev; TFrame* prev;
NCSTRING procname; NCSTRING procname;
NI line; NI line;
@ -476,6 +481,10 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
"error: 'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array with a negative size" */ "error: 'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array with a negative size" */
typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1]; typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
#ifdef USE_NIM_NAMESPACE
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
# define NIM_EXTERNC extern "C" # define NIM_EXTERNC extern "C"
#else #else

View file

@ -295,7 +295,7 @@ else:
when (defined(x86) or defined(amd64)) and defined(vcc): when (defined(x86) or defined(amd64)) and defined(vcc):
proc cpuRelax* {.importc: "YieldProcessor", header: "<windows.h>".} proc cpuRelax* {.importc: "YieldProcessor", header: "<windows.h>".}
elif (defined(x86) or defined(amd64)) and someGcc: elif (defined(x86) or defined(amd64)) and (someGcc or defined(bcc)):
proc cpuRelax* {.inline.} = proc cpuRelax* {.inline.} =
{.emit: """asm volatile("pause" ::: "memory");""".} {.emit: """asm volatile("pause" ::: "memory");""".}
elif someGcc or defined(tcc): elif someGcc or defined(tcc):