Implement {.booldefine.} (#10533)
This commit is contained in:
parent
07553034de
commit
0091f2ad3b
9 changed files with 71 additions and 17 deletions
|
|
@ -655,7 +655,7 @@ type
|
||||||
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
|
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
|
||||||
mNHint, mNWarning, mNError,
|
mNHint, mNWarning, mNError,
|
||||||
mInstantiationInfo, mGetTypeInfo,
|
mInstantiationInfo, mGetTypeInfo,
|
||||||
mNimvm, mIntDefine, mStrDefine, mRunnableExamples,
|
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
|
||||||
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
|
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
|
||||||
mSymIsInstantiationOf
|
mSymIsInstantiationOf
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,26 +15,21 @@ import
|
||||||
from options import Feature
|
from options import Feature
|
||||||
from lineinfos import HintsToStr, WarningsToStr
|
from lineinfos import HintsToStr, WarningsToStr
|
||||||
|
|
||||||
const
|
|
||||||
catNone = "false"
|
|
||||||
|
|
||||||
proc defineSymbol*(symbols: StringTableRef; symbol: string, value: string = "true") =
|
proc defineSymbol*(symbols: StringTableRef; symbol: string, value: string = "true") =
|
||||||
symbols[symbol] = value
|
symbols[symbol] = value
|
||||||
|
|
||||||
proc undefSymbol*(symbols: StringTableRef; symbol: string) =
|
proc undefSymbol*(symbols: StringTableRef; symbol: string) =
|
||||||
symbols[symbol] = catNone
|
symbols.del(symbol)
|
||||||
|
|
||||||
#proc lookupSymbol*(symbols: StringTableRef; symbol: string): string =
|
#proc lookupSymbol*(symbols: StringTableRef; symbol: string): string =
|
||||||
# result = if isDefined(symbol): gSymbols[symbol] else: nil
|
# result = if isDefined(symbol): gSymbols[symbol] else: nil
|
||||||
|
|
||||||
iterator definedSymbolNames*(symbols: StringTableRef): string =
|
iterator definedSymbolNames*(symbols: StringTableRef): string =
|
||||||
for key, val in pairs(symbols):
|
for key, val in pairs(symbols):
|
||||||
if val != catNone: yield key
|
yield key
|
||||||
|
|
||||||
proc countDefinedSymbols*(symbols: StringTableRef): int =
|
proc countDefinedSymbols*(symbols: StringTableRef): int =
|
||||||
result = 0
|
symbols.len
|
||||||
for key, val in pairs(symbols):
|
|
||||||
if val != catNone: inc(result)
|
|
||||||
|
|
||||||
proc initDefines*(symbols: StringTableRef) =
|
proc initDefines*(symbols: StringTableRef) =
|
||||||
# for bootstrapping purposes and old code:
|
# for bootstrapping purposes and old code:
|
||||||
|
|
|
||||||
|
|
@ -360,7 +360,7 @@ proc cppDefine*(c: ConfigRef; define: string) =
|
||||||
|
|
||||||
proc isDefined*(conf: ConfigRef; symbol: string): bool =
|
proc isDefined*(conf: ConfigRef; symbol: string): bool =
|
||||||
if conf.symbols.hasKey(symbol):
|
if conf.symbols.hasKey(symbol):
|
||||||
result = conf.symbols[symbol] != "false"
|
result = true
|
||||||
elif cmpIgnoreStyle(symbol, CPU[conf.target.targetCPU].name) == 0:
|
elif cmpIgnoreStyle(symbol, CPU[conf.target.targetCPU].name) == 0:
|
||||||
result = true
|
result = true
|
||||||
elif cmpIgnoreStyle(symbol, platform.OS[conf.target.targetOS].name) == 0:
|
elif cmpIgnoreStyle(symbol, platform.OS[conf.target.targetOS].name) == 0:
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ const
|
||||||
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims, wUsed}
|
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims, wUsed}
|
||||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
||||||
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims,
|
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims,
|
||||||
wIntDefine, wStrDefine, wUsed, wCompilerProc, wCore}
|
wIntDefine, wStrDefine, wBoolDefine, wUsed, wCompilerProc, wCore}
|
||||||
letPragmas* = varPragmas
|
letPragmas* = varPragmas
|
||||||
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
|
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
|
||||||
wThread, wRaises, wLocks, wTags, wGcSafe}
|
wThread, wRaises, wLocks, wTags, wGcSafe}
|
||||||
|
|
@ -1106,6 +1106,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
sym.magic = mIntDefine
|
sym.magic = mIntDefine
|
||||||
of wStrDefine:
|
of wStrDefine:
|
||||||
sym.magic = mStrDefine
|
sym.magic = mStrDefine
|
||||||
|
of wBoolDefine:
|
||||||
|
sym.magic = mBoolDefine
|
||||||
of wUsed:
|
of wUsed:
|
||||||
noVal(c, it)
|
noVal(c, it)
|
||||||
if sym == nil: invalidPragma(c, it)
|
if sym == nil: invalidPragma(c, it)
|
||||||
|
|
|
||||||
|
|
@ -569,10 +569,20 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
try:
|
try:
|
||||||
result = newIntNodeT(g.config.symbols[s.name.s].parseInt, n, g)
|
result = newIntNodeT(g.config.symbols[s.name.s].parseInt, n, g)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
localError(g.config, n.info, "expression is not an integer literal")
|
localError(g.config, s.info,
|
||||||
|
"{.intdefine.} const was set to an invalid integer: '" &
|
||||||
|
g.config.symbols[s.name.s] & "'")
|
||||||
of mStrDefine:
|
of mStrDefine:
|
||||||
if isDefined(g.config, s.name.s):
|
if isDefined(g.config, s.name.s):
|
||||||
result = newStrNodeT(g.config.symbols[s.name.s], n, g)
|
result = newStrNodeT(g.config.symbols[s.name.s], n, g)
|
||||||
|
of mBoolDefine:
|
||||||
|
if isDefined(g.config, s.name.s):
|
||||||
|
try:
|
||||||
|
result = newIntNodeT(g.config.symbols[s.name.s].parseBool.int, n, g)
|
||||||
|
except ValueError:
|
||||||
|
localError(g.config, s.info,
|
||||||
|
"{.booldefine.} const was set to an invalid bool: '" &
|
||||||
|
g.config.symbols[s.name.s] & "'")
|
||||||
else:
|
else:
|
||||||
result = copyTree(s.ast)
|
result = copyTree(s.ast)
|
||||||
of skProc, skFunc, skMethod:
|
of skProc, skFunc, skMethod:
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ type
|
||||||
wColon, wColonColon, wEquals, wDot, wDotDot,
|
wColon, wColonColon, wEquals, wDot, wDotDot,
|
||||||
wStar, wMinus,
|
wStar, wMinus,
|
||||||
wMagic, wThread, wFinal, wProfiler, wMemTracker, wObjChecks,
|
wMagic, wThread, wFinal, wProfiler, wMemTracker, wObjChecks,
|
||||||
wIntDefine, wStrDefine,
|
wIntDefine, wStrDefine, wBoolDefine
|
||||||
|
|
||||||
wDestroy,
|
wDestroy,
|
||||||
|
|
||||||
|
|
@ -122,7 +122,8 @@ const
|
||||||
|
|
||||||
":", "::", "=", ".", "..",
|
":", "::", "=", ".", "..",
|
||||||
"*", "-",
|
"*", "-",
|
||||||
"magic", "thread", "final", "profiler", "memtracker", "objchecks", "intdefine", "strdefine",
|
"magic", "thread", "final", "profiler", "memtracker", "objchecks",
|
||||||
|
"intdefine", "strdefine", "booldefine",
|
||||||
|
|
||||||
"destroy",
|
"destroy",
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7851,6 +7851,7 @@ pragma description
|
||||||
================= ============================================
|
================= ============================================
|
||||||
`intdefine`:idx: Reads in a build-time define as an integer
|
`intdefine`:idx: Reads in a build-time define as an integer
|
||||||
`strdefine`:idx: Reads in a build-time define as a string
|
`strdefine`:idx: Reads in a build-time define as a string
|
||||||
|
`booldefine`:idx: Reads in a build-time define as a bool
|
||||||
================= ============================================
|
================= ============================================
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
@ -7858,13 +7859,14 @@ pragma description
|
||||||
echo FooBar
|
echo FooBar
|
||||||
|
|
||||||
::
|
::
|
||||||
nim c -d:FooBar=42 foobar.c
|
nim c -d:FooBar=42 foobar.nim
|
||||||
|
|
||||||
In the above example, providing the -d flag causes the symbol
|
In the above example, providing the -d flag causes the symbol
|
||||||
``FooBar`` to be overwritten at compile time, printing out 42. If the
|
``FooBar`` to be overwritten at compile time, printing out 42. If the
|
||||||
``-d:FooBar=42`` were to be omitted, the default value of 5 would be
|
``-d:FooBar=42`` were to be omitted, the default value of 5 would be
|
||||||
used.
|
used. To see if a value was provided, `defined(FooBar)` can be used.
|
||||||
|
|
||||||
|
The syntax `-d:flag` is actually just a shortcut for `-d:flag=true`.
|
||||||
|
|
||||||
Custom annotations
|
Custom annotations
|
||||||
------------------
|
------------------
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ runnableExamples:
|
||||||
|
|
||||||
|
|
||||||
## When using the style insensitive mode ``modeStyleInsensitive``,
|
## When using the style insensitive mode ``modeStyleInsensitive``,
|
||||||
## all letters are compared case insensitively within the ASCII range
|
## all letters are compared case insensitively within the ASCII range
|
||||||
## and underscores are ignored.
|
## and underscores are ignored.
|
||||||
|
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
|
|
@ -272,6 +272,32 @@ proc `%`*(f: string, t: StringTableRef, flags: set[FormatFlag] = {}): string {.
|
||||||
add(result, f[i])
|
add(result, f[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
|
proc del*(t: StringTableRef, key: string) =
|
||||||
|
## Removes `key` from `t`.
|
||||||
|
# Impl adapted from `tableimpl.delImplIdx`
|
||||||
|
var i = rawGet(t, key)
|
||||||
|
let msk = high(t.data)
|
||||||
|
if i >= 0:
|
||||||
|
dec(t.counter)
|
||||||
|
block outer:
|
||||||
|
while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1
|
||||||
|
var j = i # The correctness of this depends on (h+1) in nextTry,
|
||||||
|
var r = j # though may be adaptable to other simple sequences.
|
||||||
|
t.data[i].hasValue = false # mark current EMPTY
|
||||||
|
t.data[i].key = ""
|
||||||
|
t.data[i].val = ""
|
||||||
|
while true:
|
||||||
|
i = (i + 1) and msk # increment mod table size
|
||||||
|
if not t.data[i].hasValue: # end of collision cluster; So all done
|
||||||
|
break outer
|
||||||
|
r = t.myhash(t.data[i].key) and msk # "home" location of key@i
|
||||||
|
if not ((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)):
|
||||||
|
break
|
||||||
|
when defined(js):
|
||||||
|
t.data[j] = t.data[i]
|
||||||
|
else:
|
||||||
|
shallowCopy(t.data[j], t.data[i]) # data[j] will be marked EMPTY next loop
|
||||||
|
|
||||||
proc `$`*(t: StringTableRef): string {.rtlFunc, extern: "nstDollar".} =
|
proc `$`*(t: StringTableRef): string {.rtlFunc, extern: "nstDollar".} =
|
||||||
## The `$` operator for string tables.
|
## The `$` operator for string tables.
|
||||||
if t.len == 0:
|
if t.len == 0:
|
||||||
|
|
|
||||||
18
tests/misc/tdefine.nim
Normal file
18
tests/misc/tdefine.nim
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
discard """
|
||||||
|
joinable: false
|
||||||
|
cmd: "nim c -d:booldef -d:booldef2=false -d:intdef=2 -d:strdef=foobar -r $file"
|
||||||
|
"""
|
||||||
|
|
||||||
|
const booldef {.booldefine.} = false
|
||||||
|
const booldef2 {.booldefine.} = true
|
||||||
|
const intdef {.intdefine.} = 0
|
||||||
|
const strdef {.strdefine.} = ""
|
||||||
|
|
||||||
|
doAssert defined(booldef)
|
||||||
|
doAssert defined(booldef2)
|
||||||
|
doAssert defined(intdef)
|
||||||
|
doAssert defined(strdef)
|
||||||
|
doAssert booldef
|
||||||
|
doAssert not booldef2
|
||||||
|
doAssert intdef == 2
|
||||||
|
doAssert strdef == "foobar"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue