distinguish between 'defined' and 'declared'

This commit is contained in:
Araq 2014-08-11 20:38:28 +02:00
commit dd806cafa0
36 changed files with 155 additions and 96 deletions

View file

@ -315,6 +315,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
of "undef", "u": of "undef", "u":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
undefSymbol(arg) undefSymbol(arg)
of "symbol":
expectArg(switch, arg, pass, info)
declareSymbol(arg)
of "compile": of "compile":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: processCompile(arg) if pass in {passCmd2, passPP}: processCompile(arg)

View file

@ -19,6 +19,9 @@ var gSymbols: PStringTable
proc defineSymbol*(symbol: string) = proc defineSymbol*(symbol: string) =
gSymbols[symbol] = "true" gSymbols[symbol] = "true"
proc declareSymbol*(symbol: string) =
gSymbols[symbol] = "unknown"
proc undefSymbol*(symbol: string) = proc undefSymbol*(symbol: string) =
gSymbols[symbol] = "false" gSymbols[symbol] = "false"
@ -27,6 +30,7 @@ proc isDefined*(symbol: string): bool =
result = gSymbols[symbol] == "true" result = gSymbols[symbol] == "true"
proc isDefined*(symbol: PIdent): bool = isDefined(symbol.s) proc isDefined*(symbol: PIdent): bool = isDefined(symbol.s)
proc isDeclared*(symbol: PIdent): bool = gSymbols.hasKey(symbol.s)
iterator definedSymbolNames*: string = iterator definedSymbolNames*: string =
for key, val in pairs(gSymbols): for key, val in pairs(gSymbols):
@ -37,6 +41,36 @@ proc countDefinedSymbols*(): int =
for key, val in pairs(gSymbols): for key, val in pairs(gSymbols):
if val == "true": inc(result) if val == "true": inc(result)
# For ease of bootstrapping, we keep there here and not in the global config
# file for now:
const
additionalSymbols = """
x86 itanium x8664
msdos mswindows win32 unix posix sunos bsd macintosh RISCOS doslike hpux
mac
hppa hp9000 hp9000s300 hp9000s700 hp9000s800 hp9000s820 ELATE sparcv9
ecmascript js nimrodvm nimffi nimdoc cpp objc
gcc llvmgcc clang lcc bcc dmc wcc vcc tcc pcc ucc icl
boehmgc gcmarkandsweep gcgenerational nogc gcUseBitvectors
endb profiler
executable guiapp consoleapp library dll staticlib
quick nimbabel
release debug
useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler
nodejs kwin
usesysassert usegcassert tinyC useFFI
useStdoutAsStdmsg createNimRtl
booting fulldebug corruption nimsuperops noSignalHandler useGnuReadline
noCaas noDocGen noBusyWaiting nativeStackTrace useNodeIds selftest
reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize
debugExecProcesses pcreDll useLipzipSrc
preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime
""".split
proc initDefines*() = proc initDefines*() =
gSymbols = newStringTable(modeStyleInsensitive) gSymbols = newStringTable(modeStyleInsensitive)
defineSymbol("nimrod") # 'nimrod' is always defined defineSymbol("nimrod") # 'nimrod' is always defined
@ -53,6 +87,17 @@ proc initDefines*() =
defineSymbol("nimparsebiggestfloatmagic") defineSymbol("nimparsebiggestfloatmagic")
# add platform specific symbols: # add platform specific symbols:
for c in low(CPU)..high(CPU):
declareSymbol("cpu" & $CPU[c].bit)
declareSymbol(normalize(EndianToStr[CPU[c].endian]))
declareSymbol(CPU[c].name)
for o in low(platform.OS)..high(platform.OS):
declareSymbol(platform.OS[o].name)
for a in additionalSymbols:
declareSymbol(a)
# -----------------------------------------------------------
case targetCPU case targetCPU
of cpuI386: defineSymbol("x86") of cpuI386: defineSymbol("x86")
of cpuIa64: defineSymbol("itanium") of cpuIa64: defineSymbol("itanium")
@ -88,5 +133,6 @@ proc initDefines*() =
defineSymbol(normalize(EndianToStr[CPU[targetCPU].endian])) defineSymbol(normalize(EndianToStr[CPU[targetCPU].endian]))
defineSymbol(CPU[targetCPU].name) defineSymbol(CPU[targetCPU].name)
defineSymbol(platform.OS[targetOS].name) defineSymbol(platform.OS[targetOS].name)
declareSymbol("emulatedthreadvars")
if platform.OS[targetOS].props.contains(ospLacksThreadVars): if platform.OS[targetOS].props.contains(ospLacksThreadVars):
defineSymbol("emulatedthreadvars") defineSymbol("emulatedthreadvars")

View file

@ -77,7 +77,7 @@ proc llStreamClose(s: PLLStream) =
of llsFile: of llsFile:
close(s.f) close(s.f)
when not defined(readLineFromStdin): when not declared(readLineFromStdin):
# fallback implementation: # fallback implementation:
proc readLineFromStdin(prompt: string, line: var string): bool = proc readLineFromStdin(prompt: string, line: var string): bool =
stdout.write(prompt) stdout.write(prompt)

View file

@ -79,7 +79,7 @@ proc handleCmdLine() =
var ex = quoteShell(binPath) var ex = quoteShell(binPath)
execExternalProgram(ex & ' ' & service.arguments) execExternalProgram(ex & ' ' & service.arguments)
when defined(GC_setMaxPause): when declared(GC_setMaxPause):
GC_setMaxPause 2_000 GC_setMaxPause 2_000
when compileOption("gc", "v2") or compileOption("gc", "refc"): when compileOption("gc", "v2") or compileOption("gc", "refc"):

View file

@ -1393,10 +1393,16 @@ proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
checkSonsLen(n, 2) checkSonsLen(n, 2)
# we replace this node by a 'true' or 'false' node: # we replace this node by a 'true' or 'false' node:
result = newIntNode(nkIntLit, 0) result = newIntNode(nkIntLit, 0)
if lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: if not onlyCurrentScope and considerQuotedIdent(n[0]).s == "defined":
result.intVal = 1 if n.sons[1].kind != nkIdent:
elif not onlyCurrentScope and (n.sons[1].kind == nkIdent) and localError(n.info, "obsolete usage of 'defined', use 'declared' instead")
condsyms.isDefined(n.sons[1].ident): elif condsyms.isDefined(n.sons[1].ident):
result.intVal = 1
elif not condsyms.isDeclared(n.sons[1].ident):
message(n.info, warnUser,
"undeclared conditional symbol; use --symbol to declare it: " &
n[1].ident.s)
elif lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil:
result.intVal = 1 result.intVal = 1
result.info = n.info result.info = n.info
result.typ = getSysType(tyBool) result.typ = getSysType(tyBool)

View file

@ -1,5 +1,5 @@
template tests*(body: stmt) {.immediate.} = template tests*(body: stmt) {.immediate.} =
when defined(selftest): when defined(selftest):
when not defined(unittest): import unittest when not declared(unittest): import unittest
body body

View file

@ -87,9 +87,7 @@ proc bailOut(c: PCtx; tos: PStackFrame) =
when not defined(nimComputedGoto): when not defined(nimComputedGoto):
{.pragma: computedGoto.} {.pragma: computedGoto.}
proc myreset(n: var TFullReg) = proc myreset(n: var TFullReg) = reset(n)
when defined(system.reset):
reset(n)
template ensureKind(k: expr) {.immediate, dirty.} = template ensureKind(k: expr) {.immediate, dirty.} =
if regs[ra].kind != k: if regs[ra].kind != k:

View file

@ -13,6 +13,7 @@ Options:
-p, --path:PATH add path to search paths -p, --path:PATH add path to search paths
-d, --define:SYMBOL define a conditional symbol -d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol -u, --undef:SYMBOL undefine a conditional symbol
--symbol:SYMBOL declare a conditional symbol
-f, --forceBuild force rebuilding of all modules -f, --forceBuild force rebuilding of all modules
--stackTrace:on|off turn stack tracing on|off --stackTrace:on|off turn stack tracing on|off
--lineTrace:on|off turn line tracing on|off --lineTrace:on|off turn line tracing on|off

View file

@ -102,7 +102,7 @@ proc newAny(value: pointer, rawType: PNimType): TAny =
result.value = value result.value = value
result.rawType = rawType result.rawType = rawType
when defined(system.TVarSlot): when declared(system.TVarSlot):
proc toAny*(x: TVarSlot): TAny {.inline.} = proc toAny*(x: TVarSlot): TAny {.inline.} =
## constructs a ``TAny`` object from a variable slot ``x``. ## constructs a ``TAny`` object from a variable slot ``x``.
## This captures `x`'s address, so `x` can be modified with its ## This captures `x`'s address, so `x` can be modified with its

View file

@ -243,7 +243,7 @@ template `=~` *(s: string, pattern: TRegex): expr =
## echo("syntax error") ## echo("syntax error")
## ##
bind maxSubPatterns bind maxSubPatterns
when not definedInScope(matches): when not declaredInScope(matches):
var matches {.inject.}: array[0..MaxSubpatterns-1, string] var matches {.inject.}: array[0..MaxSubpatterns-1, string]
match(s, pattern, matches) match(s, pattern, matches)

View file

@ -219,7 +219,7 @@ when not defined(JS):
proc randomize(seed: int) = proc randomize(seed: int) =
srand(cint(seed)) srand(cint(seed))
when defined(srand48): srand48(seed) when declared(srand48): srand48(seed)
proc random(max: int): int = proc random(max: int): int =
result = int(rand()) mod max result = int(rand()) mod max

View file

@ -26,7 +26,7 @@ const
withThreads = compileOption("threads") withThreads = compileOption("threads")
tickCountCorrection = 50_000 tickCountCorrection = 50_000
when not defined(system.TStackTrace): when not declared(system.TStackTrace):
type TStackTrace = array [0..20, cstring] type TStackTrace = array [0..20, cstring]
# We use a simple hash table of bounded size to keep track of the stack traces: # We use a simple hash table of bounded size to keep track of the stack traces:
@ -146,7 +146,7 @@ proc `//`(a, b: int): string =
result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2)) result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2))
proc writeProfile() {.noconv.} = proc writeProfile() {.noconv.} =
when defined(system.TStackTrace): when declared(system.TStackTrace):
system.profilerHook = nil system.profilerHook = nil
const filename = "profile_results.txt" const filename = "profile_results.txt"
echo "writing " & filename & "..." echo "writing " & filename & "..."
@ -189,16 +189,16 @@ var
disabled: int disabled: int
proc disableProfiling*() = proc disableProfiling*() =
when defined(system.TStackTrace): when declared(system.TStackTrace):
atomicDec disabled atomicDec disabled
system.profilerHook = nil system.profilerHook = nil
proc enableProfiling*() = proc enableProfiling*() =
when defined(system.TStackTrace): when declared(system.TStackTrace):
if atomicInc(disabled) >= 0: if atomicInc(disabled) >= 0:
system.profilerHook = hook system.profilerHook = hook
when defined(system.TStackTrace): when declared(system.TStackTrace):
system.profilerHook = hook system.profilerHook = hook
addQuitProc(writeProfile) addQuitProc(writeProfile)

View file

@ -997,7 +997,7 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
if c_rename(source, dest) != 0'i32: if c_rename(source, dest) != 0'i32:
raise newException(EOS, $strerror(errno)) raise newException(EOS, $strerror(errno))
when not defined(ENOENT) and not defined(Windows): when not declared(ENOENT) and not defined(Windows):
when NoFakeVars: when NoFakeVars:
const ENOENT = cint(2) # 2 on most systems including Solaris const ENOENT = cint(2) # 2 on most systems including Solaris
else: else:
@ -1615,11 +1615,11 @@ when defined(nimdoc):
## ##
## **Availability**: On Posix there is no portable way to get the command ## **Availability**: On Posix there is no portable way to get the command
## line from a DLL and thus the proc isn't defined in this environment. You ## line from a DLL and thus the proc isn't defined in this environment. You
## can test for its availability with `defined() <system.html#defined>`_. ## can test for its availability with `declared() <system.html#declared>`_.
## Example: ## Example:
## ##
## .. code-block:: nimrod ## .. code-block:: nimrod
## when defined(paramCount): ## when declared(paramCount):
## # Use paramCount() here ## # Use paramCount() here
## else: ## else:
## # Do something else! ## # Do something else!
@ -1638,11 +1638,11 @@ when defined(nimdoc):
## ##
## **Availability**: On Posix there is no portable way to get the command ## **Availability**: On Posix there is no portable way to get the command
## line from a DLL and thus the proc isn't defined in this environment. You ## line from a DLL and thus the proc isn't defined in this environment. You
## can test for its availability with `defined() <system.html#defined>`_. ## can test for its availability with `declared() <system.html#declared>`_.
## Example: ## Example:
## ##
## .. code-block:: nimrod ## .. code-block:: nimrod
## when defined(paramStr): ## when declared(paramStr):
## # Use paramStr() here ## # Use paramStr() here
## else: ## else:
## # Do something else! ## # Do something else!
@ -1682,7 +1682,7 @@ elif not defined(createNimRtl):
# Docstring in nimdoc block. # Docstring in nimdoc block.
result = cmdCount-1 result = cmdCount-1
when defined(paramCount) or defined(nimdoc): when declared(paramCount) or defined(nimdoc):
proc commandLineParams*(): seq[TaintedString] = proc commandLineParams*(): seq[TaintedString] =
## Convenience proc which returns the command line parameters. ## Convenience proc which returns the command line parameters.
## ##
@ -1691,11 +1691,11 @@ when defined(paramCount) or defined(nimdoc):
## ##
## **Availability**: On Posix there is no portable way to get the command ## **Availability**: On Posix there is no portable way to get the command
## line from a DLL and thus the proc isn't defined in this environment. You ## line from a DLL and thus the proc isn't defined in this environment. You
## can test for its availability with `defined() <system.html#defined>`_. ## can test for its availability with `declared() <system.html#declared>`_.
## Example: ## Example:
## ##
## .. code-block:: nimrod ## .. code-block:: nimrod
## when defined(commandLineParams): ## when declared(commandLineParams):
## # Use commandLineParams() here ## # Use commandLineParams() here
## else: ## else:
## # Do something else! ## # Do something else!
@ -1714,7 +1714,7 @@ when defined(linux) or defined(solaris) or defined(bsd) or defined(aix):
when not (defined(windows) or defined(macosx)): when not (defined(windows) or defined(macosx)):
proc getApplHeuristic(): string = proc getApplHeuristic(): string =
when defined(paramStr): when declared(paramStr):
result = string(paramStr(0)) result = string(paramStr(0))
# POSIX guaranties that this contains the executable # POSIX guaranties that this contains the executable
# as it has been executed by the calling process # as it has been executed by the calling process

View file

@ -643,7 +643,7 @@ elif not defined(useNimRtl):
data.workingDir = workingDir data.workingDir = workingDir
when defined(posix_spawn) and not defined(useFork) and when declared(posix_spawn) and not defined(useFork) and
not defined(useClone) and not defined(linux): not defined(useClone) and not defined(linux):
pid = startProcessAuxSpawn(data) pid = startProcessAuxSpawn(data)
else: else:

View file

@ -37,7 +37,7 @@ type
## or the argument, ``value`` is not "" if ## or the argument, ``value`` is not "" if
## the option was given a value ## the option was given a value
when defined(os.paramCount): when declared(os.paramCount):
# we cannot provide this for NimRtl creation on Posix, because we can't # we cannot provide this for NimRtl creation on Posix, because we can't
# access the command line arguments then! # access the command line arguments then!
@ -127,7 +127,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {.
## retrieves the rest of the command line that has not been parsed yet. ## retrieves the rest of the command line that has not been parsed yet.
result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString
when defined(initOptParser): when declared(initOptParser):
iterator getopt*(): tuple[kind: TCmdLineKind, key, val: TaintedString] = iterator getopt*(): tuple[kind: TCmdLineKind, key, val: TaintedString] =
## This is an convenience iterator for iterating over the command line. ## This is an convenience iterator for iterating over the command line.

View file

@ -119,7 +119,7 @@ proc cmdLineRest*(p: TOptParser): TaintedString {.rtl, extern: "npo$1", deprecat
type type
TGetoptResult* = tuple[kind: TCmdLineKind, key, val: TaintedString] TGetoptResult* = tuple[kind: TCmdLineKind, key, val: TaintedString]
when defined(paramCount): when declared(paramCount):
iterator getopt*(): TGetoptResult = iterator getopt*(): TGetoptResult =
## This is an convenience iterator for iterating over the command line. ## This is an convenience iterator for iterating over the command line.
## This uses the TOptParser object. Example: ## This uses the TOptParser object. Example:

View file

@ -870,7 +870,7 @@ template `=~`*(s: string, pattern: TPeg): bool =
## echo("syntax error") ## echo("syntax error")
## ##
bind maxSubpatterns bind maxSubpatterns
when not definedInScope(matches): when not declaredInScope(matches):
var matches {.inject.}: array[0..MaxSubpatterns-1, string] var matches {.inject.}: array[0..MaxSubpatterns-1, string]
match(s, pattern, matches) match(s, pattern, matches)

View file

@ -19,7 +19,7 @@
import import
macros macros
when defined(stdout): when declared(stdout):
import os import os
when not defined(ECMAScript): when not defined(ECMAScript):
@ -99,7 +99,7 @@ template fail* =
when not defined(ECMAScript): when not defined(ECMAScript):
if AbortOnError: quit(1) if AbortOnError: quit(1)
when defined(TestStatusIMPL): when declared(TestStatusIMPL):
TestStatusIMPL = FAILED TestStatusIMPL = FAILED
else: else:
program_result += 1 program_result += 1
@ -188,7 +188,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
result = getAst(expectBody(errorTypes, exp.lineinfo, body)) result = getAst(expectBody(errorTypes, exp.lineinfo, body))
when defined(stdout): when declared(stdout):
## Reading settings ## Reading settings
var envOutLvl = os.getEnv("NIMTEST_OUTPUT_LVL").string var envOutLvl = os.getEnv("NIMTEST_OUTPUT_LVL").string

View file

@ -98,16 +98,8 @@ type
proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.} proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
## Special compile-time procedure that checks whether `x` is ## Special compile-time procedure that checks whether `x` is
## defined. `x` has to be an identifier or a qualified identifier. ## defined.
## This can be used to check whether a library provides a certain ## `x` is an external symbol introduced through the compiler's
## feature or not:
##
## .. code-block:: Nimrod
## when not defined(strutils.toUpper):
## # provide our own toUpper proc here, because strutils is
## # missing it.
##
## You can also check external symbols introduced through the compiler's
## `-d:x switch <nimrodc.html#compile-time-symbols>`_ to enable build time ## `-d:x switch <nimrodc.html#compile-time-symbols>`_ to enable build time
## conditionals: ## conditionals:
## ##
@ -116,13 +108,28 @@ proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
## # Do here programmer friendly expensive sanity checks. ## # Do here programmer friendly expensive sanity checks.
## # Put here the normal code ## # Put here the normal code
proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
## Special compile-time procedure that checks whether `x` is
## declared. `x` has to be an identifier or a qualified identifier.
## This can be used to check whether a library provides a certain
## feature or not:
##
## .. code-block:: Nimrod
## when not defined(strutils.toUpper):
## # provide our own toUpper proc here, because strutils is
## # missing it.
when defined(useNimRtl): when defined(useNimRtl):
{.deadCodeElim: on.} {.deadCodeElim: on.}
proc definedInScope*(x: expr): bool {. proc definedInScope*(x: expr): bool {.
magic: "DefinedInScope", noSideEffect.} magic: "DefinedInScope", noSideEffect, deprecated.}
## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
proc declaredInScope*(x: expr): bool {.
magic: "DefinedInScope", noSideEffect, deprecated.}
## Special compile-time procedure that checks whether `x` is ## Special compile-time procedure that checks whether `x` is
## defined in the current scope. `x` has to be an identifier. ## declared in the current scope. `x` has to be an identifier.
proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.} proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
## Boolean not; returns true iff ``x == false``. ## Boolean not; returns true iff ``x == false``.
@ -2118,7 +2125,7 @@ template newException*(exceptn: typedesc, message: string): expr =
when hostOS == "standalone": when hostOS == "standalone":
include panicoverride include panicoverride
when not defined(sysFatal): when not declared(sysFatal):
template sysFatal(exceptn: typedesc, message: string) = template sysFatal(exceptn: typedesc, message: string) =
when hostOS == "standalone": when hostOS == "standalone":
panic(message) panic(message)
@ -2170,7 +2177,7 @@ when not defined(JS): #and not defined(NimrodVM):
# WARNING: This is very fragile! An array size of 8 does not work on my # WARNING: This is very fragile! An array size of 8 does not work on my
# Linux 64bit system. -- That's because the stack direction is the other # Linux 64bit system. -- That's because the stack direction is the other
# way round. # way round.
when defined(setStackBottom): when declared(setStackBottom):
var locals {.volatile.}: pointer var locals {.volatile.}: pointer
locals = addr(locals) locals = addr(locals)
setStackBottom(locals) setStackBottom(locals)
@ -2443,7 +2450,7 @@ when not defined(JS): #and not defined(NimrodVM):
hasRaiseAction: bool hasRaiseAction: bool
raiseAction: proc (e: ref E_Base): bool {.closure.} raiseAction: proc (e: ref E_Base): bool {.closure.}
when defined(initAllocator): when declared(initAllocator):
initAllocator() initAllocator()
when hasThreadSupport: when hasThreadSupport:
include "system/syslocks" include "system/syslocks"
@ -3016,7 +3023,7 @@ proc compiles*(x): bool {.magic: "Compiles", noSideEffect.} =
## echo "'+' for integers is available" ## echo "'+' for integers is available"
discard discard
when defined(initDebugger): when declared(initDebugger):
initDebugger() initDebugger()
when hostOS != "standalone": when hostOS != "standalone":

View file

@ -39,7 +39,7 @@ var
c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar
# constants faked as variables: # constants faked as variables:
when not defined(SIGINT): when not declared(SIGINT):
when NoFakeVars: when NoFakeVars:
when defined(windows): when defined(windows):
const const
@ -132,7 +132,7 @@ proc c_realloc(p: pointer, newsize: int): pointer {.
importc: "realloc", header: "<stdlib.h>".} importc: "realloc", header: "<stdlib.h>".}
when hostOS != "standalone": when hostOS != "standalone":
when not defined(errno): when not declared(errno):
when defined(NimrodVM): when defined(NimrodVM):
var vmErrnoWrapper {.importc.}: ptr cint var vmErrnoWrapper {.importc.}: ptr cint
template errno: expr = template errno: expr =

View file

@ -241,26 +241,26 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
""" """
# Platform independent versions of the above (slower!) # Platform independent versions of the above (slower!)
when not defined(addInt): when not declared(addInt):
proc addInt(a, b: int): int {.compilerProc, inline.} = proc addInt(a, b: int): int {.compilerProc, inline.} =
result = a +% b result = a +% b
if (result xor a) >= 0 or (result xor b) >= 0: if (result xor a) >= 0 or (result xor b) >= 0:
return result return result
raiseOverflow() raiseOverflow()
when not defined(subInt): when not declared(subInt):
proc subInt(a, b: int): int {.compilerProc, inline.} = proc subInt(a, b: int): int {.compilerProc, inline.} =
result = a -% b result = a -% b
if (result xor a) >= 0 or (result xor not b) >= 0: if (result xor a) >= 0 or (result xor not b) >= 0:
return result return result
raiseOverflow() raiseOverflow()
when not defined(negInt): when not declared(negInt):
proc negInt(a: int): int {.compilerProc, inline.} = proc negInt(a: int): int {.compilerProc, inline.} =
if a != low(int): return -a if a != low(int): return -a
raiseOverflow() raiseOverflow()
when not defined(divInt): when not declared(divInt):
proc divInt(a, b: int): int {.compilerProc, inline.} = proc divInt(a, b: int): int {.compilerProc, inline.} =
if b == 0: if b == 0:
raiseDivByZero() raiseDivByZero()
@ -268,13 +268,13 @@ when not defined(divInt):
raiseOverflow() raiseOverflow()
return a div b return a div b
when not defined(modInt): when not declared(modInt):
proc modInt(a, b: int): int {.compilerProc, inline.} = proc modInt(a, b: int): int {.compilerProc, inline.} =
if b == 0: if b == 0:
raiseDivByZero() raiseDivByZero()
return a mod b return a mod b
when not defined(mulInt): when not declared(mulInt):
# #
# This code has been inspired by Python's source code. # This code has been inspired by Python's source code.
# The native int product x*y is either exactly right or *way* off, being # The native int product x*y is either exactly right or *way* off, being

View file

@ -174,7 +174,7 @@ proc atomicInc*(memLoc: var int, x: int = 1): int =
proc atomicDec*(memLoc: var int, x: int = 1): int = proc atomicDec*(memLoc: var int, x: int = 1): int =
when defined(gcc) and hasThreadSupport: when defined(gcc) and hasThreadSupport:
when defined(atomic_sub_fetch): when declared(atomic_sub_fetch):
result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED) result = atomic_sub_fetch(memLoc.addr, x, ATOMIC_RELAXED)
else: else:
result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED) result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED)
@ -201,14 +201,14 @@ when (defined(x86) or defined(amd64)) and (defined(gcc) or defined(llvm_gcc)):
{.emit: """asm volatile("pause" ::: "memory");""".} {.emit: """asm volatile("pause" ::: "memory");""".}
elif (defined(x86) or defined(amd64)) and defined(vcc): elif (defined(x86) or defined(amd64)) and defined(vcc):
proc cpuRelax {.importc: "YieldProcessor", header: "<windows.h>".} proc cpuRelax {.importc: "YieldProcessor", header: "<windows.h>".}
elif defined(intelc): elif defined(icl):
proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".} proc cpuRelax {.importc: "_mm_pause", header: "xmmintrin.h".}
elif false: elif false:
from os import sleep from os import sleep
proc cpuRelax {.inline.} = os.sleep(1) proc cpuRelax {.inline.} = os.sleep(1)
when not defined(fence) and hasThreadSupport: when not declared(fence) and hasThreadSupport:
# XXX fixme # XXX fixme
proc fence*() {.inline.} = proc fence*() {.inline.} =
var dummy: bool var dummy: bool

View file

@ -14,7 +14,7 @@
## **Note:** The current implementation of message passing is slow and does ## **Note:** The current implementation of message passing is slow and does
## not work with cyclic data structures. ## not work with cyclic data structures.
when not defined(NimString): when not declared(NimString):
{.error: "You must not import this module explicitly".} {.error: "You must not import this module explicitly".}
type type

View file

@ -93,7 +93,7 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
if s2 == nil: if s2 == nil:
unsureAsgnRef(cast[PPointer](dest), s2) unsureAsgnRef(cast[PPointer](dest), s2)
return return
when defined(usrToCell): when declared(usrToCell):
# unfortunately we only have cycle detection for our native GCs. # unfortunately we only have cycle detection for our native GCs.
let x = usrToCell(s2) let x = usrToCell(s2)
let forw = cast[int](x.typ) let forw = cast[int](x.typ)

View file

@ -307,7 +307,7 @@ when not defined(noSignalHandler):
action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n") action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
else: else:
block platformSpecificSignal: block platformSpecificSignal:
when defined(SIGPIPE): when declared(SIGPIPE):
if s == SIGPIPE: if s == SIGPIPE:
action("SIGPIPE: Pipe closed.\n") action("SIGPIPE: Pipe closed.\n")
break platformSpecificSignal break platformSpecificSignal
@ -336,7 +336,7 @@ when not defined(noSignalHandler):
c_signal(SIGFPE, signalHandler) c_signal(SIGFPE, signalHandler)
c_signal(SIGILL, signalHandler) c_signal(SIGILL, signalHandler)
c_signal(SIGBUS, signalHandler) c_signal(SIGBUS, signalHandler)
when defined(SIGPIPE): when declared(SIGPIPE):
c_signal(SIGPIPE, signalHandler) c_signal(SIGPIPE, signalHandler)
registerSignalHandler() # call it in initialization section registerSignalHandler() # call it in initialization section

View file

@ -30,7 +30,7 @@ const
# cycles instead of the complex # cycles instead of the complex
# algorithm # algorithm
when withRealTime and not defined(getTicks): when withRealTime and not declared(getTicks):
include "system/timers" include "system/timers"
when defined(memProfiler): when defined(memProfiler):
proc nimProfile(requestedSize: int) proc nimProfile(requestedSize: int)
@ -413,7 +413,7 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
{.push stackTrace: off, profiler:off.} {.push stackTrace: off, profiler:off.}
proc gcInvariant*() = proc gcInvariant*() =
sysAssert(allocInv(gch.region), "injected") sysAssert(allocInv(gch.region), "injected")
when defined(markForDebug): when declared(markForDebug):
markForDebug(gch) markForDebug(gch)
{.pop.} {.pop.}

View file

@ -26,7 +26,7 @@ const
# this seems to be a good value # this seems to be a good value
withRealTime = defined(useRealtimeGC) withRealTime = defined(useRealtimeGC)
when withRealTime and not defined(getTicks): when withRealTime and not declared(getTicks):
include "system/timers" include "system/timers"
when defined(memProfiler): when defined(memProfiler):
proc nimProfile(requestedSize: int) proc nimProfile(requestedSize: int)

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
when defined(NimString): when declared(NimString):
# we are in system module: # we are in system module:
{.pragma: codegenType, compilerproc.} {.pragma: codegenType, compilerproc.}
else: else:

View file

@ -121,7 +121,7 @@ proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
type type
TReprClosure {.final.} = object # we cannot use a global variable here TReprClosure {.final.} = object # we cannot use a global variable here
# as this wouldn't be thread-safe # as this wouldn't be thread-safe
when defined(TCellSet): when declared(TCellSet):
marked: TCellSet marked: TCellSet
recdepth: int # do not recurse endlessly recdepth: int # do not recurse endlessly
indent: int # indentation indent: int # indentation
@ -130,16 +130,16 @@ when not defined(useNimRtl):
proc initReprClosure(cl: var TReprClosure) = proc initReprClosure(cl: var TReprClosure) =
# Important: cellsets does not lock the heap when doing allocations! We # Important: cellsets does not lock the heap when doing allocations! We
# have to do it here ... # have to do it here ...
when hasThreadSupport and hasSharedHeap and defined(heapLock): when hasThreadSupport and hasSharedHeap and declared(heapLock):
AcquireSys(HeapLock) AcquireSys(HeapLock)
when defined(TCellSet): when declared(TCellSet):
init(cl.marked) init(cl.marked)
cl.recdepth = -1 # default is to display everything! cl.recdepth = -1 # default is to display everything!
cl.indent = 0 cl.indent = 0
proc deinitReprClosure(cl: var TReprClosure) = proc deinitReprClosure(cl: var TReprClosure) =
when defined(TCellSet): deinit(cl.marked) when declared(TCellSet): deinit(cl.marked)
when hasThreadSupport and hasSharedHeap and defined(heapLock): when hasThreadSupport and hasSharedHeap and declared(heapLock):
ReleaseSys(HeapLock) ReleaseSys(HeapLock)
proc reprBreak(result: var string, cl: TReprClosure) = proc reprBreak(result: var string, cl: TReprClosure) =
@ -201,7 +201,7 @@ when not defined(useNimRtl):
proc reprRef(result: var string, p: pointer, typ: PNimType, proc reprRef(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) = cl: var TReprClosure) =
# we know that p is not nil here: # we know that p is not nil here:
when defined(TCellSet): when declared(TCellSet):
when defined(boehmGC) or defined(nogc): when defined(boehmGC) or defined(nogc):
var cell = cast[PCell](p) var cell = cast[PCell](p)
else: else:

View file

@ -9,7 +9,7 @@
## Implements Nimrod's 'spawn'. ## Implements Nimrod's 'spawn'.
when not defined(NimString): when not declared(NimString):
{.error: "You must not import this module explicitly".} {.error: "You must not import this module explicitly".}
{.push stackTrace:off.} {.push stackTrace:off.}

View file

@ -32,7 +32,7 @@ proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
return a.len == b.len and return a.len == b.len and
c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32 c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32
when defined(allocAtomic): when declared(allocAtomic):
template allocStr(size: expr): expr = template allocStr(size: expr): expr =
cast[NimString](allocAtomic(size)) cast[NimString](allocAtomic(size))
else: else:
@ -85,7 +85,7 @@ proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
if src != nil: if src != nil:
var s = src.space var s = src.space
if s < 8: s = 7 if s < 8: s = 7
when defined(newObjRC1): when declared(newObjRC1):
result = cast[NimString](newObjRC1(addr(strDesc), sizeof(TGenericSeq) + result = cast[NimString](newObjRC1(addr(strDesc), sizeof(TGenericSeq) +
s+1)) s+1))
else: else:

View file

@ -39,7 +39,7 @@
## createThread(thr[i], threadFunc, (i*10, i*10+5)) ## createThread(thr[i], threadFunc, (i*10, i*10+5))
## joinThreads(thr) ## joinThreads(thr)
when not defined(NimString): when not declared(NimString):
{.error: "You must not import this module explicitly".} {.error: "You must not import this module explicitly".}
const const
@ -267,7 +267,7 @@ when not defined(boehmgc) and not hasSharedHeap:
proc deallocOsPages() proc deallocOsPages()
template threadProcWrapperBody(closure: expr) {.immediate.} = template threadProcWrapperBody(closure: expr) {.immediate.} =
when defined(globalsSlot): ThreadVarSetValue(globalsSlot, closure) when declared(globalsSlot): ThreadVarSetValue(globalsSlot, closure)
var t = cast[ptr TThread[TArg]](closure) var t = cast[ptr TThread[TArg]](closure)
when useStackMaskHack: when useStackMaskHack:
var tls: TThreadLocalStorage var tls: TThreadLocalStorage
@ -275,13 +275,13 @@ template threadProcWrapperBody(closure: expr) {.immediate.} =
# init the GC for this thread: # init the GC for this thread:
setStackBottom(addr(t)) setStackBottom(addr(t))
initGC() initGC()
when defined(registerThread): when declared(registerThread):
t.stackBottom = addr(t) t.stackBottom = addr(t)
registerThread(t) registerThread(t)
when TArg is void: t.dataFn() when TArg is void: t.dataFn()
else: t.dataFn(t.data) else: t.dataFn(t.data)
when defined(registerThread): unregisterThread(t) when declared(registerThread): unregisterThread(t)
when defined(deallocOsPages): deallocOsPages() when declared(deallocOsPages): deallocOsPages()
# Since an unhandled exception terminates the whole process (!), there is # Since an unhandled exception terminates the whole process (!), there is
# no need for a ``try finally`` here, nor would it be correct: The current # no need for a ``try finally`` here, nor would it be correct: The current
# exception is tried to be re-raised by the code-gen after the ``finally``! # exception is tried to be re-raised by the code-gen after the ``finally``!
@ -332,7 +332,7 @@ when false:
discard TerminateThread(t.sys, 1'i32) discard TerminateThread(t.sys, 1'i32)
else: else:
discard pthread_cancel(t.sys) discard pthread_cancel(t.sys)
when defined(registerThread): unregisterThread(addr(t)) when declared(registerThread): unregisterThread(addr(t))
t.dataFn = nil t.dataFn = nil
proc createThread*[TArg](t: var TThread[TArg], proc createThread*[TArg](t: var TThread[TArg],

View file

@ -10,7 +10,7 @@
# Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system # Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system
# module! Do not import it directly! # module! Do not import it directly!
when not defined(NimString): when not declared(NimString):
{.error: "You must not import this module explicitly".} {.error: "You must not import this module explicitly".}
type type
@ -103,7 +103,7 @@ proc newWideCString*(source: cstring, L: int): WideCString =
proc newWideCString*(s: cstring): WideCString = proc newWideCString*(s: cstring): WideCString =
if s.isNil: return nil if s.isNil: return nil
when not defined(c_strlen): when not declared(c_strlen):
proc c_strlen(a: cstring): int {. proc c_strlen(a: cstring): int {.
header: "<string.h>", noSideEffect, importc: "strlen".} header: "<string.h>", noSideEffect, importc: "strlen".}

View file

@ -333,11 +333,5 @@ proc VERSION*(X: var sdl.Tversion) =
X.patch = PATCHLEVEL X.patch = PATCHLEVEL
when not (defined(Workaround_RenderText_Solid)): proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{.
proc RenderText_Solid*(font: PFont, text: cstring, fg: TColor): PSurface{. cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.}
cdecl, importc: "TTF_RenderText_Solid", dynlib: ttfLibName.}
else:
proc RenderText_Solid(font: PFont, text: cstring, fg: TColor): PSurface =
var Black: TColor # initialized to zero
result = RenderText_Shaded(font, text, fg, Black)

View file

@ -8,7 +8,7 @@ version 0.9.6
Concurrency Concurrency
----------- -----------
- 'gcsafe' inferrence needs to be fixed - 'gcsafe' inference needs to be fixed
- 'deepCopy' needs to be instantiated for - 'deepCopy' needs to be instantiated for
generics *when the type is constructed* generics *when the type is constructed*
- test 'deepCopy' - test 'deepCopy'

View file

@ -23,6 +23,9 @@ News
- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma - The ``destructor`` pragma has been deprecated. Use the ``override`` pragma
instead. The destructor's name has to be ``destroy`` now. instead. The destructor's name has to be ``destroy`` now.
- ``lambda`` is not a keyword anymore. - ``lambda`` is not a keyword anymore.
- **system.defined has been split into system.defined and system.declared**.
You have to use ``--symbol`` to declare new conditional symbols that can be
set via ``--define``.
Language Additions Language Additions
------------------ ------------------
@ -39,6 +42,7 @@ News
- Added ``algorithm.reversed`` - Added ``algorithm.reversed``
- Added ``uri.combine`` and ``uri.parseUri``. - Added ``uri.combine`` and ``uri.parseUri``.
2014-04-21 Version 0.9.4 released 2014-04-21 Version 0.9.4 released
================================= =================================