generic define pragma + string alias (#20979)
* generic `define` pragma + string alias * clean * add tests and document * remove char/float, minimize changelog
This commit is contained in:
parent
2564b5c938
commit
9a50033d5b
8 changed files with 218 additions and 53 deletions
24
changelog.md
24
changelog.md
|
|
@ -221,9 +221,33 @@
|
||||||
- Full command syntax and block arguments i.e. `foo a, b: c` are now allowed
|
- Full command syntax and block arguments i.e. `foo a, b: c` are now allowed
|
||||||
for the right-hand side of type definitions in type sections. Previously
|
for the right-hand side of type definitions in type sections. Previously
|
||||||
they would error with "invalid indentation".
|
they would error with "invalid indentation".
|
||||||
|
|
||||||
|
- Compile-time define changes:
|
||||||
- `defined` now accepts identifiers separated by dots, i.e. `defined(a.b.c)`.
|
- `defined` now accepts identifiers separated by dots, i.e. `defined(a.b.c)`.
|
||||||
In the command line, this is defined as `-d:a.b.c`. Older versions can
|
In the command line, this is defined as `-d:a.b.c`. Older versions can
|
||||||
use accents as in ``defined(`a.b.c`)`` to access such defines.
|
use accents as in ``defined(`a.b.c`)`` to access such defines.
|
||||||
|
- [Define pragmas for constants](https://nim-lang.github.io/Nim/manual.html#implementation-specific-pragmas-compileminustime-define-pragmas)
|
||||||
|
now support a string argument for qualified define names.
|
||||||
|
|
||||||
|
```nim
|
||||||
|
# -d:package.FooBar=42
|
||||||
|
const FooBar {.intdefine: "package.FooBar".}: int = 5
|
||||||
|
echo FooBar # 42
|
||||||
|
```
|
||||||
|
|
||||||
|
This was added to help disambiguate similar define names for different packages.
|
||||||
|
In older versions, this could only be achieved with something like the following:
|
||||||
|
|
||||||
|
```nim
|
||||||
|
const FooBar = block:
|
||||||
|
const `package.FooBar` {.intdefine.}: int = 5
|
||||||
|
`package.FooBar`
|
||||||
|
```
|
||||||
|
- A generic `define` pragma for constants has been added that interprets
|
||||||
|
the value of the define based on the type of the constant value.
|
||||||
|
See the [experimental manual](https://nim-lang.github.io/Nim/manual_experimental.html#generic-define-pragma)
|
||||||
|
for a list of supported types.
|
||||||
|
|
||||||
- [Macro pragmas](https://nim-lang.github.io/Nim/manual.html#userminusdefined-pragmas-macro-pragmas) changes:
|
- [Macro pragmas](https://nim-lang.github.io/Nim/manual.html#userminusdefined-pragmas-macro-pragmas) changes:
|
||||||
- Templates now accept macro pragmas.
|
- Templates now accept macro pragmas.
|
||||||
- Macro pragmas for var/let/const sections have been redesigned in a way that works
|
- Macro pragmas for var/let/const sections have been redesigned in a way that works
|
||||||
|
|
|
||||||
|
|
@ -712,7 +712,7 @@ type
|
||||||
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
|
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
|
||||||
mNHint, mNWarning, mNError,
|
mNHint, mNWarning, mNError,
|
||||||
mInstantiationInfo, mGetTypeInfo, mGetTypeInfoV2,
|
mInstantiationInfo, mGetTypeInfo, mGetTypeInfoV2,
|
||||||
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
|
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mGenericDefine, mRunnableExamples,
|
||||||
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
|
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
|
||||||
mSymIsInstantiationOf, mNodeId, mPrivateAccess, mZeroDefault
|
mSymIsInstantiationOf, mNodeId, mPrivateAccess, mZeroDefault
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -149,3 +149,5 @@ proc initDefines*(symbols: StringTableRef) =
|
||||||
defineSymbol("nimHasOutParams")
|
defineSymbol("nimHasOutParams")
|
||||||
defineSymbol("nimHasSystemRaisesDefect")
|
defineSymbol("nimHasSystemRaisesDefect")
|
||||||
defineSymbol("nimHasWarnUnnamedBreak")
|
defineSymbol("nimHasWarnUnnamedBreak")
|
||||||
|
defineSymbol("nimHasGenericDefine")
|
||||||
|
defineSymbol("nimHasDefineAliases")
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,8 @@ const
|
||||||
wGuard, wGoto, wCursor, wNoalias, wAlign}
|
wGuard, wGoto, wCursor, wNoalias, wAlign}
|
||||||
constPragmas* = declPragmas + {wHeader, wMagic,
|
constPragmas* = declPragmas + {wHeader, wMagic,
|
||||||
wGensym, wInject,
|
wGensym, wInject,
|
||||||
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
|
wIntDefine, wStrDefine, wBoolDefine, wDefine,
|
||||||
|
wCompilerProc, wCore}
|
||||||
paramPragmas* = {wNoalias, wInject, wGensym}
|
paramPragmas* = {wNoalias, wInject, wGensym}
|
||||||
letPragmas* = varPragmas
|
letPragmas* = varPragmas
|
||||||
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
|
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
|
||||||
|
|
@ -476,8 +477,16 @@ proc processPop(c: PContext, n: PNode) =
|
||||||
when defined(debugOptions):
|
when defined(debugOptions):
|
||||||
echo c.config $ n.info, " POP config is now ", c.config.options
|
echo c.config $ n.info, " POP config is now ", c.config.options
|
||||||
|
|
||||||
proc processDefine(c: PContext, n: PNode) =
|
proc processDefineConst(c: PContext, n: PNode, sym: PSym, kind: TMagic) =
|
||||||
if (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent):
|
sym.magic = kind
|
||||||
|
if n.kind in nkPragmaCallKinds and n.len == 2:
|
||||||
|
# could also use TLib
|
||||||
|
n[1] = getStrLitNode(c, n)
|
||||||
|
|
||||||
|
proc processDefine(c: PContext, n: PNode, sym: PSym) =
|
||||||
|
if sym != nil and sym.kind == skConst:
|
||||||
|
processDefineConst(c, n, sym, mGenericDefine)
|
||||||
|
elif (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent):
|
||||||
defineSymbol(c.config.symbols, n[1].ident.s)
|
defineSymbol(c.config.symbols, n[1].ident.s)
|
||||||
else:
|
else:
|
||||||
invalidPragma(c, n)
|
invalidPragma(c, n)
|
||||||
|
|
@ -1066,7 +1075,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
recordPragma(c, it, "error", s)
|
recordPragma(c, it, "error", s)
|
||||||
localError(c.config, it.info, errUser, s)
|
localError(c.config, it.info, errUser, s)
|
||||||
of wFatal: fatal(c.config, it.info, expectStrLit(c, it))
|
of wFatal: fatal(c.config, it.info, expectStrLit(c, it))
|
||||||
of wDefine: processDefine(c, it)
|
of wDefine: processDefine(c, it, sym)
|
||||||
of wUndef: processUndef(c, it)
|
of wUndef: processUndef(c, it)
|
||||||
of wCompile: processCompile(c, it)
|
of wCompile: processCompile(c, it)
|
||||||
of wLink: processLink(c, it)
|
of wLink: processLink(c, it)
|
||||||
|
|
@ -1213,11 +1222,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
noVal(c, it)
|
noVal(c, it)
|
||||||
sym.flags.incl sfBase
|
sym.flags.incl sfBase
|
||||||
of wIntDefine:
|
of wIntDefine:
|
||||||
sym.magic = mIntDefine
|
processDefineConst(c, n, sym, mIntDefine)
|
||||||
of wStrDefine:
|
of wStrDefine:
|
||||||
sym.magic = mStrDefine
|
processDefineConst(c, n, sym, mStrDefine)
|
||||||
of wBoolDefine:
|
of wBoolDefine:
|
||||||
sym.magic = mBoolDefine
|
processDefineConst(c, n, sym, mBoolDefine)
|
||||||
of wUsed:
|
of wUsed:
|
||||||
noVal(c, it)
|
noVal(c, it)
|
||||||
if sym == nil: invalidPragma(c, it)
|
if sym == nil: invalidPragma(c, it)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
import
|
import
|
||||||
strutils, options, ast, trees, nimsets,
|
strutils, options, ast, trees, nimsets,
|
||||||
platform, math, msgs, idents, renderer, types,
|
platform, math, msgs, idents, renderer, types,
|
||||||
commands, magicsys, modulegraphs, strtabs, lineinfos
|
commands, magicsys, modulegraphs, strtabs, lineinfos, wordrecg
|
||||||
|
|
||||||
from system/memory import nimCStrLen
|
from system/memory import nimCStrLen
|
||||||
|
|
||||||
|
|
@ -371,6 +371,11 @@ proc rangeCheck(n: PNode, value: Int128; g: ModuleGraph) =
|
||||||
localError(g.config, n.info, "cannot convert " & $value &
|
localError(g.config, n.info, "cannot convert " & $value &
|
||||||
" to " & typeToString(n.typ))
|
" to " & typeToString(n.typ))
|
||||||
|
|
||||||
|
proc floatRangeCheck(n: PNode, value: BiggestFloat; g: ModuleGraph) =
|
||||||
|
if value < firstFloat(n.typ) or value > lastFloat(n.typ):
|
||||||
|
localError(g.config, n.info, "cannot convert " & $value &
|
||||||
|
" to " & typeToString(n.typ))
|
||||||
|
|
||||||
proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): PNode =
|
proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): PNode =
|
||||||
let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc})
|
let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc})
|
||||||
let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc})
|
let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc})
|
||||||
|
|
@ -490,6 +495,81 @@ proc newSymNodeTypeDesc*(s: PSym; idgen: IdGenerator; info: TLineInfo): PNode =
|
||||||
else:
|
else:
|
||||||
result.typ = s.typ
|
result.typ = s.typ
|
||||||
|
|
||||||
|
proc foldDefine(m, s: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
||||||
|
var name = s.name.s
|
||||||
|
let prag = extractPragma(s)
|
||||||
|
if prag != nil:
|
||||||
|
for it in prag:
|
||||||
|
if it.kind in nkPragmaCallKinds and it.len == 2 and it[0].kind == nkIdent:
|
||||||
|
let word = whichKeyword(it[0].ident)
|
||||||
|
if word in {wStrDefine, wIntDefine, wBoolDefine, wDefine}:
|
||||||
|
# should be processed in pragmas.nim already
|
||||||
|
if it[1].kind in {nkStrLit, nkRStrLit, nkTripleStrLit}:
|
||||||
|
name = it[1].strVal
|
||||||
|
if isDefined(g.config, name):
|
||||||
|
let str = g.config.symbols[name]
|
||||||
|
case s.magic
|
||||||
|
of mIntDefine:
|
||||||
|
try:
|
||||||
|
result = newIntNodeT(toInt128(str.parseInt), n, idgen, g)
|
||||||
|
except ValueError:
|
||||||
|
localError(g.config, s.info,
|
||||||
|
"{.intdefine.} const was set to an invalid integer: '" &
|
||||||
|
str & "'")
|
||||||
|
of mStrDefine:
|
||||||
|
result = newStrNodeT(str, n, g)
|
||||||
|
of mBoolDefine:
|
||||||
|
try:
|
||||||
|
result = newIntNodeT(toInt128(str.parseBool.int), n, idgen, g)
|
||||||
|
except ValueError:
|
||||||
|
localError(g.config, s.info,
|
||||||
|
"{.booldefine.} const was set to an invalid bool: '" &
|
||||||
|
str & "'")
|
||||||
|
of mGenericDefine:
|
||||||
|
let rawTyp = s.typ
|
||||||
|
# pretend we don't support distinct types
|
||||||
|
let typ = rawTyp.skipTypes(abstractVarRange-{tyDistinct})
|
||||||
|
try:
|
||||||
|
template intNode(value): PNode =
|
||||||
|
let val = toInt128(value)
|
||||||
|
rangeCheck(n, val, g)
|
||||||
|
newIntNodeT(val, n, idgen, g)
|
||||||
|
case typ.kind
|
||||||
|
of tyString, tyCstring:
|
||||||
|
result = newStrNodeT(str, n, g)
|
||||||
|
of tyInt..tyInt64:
|
||||||
|
result = intNode(str.parseBiggestInt)
|
||||||
|
of tyUInt..tyUInt64:
|
||||||
|
result = intNode(str.parseBiggestUInt)
|
||||||
|
of tyBool:
|
||||||
|
result = intNode(str.parseBool.int)
|
||||||
|
of tyEnum:
|
||||||
|
# compile time parseEnum
|
||||||
|
let ident = getIdent(g.cache, str)
|
||||||
|
for e in typ.n:
|
||||||
|
if e.kind != nkSym: internalError(g.config, "foldDefine for enum")
|
||||||
|
let es = e.sym
|
||||||
|
let match =
|
||||||
|
if es.ast.isNil:
|
||||||
|
es.name.id == ident.id
|
||||||
|
else:
|
||||||
|
es.ast.strVal == str
|
||||||
|
if match:
|
||||||
|
result = intNode(es.position)
|
||||||
|
break
|
||||||
|
if result.isNil:
|
||||||
|
raise newException(ValueError, "invalid enum value: " & str)
|
||||||
|
else:
|
||||||
|
localError(g.config, s.info, "unsupported type $1 for define '$2'" %
|
||||||
|
[name, typeToString(rawTyp)])
|
||||||
|
except ValueError as e:
|
||||||
|
localError(g.config, s.info,
|
||||||
|
"could not process define '$1' of type $2; $3" %
|
||||||
|
[name, typeToString(rawTyp), e.msg])
|
||||||
|
else: result = copyTree(s.astdef) # unreachable
|
||||||
|
else:
|
||||||
|
result = copyTree(s.astdef)
|
||||||
|
|
||||||
proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
@ -509,31 +589,8 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||||
of mBuildOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.hostOS].name), n, g)
|
of mBuildOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.hostOS].name), n, g)
|
||||||
of mBuildCPU: result = newStrNodeT(platform.CPU[g.config.target.hostCPU].name.toLowerAscii, n, g)
|
of mBuildCPU: result = newStrNodeT(platform.CPU[g.config.target.hostCPU].name.toLowerAscii, n, g)
|
||||||
of mAppType: result = getAppType(n, g)
|
of mAppType: result = getAppType(n, g)
|
||||||
of mIntDefine:
|
of mIntDefine, mStrDefine, mBoolDefine, mGenericDefine:
|
||||||
if isDefined(g.config, s.name.s):
|
result = foldDefine(m, s, n, idgen, g)
|
||||||
try:
|
|
||||||
result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseInt), n, idgen, g)
|
|
||||||
except ValueError:
|
|
||||||
localError(g.config, s.info,
|
|
||||||
"{.intdefine.} const was set to an invalid integer: '" &
|
|
||||||
g.config.symbols[s.name.s] & "'")
|
|
||||||
else:
|
|
||||||
result = copyTree(s.astdef)
|
|
||||||
of mStrDefine:
|
|
||||||
if isDefined(g.config, s.name.s):
|
|
||||||
result = newStrNodeT(g.config.symbols[s.name.s], n, g)
|
|
||||||
else:
|
|
||||||
result = copyTree(s.astdef)
|
|
||||||
of mBoolDefine:
|
|
||||||
if isDefined(g.config, s.name.s):
|
|
||||||
try:
|
|
||||||
result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseBool.int), n, idgen, g)
|
|
||||||
except ValueError:
|
|
||||||
localError(g.config, s.info,
|
|
||||||
"{.booldefine.} const was set to an invalid bool: '" &
|
|
||||||
g.config.symbols[s.name.s] & "'")
|
|
||||||
else:
|
|
||||||
result = copyTree(s.astdef)
|
|
||||||
else:
|
else:
|
||||||
result = copyTree(s.astdef)
|
result = copyTree(s.astdef)
|
||||||
of skProc, skFunc, skMethod:
|
of skProc, skFunc, skMethod:
|
||||||
|
|
|
||||||
|
|
@ -8049,6 +8049,24 @@ used. To see if a value was provided, `defined(FooBar)` can be used.
|
||||||
The syntax `-d:flag`:option: is actually just a shortcut for
|
The syntax `-d:flag`:option: is actually just a shortcut for
|
||||||
`-d:flag=true`:option:.
|
`-d:flag=true`:option:.
|
||||||
|
|
||||||
|
These pragmas also accept an optional string argument for qualified
|
||||||
|
define names.
|
||||||
|
|
||||||
|
```nim
|
||||||
|
const FooBar {.intdefine: "package.FooBar".}: int = 5
|
||||||
|
echo FooBar
|
||||||
|
```
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
nim c -d:package.FooBar=42 foobar.nim
|
||||||
|
```
|
||||||
|
|
||||||
|
This helps disambiguate define names in different packages.
|
||||||
|
|
||||||
|
See also the [generic `define` pragma](manual_experimental.html#generic-define-pragma)
|
||||||
|
for a version of these pragmas that detects the type of the define based on
|
||||||
|
the constant value.
|
||||||
|
|
||||||
User-defined pragmas
|
User-defined pragmas
|
||||||
====================
|
====================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,29 @@ However, a `void` type cannot be inferred in generic code:
|
||||||
The `void` type is only valid for parameters and return types; other symbols
|
The `void` type is only valid for parameters and return types; other symbols
|
||||||
cannot have the type `void`.
|
cannot have the type `void`.
|
||||||
|
|
||||||
|
Generic `define` pragma
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Aside the [typed define pragmas for constants](manual.html#implementation-specific-pragmas-compileminustime-define-pragmas),
|
||||||
|
there is a generic `{.define.}` pragma that interprets the value of the define
|
||||||
|
based on the type of the constant value.
|
||||||
|
|
||||||
|
```nim
|
||||||
|
const foo {.define: "package.foo".} = 123
|
||||||
|
const bar {.define: "package.bar".} = false
|
||||||
|
```
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
nim c -d:package.foo=456 -d:package.bar foobar.nim
|
||||||
|
```
|
||||||
|
|
||||||
|
The following types are supported:
|
||||||
|
|
||||||
|
* `string` and `cstring`
|
||||||
|
* Signed and unsigned integer types
|
||||||
|
* `bool`
|
||||||
|
* Enums
|
||||||
|
|
||||||
Top-down type inference
|
Top-down type inference
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,23 @@
|
||||||
discard """
|
discard """
|
||||||
joinable: false
|
joinable: false
|
||||||
cmd: "nim c -d:booldef -d:booldef2=false -d:intdef=2 -d:strdef=foobar -d:namespaced.define=false -d:double.namespaced.define -r $file"
|
cmd: "nim c $options -d:booldef -d:booldef2=false -d:intdef=2 -d:strdef=foobar -d:namespaced.define=false -d:double.namespaced.define -r $file"
|
||||||
|
matrix: "; -d:useGenericDefine"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
const booldef {.booldefine.} = false
|
when defined(useGenericDefine):
|
||||||
const booldef2 {.booldefine.} = true
|
{.pragma: booldefine2, define.}
|
||||||
const intdef {.intdefine.} = 0
|
{.pragma: intdefine2, define.}
|
||||||
const strdef {.strdefine.} = ""
|
{.pragma: strdefine2, define.}
|
||||||
|
else:
|
||||||
|
|
||||||
|
{.pragma: booldefine2, booldefine.}
|
||||||
|
{.pragma: intdefine2, intdefine.}
|
||||||
|
{.pragma: strdefine2, strdefine.}
|
||||||
|
|
||||||
|
const booldef {.booldefine2.} = false
|
||||||
|
const booldef2 {.booldefine2.} = true
|
||||||
|
const intdef {.intdefine2.} = 0
|
||||||
|
const strdef {.strdefine2.} = ""
|
||||||
|
|
||||||
doAssert defined(booldef)
|
doAssert defined(booldef)
|
||||||
doAssert defined(booldef2)
|
doAssert defined(booldef2)
|
||||||
|
|
@ -17,10 +28,21 @@ doAssert not booldef2
|
||||||
doAssert intdef == 2
|
doAssert intdef == 2
|
||||||
doAssert strdef == "foobar"
|
doAssert strdef == "foobar"
|
||||||
|
|
||||||
|
when defined(useGenericDefine):
|
||||||
|
block:
|
||||||
|
const uintdef {.define: "intdef".}: uint = 17
|
||||||
|
doAssert intdef == int(uintdef)
|
||||||
|
const cstrdef {.define: "strdef".}: cstring = "not strdef"
|
||||||
|
doAssert $cstrdef == strdef
|
||||||
|
type FooBar = enum foo, bar, foobar
|
||||||
|
const enumdef {.define: "strdef".} = foo
|
||||||
|
doAssert $enumdef == strdef
|
||||||
|
doAssert enumdef == foobar
|
||||||
|
|
||||||
# Intentionally not defined from command line
|
# Intentionally not defined from command line
|
||||||
const booldef3 {.booldefine.} = true
|
const booldef3 {.booldefine2.} = true
|
||||||
const intdef2 {.intdefine.} = 1
|
const intdef2 {.intdefine2.} = 1
|
||||||
const strdef2 {.strdefine.} = "abc"
|
const strdef2 {.strdefine2.} = "abc"
|
||||||
type T = object
|
type T = object
|
||||||
when booldef3:
|
when booldef3:
|
||||||
field1: int
|
field1: int
|
||||||
|
|
@ -35,11 +57,21 @@ doAssert not defined(strdef2)
|
||||||
discard T(field1: 1, field2: 2, field3: 3)
|
discard T(field1: 1, field2: 2, field3: 3)
|
||||||
|
|
||||||
doAssert defined(namespaced.define)
|
doAssert defined(namespaced.define)
|
||||||
const `namespaced.define` {.booldefine.} = true
|
const `namespaced.define` {.booldefine2.} = true
|
||||||
doAssert not `namespaced.define`
|
doAssert not `namespaced.define`
|
||||||
|
when defined(useGenericDefine):
|
||||||
|
const aliasToNamespacedDefine {.define: "namespaced.define".} = not `namespaced.define`
|
||||||
|
else:
|
||||||
|
const aliasToNamespacedDefine {.booldefine: "namespaced.define".} = not `namespaced.define`
|
||||||
|
doAssert aliasToNamespacedDefine == `namespaced.define`
|
||||||
|
|
||||||
doAssert defined(double.namespaced.define)
|
doAssert defined(double.namespaced.define)
|
||||||
const `double.namespaced.define` {.booldefine.} = false
|
const `double.namespaced.define` {.booldefine2.} = false
|
||||||
doAssert `double.namespaced.define`
|
doAssert `double.namespaced.define`
|
||||||
|
when defined(useGenericDefine):
|
||||||
|
const aliasToDoubleNamespacedDefine {.define: "double.namespaced.define".} = not `double.namespaced.define`
|
||||||
|
else:
|
||||||
|
const aliasToDoubleNamespacedDefine {.booldefine: "double.namespaced.define".} = not `double.namespaced.define`
|
||||||
|
doAssert aliasToDoubleNamespacedDefine == `double.namespaced.define`
|
||||||
|
|
||||||
doAssert not defined(namespaced.butnotdefined)
|
doAssert not defined(namespaced.butnotdefined)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue