Implement {.booldefine.} (#10533)

This commit is contained in:
Oscar Nihlgård 2019-02-03 09:06:00 +01:00 • committed by Andreas Rumpf
commit 0091f2ad3b
9 changed files with 71 additions and 17 deletions

View file

@ -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

View file

@ -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:

View file

@ -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:

View file

@ -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)

View file

@ -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:

View file

@ -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",

View file

@ -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
------------------ ------------------

View file

@ -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
View 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"