From 38040e76910639ef99d1685e2670140e408249da Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Wed, 11 May 2016 20:00:28 +0200 Subject: fixes #4040 --- compiler/semfold.nim | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'compiler/semfold.nim') diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 5fe4e3299..c5a8cc2a2 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -419,7 +419,14 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = result = newStrNodeT(substr(getStr(a), int(getOrdValue(b)), int(getOrdValue(c))), n) of mFloatToStr: result = newStrNodeT($getFloat(a), n) - of mCStrToStr, mCharToStr: result = newStrNodeT(getStrOrChar(a), n) + of mCStrToStr, mCharToStr: + if a.kind == nkBracket: + var s = "" + for b in a.sons: + s.add b.getStrOrChar + result = newStrNodeT(s, n) + else: + result = newStrNodeT(getStrOrChar(a), n) of mStrToStr: result = a of mEnumToStr: result = newStrNodeT(ordinalValToString(a), n) of mArrToSeq: -- cgit 1.4.1-2-gfad0 From 0cc7c9a13ceb1afe703d328222dace69cf84a81b Mon Sep 17 00:00:00 2001 From: "A. S. Budden" Date: Tue, 31 May 2016 13:17:40 +0100 Subject: Modification to implementation of round() such that it returns a float and accepts a places argument (fixes #3473). This also involved moving some functions around to get the hierarchy correct and the documentation for frexp was modified such that it was clear that it can return a float in either the range [-1, -0.5] or [0.5, 1]. --- compiler/semfold.nim | 2 +- lib/pure/math.nim | 92 +++++++++++++++++++++++++++++----------- tests/overload/tstmtoverload.nim | 2 +- web/news.txt | 5 +++ 4 files changed, 74 insertions(+), 27 deletions(-) (limited to 'compiler/semfold.nim') diff --git a/compiler/semfold.nim b/compiler/semfold.nim index c5a8cc2a2..feea6ce34 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -489,7 +489,7 @@ proc leValueConv(a, b: PNode): bool = of nkCharLit..nkUInt64Lit: case b.kind of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal - of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal) + of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal).int else: internalError(a.info, "leValueConv") of nkFloatLit..nkFloat128Lit: case b.kind diff --git a/lib/pure/math.nim b/lib/pure/math.nim index ce418d72c..bd6764433 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -138,19 +138,10 @@ when not defined(JS): proc exp*(x: float64): float64 {.importc: "exp", header: "".} ## Computes the exponential function of `x` (pow(E, x)) - proc frexp*(x: float32, exponent: var int): float32 {. - importc: "frexp", header: "".} - proc frexp*(x: float64, exponent: var int): float64 {. - importc: "frexp", header: "".} - ## Split a number into mantissa and exponent. - ## `frexp` calculates the mantissa m (a float greater than or equal to 0.5 - ## and less than 1) and the integer value n such that `x` (the original - ## float value) equals m * 2**n. frexp stores n in `exponent` and returns - ## m. - - proc round*(x: float32): int {.importc: "lrintf", header: "".} - proc round*(x: float64): int {.importc: "lrint", header: "".} - ## converts a float to an int by rounding. + proc round0(x: float32): float32 {.importc: "roundf", header: "".} + proc round0(x: float64): float64 {.importc: "round", header: "".} + ## Converts a float to an int by rounding. Used internally by the round + ## function when the specified number of places is 0. proc arccos*(x: float32): float32 {.importc: "acosf", header: "".} proc arccos*(x: float64): float64 {.importc: "acos", header: "".} @@ -256,22 +247,11 @@ else: proc exp*(x: float32): float32 {.importc: "Math.exp", nodecl.} proc exp*(x: float64): float64 {.importc: "Math.exp", nodecl.} - proc round*(x: float): int {.importc: "Math.round", nodecl.} + proc round0*(x: float): float {.importc: "Math.round", nodecl.} proc pow*(x, y: float32): float32 {.importC: "Math.pow", nodecl.} proc pow*(x, y: float64): float64 {.importc: "Math.pow", nodecl.} - proc frexp*[T: float32|float64](x: T, exponent: var int): T = - if x == 0.0: - exponent = 0 - result = 0.0 - elif x < 0.0: - result = -frexp(-x, exponent) - else: - var ex = floor(log2(x)) - exponent = round(ex) - result = x / pow(2.0, ex) - proc arccos*(x: float32): float32 {.importc: "Math.acos", nodecl.} proc arccos*(x: float64): float64 {.importc: "Math.acos", nodecl.} proc arcsin*(x: float32): float32 {.importc: "Math.asin", nodecl.} @@ -295,6 +275,43 @@ else: var y = exp(2.0*x) return (y-1.0)/(y+1.0) +proc round*[T: float32|float64](x: T, places: int = 0): T = + ## Round a floating point number. + ## + ## If `places` is 0 (or omitted), round to the nearest integral value + ## following normal mathematical rounding rules (e.g. `round(54.5) -> 55.0`). + ## If `places` is greater than 0, round to the given number of decimal + ## places, e.g. `round(54.346, 2) -> 54.35`. + ## If `places` is negative, round to the left of the decimal place, e.g. + ## `round(537.345, -1) -> 540.0` + if places == 0: + result = round0(x) + else: + var mult = pow(10.0, places.T) + result = round0(x*mult)/mult + +when not defined(JS): + proc frexp*(x: float32, exponent: var int): float32 {. + importc: "frexp", header: "".} + proc frexp*(x: float64, exponent: var int): float64 {. + importc: "frexp", header: "".} + ## Split a number into mantissa and exponent. + ## `frexp` calculates the mantissa m (a float greater than or equal to 0.5 + ## and less than 1) and the integer value n such that `x` (the original + ## float value) equals m * 2**n. frexp stores n in `exponent` and returns + ## m. +else: + proc frexp*[T: float32|float64](x: T, exponent: var int): T = + if x == 0.0: + exponent = 0 + result = 0.0 + elif x < 0.0: + result = -frexp(-x, exponent) + else: + var ex = floor(log2(x)) + exponent = round(ex) + result = x / pow(2.0, ex) + {.pop.} proc degToRad*[T: float32|float64](d: T): T {.inline.} = @@ -357,3 +374,28 @@ when isMainModule and not defined(JS): assert(lgamma(1.0) == 0.0) # ln(1.0) == 0.0 assert(erf(6.0) > erf(5.0)) assert(erfc(6.0) < erfc(5.0)) +when isMainModule: + # Function for approximate comparison of floats + proc floatIsEqual(x, y: float): bool = (abs(x-y) < 1e-9) + + block: # round() tests + # Round to 0 decimal places + doAssert floatIsEqual(round(54.652), 55.0) + doAssert floatIsEqual(round(54.352), 54.0) + doAssert floatIsEqual(round(-54.652), -55.0) + doAssert floatIsEqual(round(-54.352), -54.0) + doAssert floatIsEqual(round(0.0), 0.0) + # Round to positive decimal places + doAssert floatIsEqual(round(-547.652, 1), -547.7) + doAssert floatIsEqual(round(547.652, 1), 547.7) + doAssert floatIsEqual(round(-547.652, 2), -547.65) + doAssert floatIsEqual(round(547.652, 2), 547.65) + # Round to negative decimal places + doAssert floatIsEqual(round(547.652, -1), 550.0) + doAssert floatIsEqual(round(547.652, -2), 500.0) + doAssert floatIsEqual(round(547.652, -3), 1000.0) + doAssert floatIsEqual(round(547.652, -4), 0.0) + doAssert floatIsEqual(round(-547.652, -1), -550.0) + doAssert floatIsEqual(round(-547.652, -2), -500.0) + doAssert floatIsEqual(round(-547.652, -3), -1000.0) + doAssert floatIsEqual(round(-547.652, -4), 0.0) diff --git a/tests/overload/tstmtoverload.nim b/tests/overload/tstmtoverload.nim index f1944b637..75584bcab 100644 --- a/tests/overload/tstmtoverload.nim +++ b/tests/overload/tstmtoverload.nim @@ -10,7 +10,7 @@ template test(loopCount: int, extraI: int, testBody: stmt): stmt = template test(loopCount: int, extraF: float, testBody: stmt): stmt = block: - test(loopCount, round(extraF), testBody) + test(loopCount, round(extraF).int, testBody) template test(loopCount: int, testBody: stmt): stmt = block: diff --git a/web/news.txt b/web/news.txt index c100c8aee..3dd6c4e1e 100644 --- a/web/news.txt +++ b/web/news.txt @@ -45,6 +45,11 @@ Changes affecting backwards compatibility - The path handling changed. The project directory is not added to the search path automatically anymore. Add this line to your project's config to get back the old behaviour: ``--path:"$projectdir"``. +- The ``round`` function in ``math.nim`` now returns a float and has been + corrected such that the C implementation always rounds up from .5 rather + than changing the operation for even and odd numbers. +- The ``round`` function now accepts a ``places`` argument to round to a + given number of places (e.g. round 4.35 to 4.4 if ``places`` is 1). Library Additions -- cgit 1.4.1-2-gfad0 From 94d1aa5109ebe022e6e51c7cd84033e2457b184f Mon Sep 17 00:00:00 2001 From: Jeff Ciesielski Date: Mon, 4 Jul 2016 18:11:25 -0400 Subject: Add the ability to pass a value with the -d flag This allows the end user to use the {.magic: "IntDefine"/"StrDefine"} pragmas to pass values into code at compile time. This has a nice side effect of also allowing/requiring a default value to be assigned in the code (see osalloc.nim/StandaloneHeapSize for an example) --- compiler/ast.nim | 2 +- compiler/commands.nim | 13 ++++++++++++- compiler/condsyms.nim | 9 +++++++-- compiler/semfold.nim | 6 ++++++ compiler/wordrecg.nim | 3 ++- doc/basicopt.txt | 3 ++- lib/system/osalloc.nim | 3 ++- 7 files changed, 32 insertions(+), 7 deletions(-) (limited to 'compiler/semfold.nim') diff --git a/compiler/ast.nim b/compiler/ast.nim index c3bb7cd62..34ffd6f58 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -610,7 +610,7 @@ type mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNHint, mNWarning, mNError, mInstantiationInfo, mGetTypeInfo, mNGenSym, - mNimvm + mNimvm, mIntDefine, mStrDefine # things that we can evaluate safely at compile time, even if not asked for it: const diff --git a/compiler/commands.nim b/compiler/commands.nim index b3edb5e14..640e07b1b 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -122,6 +122,13 @@ proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass, elif switch[i] in {':', '=', '['}: arg = substr(switch, i + 1) else: invalidCmdLineOption(pass, switch, info) +proc hasKeyValuePair(arg: string): bool = + for i in 0..arg.high: + if arg[i] in {':', '='}: + return true + + return false + proc processOnOffSwitch(op: TOptions, arg: string, pass: TCmdLinePass, info: TLineInfo) = case whichKeyword(arg) @@ -342,7 +349,11 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = discard "allow for backwards compatibility, but don't do anything" of "define", "d": expectArg(switch, arg, pass, info) - defineSymbol(arg) + if hasKeyValuePair(arg): + splitSwitch(arg, key, val, pass, info) + defineSymbol(key, val) + else: + defineSymbol(arg) of "undef", "u": expectArg(switch, arg, pass, info) undefSymbol(arg) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 60e8f2826..02f7e764d 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -19,8 +19,8 @@ var gSymbols: StringTableRef const catNone = "false" -proc defineSymbol*(symbol: string) = - gSymbols[symbol] = "true" +proc defineSymbol*(symbol: string, value: string = "true") = + gSymbols[symbol] = value proc undefSymbol*(symbol: string) = gSymbols[symbol] = catNone @@ -62,6 +62,11 @@ proc isDefined*(symbol: string): bool = proc isDefined*(symbol: PIdent): bool = isDefined(symbol.s) +proc lookupSymbol*(symbol: string): string = + result = if isDefined(symbol): gSymbols[symbol] else: nil + +proc lookupSymbol*(symbol: PIdent): string = lookupSymbol(symbol.s) + iterator definedSymbolNames*: string = for key, val in pairs(gSymbols): if val != catNone: yield key diff --git a/compiler/semfold.nim b/compiler/semfold.nim index feea6ce34..26d309cfd 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -640,6 +640,12 @@ proc getConstExpr(m: PSym, n: PNode): PNode = of mNaN: result = newFloatNodeT(NaN, n) of mInf: result = newFloatNodeT(Inf, n) of mNegInf: result = newFloatNodeT(NegInf, n) + of mIntDefine: + if isDefined(s.name): + result = newIntNodeT(lookupSymbol(s.name).parseInt, n) + of mStrDefine: + if isDefined(s.name): + result = newStrNodeT(lookupSymbol(s.name), n) else: if sfFakeConst notin s.flags: result = copyTree(s.ast) of {skProc, skMethod}: diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 3e0e05a94..b5ffd51c2 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -36,6 +36,7 @@ type wColon, wColonColon, wEquals, wDot, wDotDot, wStar, wMinus, wMagic, wThread, wFinal, wProfiler, wObjChecks, + wIntDefine, wStrDefine, wDestroy, @@ -121,7 +122,7 @@ const ":", "::", "=", ".", "..", "*", "-", - "magic", "thread", "final", "profiler", "objchecks", + "magic", "thread", "final", "profiler", "objchecks", "intdefine", "strdefine", "destroy", diff --git a/doc/basicopt.txt b/doc/basicopt.txt index 6a905bd53..c68d731e6 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -11,7 +11,8 @@ Arguments: arguments are passed to the program being run (if --run option is selected) Options: -p, --path:PATH add path to search paths - -d, --define:SYMBOL define a conditional symbol + -d, --define:SYMBOL(:VAL) define a conditional symbol + (Optionally: Define the value for that symbol) -u, --undef:SYMBOL undefine a conditional symbol -f, --forceBuild force rebuilding of all modules --stackTrace:on|off turn stack tracing on|off diff --git a/lib/system/osalloc.nim b/lib/system/osalloc.nim index de26f52d9..cfa9ae18f 100644 --- a/lib/system/osalloc.nim +++ b/lib/system/osalloc.nim @@ -150,8 +150,9 @@ elif defined(windows): #VirtualFree(p, size, MEM_DECOMMIT) elif hostOS == "standalone": + const StandaloneHeapSize {.magic: "IntDefine"}: int = 1024 * PageSize var - theHeap: array[1024*PageSize, float64] # 'float64' for alignment + theHeap: array[StandaloneHeapSize, float64] # 'float64' for alignment bumpPointer = cast[int](addr theHeap) proc osAllocPages(size: int): pointer {.inline.} = -- cgit 1.4.1-2-gfad0 From ab3c684c62c3a10d08ce8941d2296c55b1386c18 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 15 Jul 2016 01:55:42 +0200 Subject: fixes #3545 --- compiler/semfold.nim | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'compiler/semfold.nim') diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 26d309cfd..8e57ed0e2 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -286,13 +286,14 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = of mNot: result = newIntNodeT(1 - getInt(a), n) of mCard: result = newIntNodeT(nimsets.cardSet(a), n) of mBitnotI: result = newIntNodeT(not getInt(a), n) - of mLengthStr, mXLenStr: - if a.kind == nkNilLit: result = newIntNodeT(0, n) - else: result = newIntNodeT(len(getStr(a)), n) of mLengthArray: result = newIntNodeT(lengthOrd(a.typ), n) - of mLengthSeq, mLengthOpenArray, mXLenSeq: - if a.kind == nkNilLit: result = newIntNodeT(0, n) - else: result = newIntNodeT(sonsLen(a), n) # BUGFIX + of mLengthSeq, mLengthOpenArray, mXLenSeq, mLengthStr, mXLenStr: + if a.kind == nkNilLit: + result = newIntNodeT(0, n) + elif a.kind in {nkStrLit..nkTripleStrLit}: + result = newIntNodeT(len a.strVal, n) + else: + result = newIntNodeT(sonsLen(a), n) # BUGFIX of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away of mToFloat, mToBiggestFloat: result = newFloatNodeT(toFloat(int(getInt(a))), n) -- cgit 1.4.1-2-gfad0 From 9605435f2eea1e0be62170238023894d1eed29af Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 19 Jul 2016 19:28:01 +0200 Subject: get rid of deprecated toLower/toUpper --- compiler/ccgtypes.nim | 5 +++-- compiler/ccgutils.nim | 2 +- compiler/nimfix/pretty.nim | 8 ++++---- compiler/options.nim | 6 +++--- compiler/sem.nim | 2 +- compiler/semfold.nim | 4 ++-- compiler/semstmts.nim | 2 +- compiler/semtypes.nim | 2 +- 8 files changed, 16 insertions(+), 15 deletions(-) (limited to 'compiler/semfold.nim') diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 34a16c859..3d1c2affc 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -25,8 +25,9 @@ proc isKeyword(w: PIdent): bool = proc mangleField(name: PIdent): string = result = mangle(name.s) if isKeyword(name): - result[0] = result[0].toUpper # Mangling makes everything lowercase, - # but some identifiers are C keywords + result[0] = result[0].toUpperAscii + # Mangling makes everything lowercase, + # but some identifiers are C keywords proc hashOwner(s: PSym): FilenameHash = var m = s diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 27b432c2c..ecd98a2bf 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -188,7 +188,7 @@ proc mangle*(name: string): string = let c = name[i] case c of 'A'..'Z': - add(result, c.toLower) + add(result, c.toLowerAscii) of '_': discard of 'a'..'z', '0'..'9': diff --git a/compiler/nimfix/pretty.nim b/compiler/nimfix/pretty.nim index 1123afb9e..8ba922927 100644 --- a/compiler/nimfix/pretty.nim +++ b/compiler/nimfix/pretty.nim @@ -66,7 +66,7 @@ proc beautifyName(s: string, k: TSymKind): string = ]: result.add s[i] else: - result.add toUpper(s[i]) + result.add toUpperAscii(s[i]) of skConst, skEnumField: # for 'const' we keep how it's spelt; either upper case or lower case: result.add s[0] @@ -74,7 +74,7 @@ proc beautifyName(s: string, k: TSymKind): string = # as a special rule, don't transform 'L' to 'l' if s.len == 1 and s[0] == 'L': result.add 'L' elif '_' in s: result.add(s[i]) - else: result.add toLower(s[0]) + else: result.add toLowerAscii(s[0]) inc i while i < s.len: if s[i] == '_': @@ -85,9 +85,9 @@ proc beautifyName(s: string, k: TSymKind): string = result.add s[i] else: inc i - result.add toUpper(s[i]) + result.add toUpperAscii(s[i]) elif allUpper: - result.add toLower(s[i]) + result.add toLowerAscii(s[i]) else: result.add s[i] inc i diff --git a/compiler/options.nim b/compiler/options.nim index 03ae83587..dbd8ca2b9 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -220,7 +220,7 @@ proc setDefaultLibpath*() = libpath = parentNimLibPath proc canonicalizePath*(path: string): string = - when not FileSystemCaseSensitive: result = path.expandFilename.toLower + when not FileSystemCaseSensitive: result = path.expandFilename.toLowerAscii else: result = path.expandFilename proc shortenDir*(dir: string): string = @@ -340,11 +340,11 @@ proc findFile*(f: string): string {.procvar.} = else: result = f.rawFindFile if result.len == 0: - result = f.toLower.rawFindFile + result = f.toLowerAscii.rawFindFile if result.len == 0: result = f.rawFindFile2 if result.len == 0: - result = f.toLower.rawFindFile2 + result = f.toLowerAscii.rawFindFile2 patchModule() proc findModule*(modulename, currentModule: string): string = diff --git a/compiler/sem.nim b/compiler/sem.nim index 717e3b7eb..7db4ae47e 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -164,7 +164,7 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info) proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = - proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLower + proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLowerAscii # like newSymS, but considers gensym'ed symbols if n.kind == nkSym: diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 8e57ed0e2..e9ee50d74 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -635,8 +635,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode = of mCompileDate: result = newStrNodeT(times.getDateStr(), n) of mCompileTime: result = newStrNodeT(times.getClockStr(), n) of mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n) - of mHostOS: result = newStrNodeT(toLower(platform.OS[targetOS].name), n) - of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLower, n) + of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[targetOS].name), n) + of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLowerAscii, n) of mAppType: result = getAppType(n) of mNaN: result = newFloatNodeT(NaN, n) of mInf: result = newFloatNodeT(Inf, n) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 40462a1da..4c9191d12 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -454,7 +454,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = typ = skipIntLit(def.typ) if hasEmpty(typ): localError(def.info, errCannotInferTypeOfTheLiteral, - ($typ.kind).substr(2).toLower) + ($typ.kind).substr(2).toLowerAscii) else: def = ast.emptyNode if symkind == skLet: localError(a.info, errLetNeedsInit) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index bef104914..26ce28852 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1038,7 +1038,7 @@ proc semGenericParamInInvocation(c: PContext, n: PNode): PType = proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = if s.typ == nil: localError(n.info, "cannot instantiate the '$1' $2" % - [s.name.s, ($s.kind).substr(2).toLower]) + [s.name.s, ($s.kind).substr(2).toLowerAscii]) return newOrPrevType(tyError, prev, c) var t = s.typ -- cgit 1.4.1-2-gfad0 From 60b187513ed8e2a061816a912e372a1c81794d50 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 29 Jul 2016 17:35:51 +0200 Subject: stdlib and compiler don't use .immediate anymore --- compiler/ast.nim | 2 ++ compiler/ccgmerge.nim | 2 +- compiler/ccgstmts.nim | 2 +- compiler/extccomp.nim | 2 +- compiler/jsgen.nim | 2 +- compiler/parser.nim | 2 +- compiler/pragmas.nim | 5 ++- compiler/semfold.nim | 4 +-- compiler/semgnrc.nim | 9 ++++-- compiler/semparallel.nim | 2 +- compiler/semtempl.nim | 8 +++-- compiler/sigmatch.nim | 6 ++-- compiler/suggest.nim | 2 +- compiler/types.nim | 2 +- compiler/vm.nim | 19 ++++++------ compiler/vmdef.nim | 12 ++++---- compiler/vmgen.nim | 4 +-- compiler/vmhooks.nim | 4 +-- compiler/vmops.nim | 16 +++++----- lib/core/macros.nim | 17 +++++----- lib/impure/nre.nim | 6 ++-- lib/pure/asyncdispatch.nim | 8 ++--- lib/pure/collections/sequtils.nim | 24 +++++++-------- lib/pure/collections/sets.nim | 4 +-- lib/pure/collections/tableimpl.nim | 14 ++++----- lib/pure/collections/tables.nim | 16 +++++----- lib/pure/future.nim | 6 ++-- lib/pure/net.nim | 4 +-- lib/pure/os.nim | 18 +++++------ lib/pure/strutils.nim | 2 +- lib/pure/times.nim | 63 +++++++++++++------------------------- lib/pure/unittest.nim | 18 +++++------ lib/system.nim | 26 ++++++++-------- tests/macros/tdumptree.nim | 2 +- todo.txt | 4 ++- web/news/version_0_15_released.rst | 4 +++ 36 files changed, 169 insertions(+), 172 deletions(-) (limited to 'compiler/semfold.nim') diff --git a/compiler/ast.nim b/compiler/ast.nim index 4c98219f9..8a3c76435 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -278,6 +278,8 @@ const sfImmediate* = sfDeadCodeElim # macro or template is immediately expanded # without considering any possible overloads + sfAllUntyped* = sfVolatile # macro or template is immediately expanded \ + # in a generic context sfDirty* = sfPure # template is not hygienic (old styled template) diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim index 2e77cd2a6..1b2104174 100644 --- a/compiler/ccgmerge.nim +++ b/compiler/ccgmerge.nim @@ -229,7 +229,7 @@ proc processMergeInfo(L: var TBaseLexer, m: BModule) = when not defined(nimhygiene): {.pragma: inject.} -template withCFile(cfilename: string, body: stmt) {.immediate.} = +template withCFile(cfilename: string, body: untyped) = var s = llStreamOpen(cfilename, fmRead) if s == nil: return var L {.inject.}: TBaseLexer diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 70d50b060..4836527a2 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -136,7 +136,7 @@ proc exprBlock(p: BProc, n: PNode, d: var TLoc) = expr(p, n, d) endBlock(p) -template preserveBreakIdx(body: stmt): stmt {.immediate.} = +template preserveBreakIdx(body: untyped): untyped = var oldBreakIdx = p.breakIdx body p.breakIdx = oldBreakIdx diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index eb9aac490..2dcfc0226 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -61,7 +61,7 @@ type # When adding new compilers, the cmake sources could be a good reference: # http://cmake.org/gitweb?p=cmake.git;a=tree;f=Modules/Platform; -template compiler(name: expr, settings: stmt): stmt {.immediate.} = +template compiler(name, settings: untyped): untyped = proc name: TInfoCC {.compileTime.} = settings # GNU C and C++ Compiler diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index a60b0cc5e..244bba681 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -95,7 +95,7 @@ type up: PProc # up the call chain; required for closure support declaredGlobals: IntSet -template `|`(a, b: expr): expr {.immediate, dirty.} = +template `|`(a, b: untyped): untyped {.dirty.} = (if p.target == targetJS: a else: b) proc newGlobals(): PGlobals = diff --git a/compiler/parser.nim b/compiler/parser.nim index 8b20b56db..2623dea9e 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -98,7 +98,7 @@ proc parMessage(p: TParser, msg: TMsgKind, tok: TToken) = ## Produce and emit a parser message to output about the token `tok` parMessage(p, msg, prettyTok(tok)) -template withInd(p: expr, body: stmt) {.immediate.} = +template withInd(p, body: untyped) = let oldInd = p.currInd p.currInd = p.tok.indent body diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index d7d1ed838..50d5bb1b5 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -626,7 +626,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, processImportCompilerProc(sym, getOptionalStr(c, it, "$1")) of wExtern: setExternName(sym, expectStrLit(c, it)) of wImmediate: - if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate) + if sym.kind in {skTemplate, skMacro}: + incl(sym.flags, sfImmediate) + incl(sym.flags, sfAllUntyped) + message(n.info, warnDeprecated, "use 'untyped' parameters instead; immediate") else: invalidPragma(it) of wDirty: if sym.kind == skTemplate: incl(sym.flags, sfDirty) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index e9ee50d74..7c734e33b 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -143,7 +143,7 @@ proc getIntervalType*(m: TMagic, n: PNode): PType = const ordIntLit = {nkIntLit..nkUInt64Lit} result = n.typ - template commutativeOp(opr: expr) {.immediate.} = + template commutativeOp(opr: untyped) = let a = n.sons[1] let b = n.sons[2] if isIntRangeOrLit(a.typ) and isIntRangeOrLit(b.typ): @@ -151,7 +151,7 @@ proc getIntervalType*(m: TMagic, n: PNode): PType = opr(pickMinInt(a), pickMinInt(b)), opr(pickMaxInt(a), pickMaxInt(b))) - template binaryOp(opr: expr) {.immediate.} = + template binaryOp(opr: untyped) = let a = n.sons[1] let b = n.sons[2] if isIntRange(a.typ) and b.kind in {nkIntLit..nkUInt64Lit}: diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index b78679411..0fd2e546e 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -48,7 +48,10 @@ proc semGenericStmtScope(c: PContext, n: PNode, closeScope(c) template macroToExpand(s: expr): expr = - s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfImmediate in s.flags) + s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfAllUntyped in s.flags) + +template macroToExpandSym(s: expr): expr = + s.kind in {skMacro, skTemplate} and (s.typ.len == 1) proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, ctx: var GenericCtx): PNode = @@ -61,14 +64,14 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, of skProc, skMethod, skIterator, skConverter, skModule: result = symChoice(c, n, s, scOpen) of skTemplate: - if macroToExpand(s): + if macroToExpandSym(s): styleCheckUse(n.info, s) result = semTemplateExpr(c, n, s, {efNoSemCheck}) result = semGenericStmt(c, result, {}, ctx) else: result = symChoice(c, n, s, scOpen) of skMacro: - if macroToExpand(s): + if macroToExpandSym(s): styleCheckUse(n.info, s) result = semMacroExpr(c, n, n, s, {efNoSemCheck}) result = semGenericStmt(c, result, {}, ctx) diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim index a4ec14250..21429a8d8 100644 --- a/compiler/semparallel.nim +++ b/compiler/semparallel.nim @@ -260,7 +260,7 @@ proc min(a, b: PNode): PNode = proc fromSystem(op: PSym): bool = sfSystemModule in getModule(op).flags -template pushSpawnId(c: expr, body: stmt) {.immediate, dirty.} = +template pushSpawnId(c, body) {.dirty.} = inc c.spawns let oldSpawnId = c.currentSpawnId c.currentSpawnId = c.spawns diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index a4498a3ae..3ee019674 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -577,13 +577,16 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = else: gp = newNodeI(nkGenericParams, n.info) # process parameters: + var allUntyped = true if n.sons[paramsPos].kind != nkEmpty: semParamList(c, n.sons[paramsPos], gp, s) # a template's parameters are not gensym'ed even if that was originally the # case as we determine whether it's a template parameter in the template # body by the absence of the sfGenSym flag: for i in 1 .. s.typ.n.len-1: - s.typ.n.sons[i].sym.flags.excl sfGenSym + let param = s.typ.n.sons[i].sym + param.flags.excl sfGenSym + if param.typ.kind != tyExpr: allUntyped = false if sonsLen(gp) > 0: if n.sons[genericParamsPos].kind == nkEmpty: # we have a list of implicit type parameters: @@ -599,6 +602,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = s.typ.n = newNodeI(nkFormalParams, n.info) rawAddSon(s.typ, newTypeS(tyStmt, c)) addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0])) + if allUntyped: incl(s.flags, sfAllUntyped) if n.sons[patternPos].kind != nkEmpty: n.sons[patternPos] = semPattern(c, n.sons[patternPos]) var ctx: TemplCtx @@ -629,7 +633,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = proc semPatternBody(c: var TemplCtx, n: PNode): PNode = template templToExpand(s: expr): expr = - s.kind == skTemplate and (s.typ.len == 1 or sfImmediate in s.flags) + s.kind == skTemplate and (s.typ.len == 1 or sfAllUntyped in s.flags) proc newParam(c: var TemplCtx, n: PNode, s: PSym): PNode = # the param added in the current scope is actually wrong here for diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 9a8f865a6..b8fd8bf1e 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -691,7 +691,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = put(c.bindings, f, bound) return res - template considerPreviousT(body: stmt) {.immediate.} = + template considerPreviousT(body: untyped) = var prev = PType(idTableGet(c.bindings, f)) if prev == nil: body else: return typeRel(c, prev, a) @@ -1591,7 +1591,7 @@ template isVarargsUntyped(x): expr = proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var IntSet) = - template checkConstraint(n: expr) {.immediate, dirty.} = + template checkConstraint(n: untyped) {.dirty.} = if not formal.constraint.isNil: if matchNodeKinds(formal.constraint, n): # better match over other routines with no such restriction: @@ -1816,7 +1816,7 @@ proc instTypeBoundOp*(c: PContext; dc: PSym; t: PType; info: TLineInfo; include suggest when not declared(tests): - template tests(s: stmt) {.immediate.} = discard + template tests(s: untyped) = discard tests: var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo()) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index f35ff2142..c127b968c 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -138,7 +138,7 @@ proc suggestField(c: PContext, s: PSym, outputs: var int) = suggestResult(symToSuggest(s, isLocal=true, $ideSug, 100)) inc outputs -template wholeSymTab(cond, section: expr) {.immediate.} = +template wholeSymTab(cond, section: untyped) = var isLocal = true for scope in walkScopes(c.currentScope): if scope == c.topLevelScope: isLocal = false diff --git a/compiler/types.nim b/compiler/types.nim index 5fbab85b9..42ca0f9fc 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -806,7 +806,7 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool = elif a.n != b.n and (a.n == nil or b.n == nil) and IgnoreTupleFields notin c.flags: result = false -template ifFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} = +template ifFastObjectTypeCheckFailed(a, b: PType, body: untyped) = if tfFromGeneric notin a.flags + b.flags: # fast case: id comparison suffices: result = a.id == b.id diff --git a/compiler/vm.nim b/compiler/vm.nim index f275b7b9b..ac4ea6ad9 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -92,34 +92,34 @@ when not defined(nimComputedGoto): proc myreset(n: var TFullReg) = reset(n) -template ensureKind(k: expr) {.immediate, dirty.} = +template ensureKind(k: untyped) {.dirty.} = if regs[ra].kind != k: myreset(regs[ra]) regs[ra].kind = k -template decodeB(k: expr) {.immediate, dirty.} = +template decodeB(k: untyped) {.dirty.} = let rb = instr.regB ensureKind(k) -template decodeBC(k: expr) {.immediate, dirty.} = +template decodeBC(k: untyped) {.dirty.} = let rb = instr.regB let rc = instr.regC ensureKind(k) -template declBC() {.immediate, dirty.} = +template declBC() {.dirty.} = let rb = instr.regB let rc = instr.regC -template decodeBImm(k: expr) {.immediate, dirty.} = +template decodeBImm(k: untyped) {.dirty.} = let rb = instr.regB let imm = instr.regC - byteExcess ensureKind(k) -template decodeBx(k: expr) {.immediate, dirty.} = +template decodeBx(k: expr) {.dirty.} = let rbx = instr.regBx - wordExcess ensureKind(k) -template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b) +template move(a, b: untyped) {.dirty.} = system.shallowCopy(a, b) # XXX fix minor 'shallowCopy' overloading bug in compiler proc createStrKeepNode(x: var TFullReg; keepNode=true) = @@ -1573,7 +1573,7 @@ proc setupMacroParam(x: PNode, typ: PType): TFullReg = var evalMacroCounter: int proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode = - # XXX GlobalError() is ugly here, but I don't know a better solution for now + # XXX globalError() is ugly here, but I don't know a better solution for now inc(evalMacroCounter) if evalMacroCounter > 100: globalError(n.info, errTemplateInstantiationTooNested) @@ -1603,7 +1603,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode = # return value: tos.slots[0].kind = rkNode - tos.slots[0].node = newNodeIT(nkEmpty, n.info, sym.typ.sons[0]) + tos.slots[0].node = newNodeI(nkEmpty, n.info) # setup parameters: for i in 1.. = r and r > j) or (r > j and j > i) or (j > i and i >= r)): + doWhile((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)): i = (i + 1) and msk # increment mod table size if isEmpty(s.data[i].hcode): # end of collision cluster; So all done return @@ -615,7 +615,7 @@ proc card*[A](s: OrderedSet[A]): int {.inline.} = ## `_ of a set. result = s.counter -template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} = +template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} = var h = s.first while h >= 0: var nxt = s.data[h].next diff --git a/lib/pure/collections/tableimpl.nim b/lib/pure/collections/tableimpl.nim index 1bbf19ee9..f4a135e01 100644 --- a/lib/pure/collections/tableimpl.nim +++ b/lib/pure/collections/tableimpl.nim @@ -72,14 +72,14 @@ proc rawInsert[X, A, B](t: var X, data: var KeyValuePairSeq[A, B], key: A, val: B, hc: Hash, h: Hash) = rawInsertImpl() -template addImpl(enlarge) {.dirty, immediate.} = +template addImpl(enlarge) {.dirty.} = if mustRehash(t.dataLen, t.counter): enlarge(t) var hc: Hash var j = rawGetDeep(t, key, hc) rawInsert(t, t.data, key, val, hc, j) inc(t.counter) -template maybeRehashPutImpl(enlarge) {.dirty, immediate.} = +template maybeRehashPutImpl(enlarge) {.dirty.} = if mustRehash(t.dataLen, t.counter): enlarge(t) index = rawGetKnownHC(t, key, hc) @@ -87,13 +87,13 @@ template maybeRehashPutImpl(enlarge) {.dirty, immediate.} = rawInsert(t, t.data, key, val, hc, index) inc(t.counter) -template putImpl(enlarge) {.dirty, immediate.} = +template putImpl(enlarge) {.dirty.} = var hc: Hash var index = rawGet(t, key, hc) if index >= 0: t.data[index].val = val else: maybeRehashPutImpl(enlarge) -template mgetOrPutImpl(enlarge) {.dirty, immediate.} = +template mgetOrPutImpl(enlarge) {.dirty.} = var hc: Hash var index = rawGet(t, key, hc) if index < 0: @@ -102,7 +102,7 @@ template mgetOrPutImpl(enlarge) {.dirty, immediate.} = # either way return modifiable val result = t.data[index].val -template hasKeyOrPutImpl(enlarge) {.dirty, immediate.} = +template hasKeyOrPutImpl(enlarge) {.dirty.} = var hc: Hash var index = rawGet(t, key, hc) if index < 0: @@ -112,7 +112,7 @@ template hasKeyOrPutImpl(enlarge) {.dirty, immediate.} = proc default[T](t: typedesc[T]): T {.inline.} = discard -template delImpl() {.dirty, immediate.} = +template delImpl() {.dirty.} = var hc: Hash var i = rawGet(t, key, hc) let msk = maxHash(t) @@ -140,7 +140,7 @@ template delImpl() {.dirty, immediate.} = else: shallowCopy(t.data[j], t.data[i]) # data[j] will be marked EMPTY next loop -template clearImpl() {.dirty, immediate.} = +template clearImpl() {.dirty.} = for i in 0 .. = 0: var nxt = t.data[h].next @@ -649,7 +649,7 @@ proc len*[A, B](t: OrderedTableRef[A, B]): int {.inline.} = ## returns the number of keys in `t`. result = t.counter -template forAllOrderedPairs(yieldStmt: stmt) {.dirty, immediate.} = +template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} = var h = t.first while h >= 0: var nxt = t.data[h].next @@ -824,7 +824,7 @@ proc rawGet[A](t: CountTable[A], key: A): int = h = nextTry(h, high(t.data)) result = -1 - h # < 0 => MISSING; insert idx = -1 - result -template ctget(t, key: untyped): untyped {.immediate.} = +template ctget(t, key: untyped): untyped = var index = rawGet(t, key) if index >= 0: result = t.data[index].val else: diff --git a/lib/pure/future.nim b/lib/pure/future.nim index 4e2c1d893..67975cfcb 100644 --- a/lib/pure/future.nim +++ b/lib/pure/future.nim @@ -46,7 +46,7 @@ proc createProcType(p, b: NimNode): NimNode {.compileTime.} = #echo(treeRepr(result)) #echo(result.toStrLit()) -macro `=>`*(p, b: expr): expr {.immediate.} = +macro `=>`*(p, b: untyped): untyped = ## Syntax sugar for anonymous procedures. ## ## .. code-block:: nim @@ -107,7 +107,7 @@ macro `=>`*(p, b: expr): expr {.immediate.} = #echo(result.toStrLit()) #return result # TODO: Bug? -macro `->`*(p, b: expr): expr {.immediate.} = +macro `->`*(p, b: untyped): untyped = ## Syntax sugar for procedure types. ## ## .. code-block:: nim @@ -125,7 +125,7 @@ macro `->`*(p, b: expr): expr {.immediate.} = type ListComprehension = object var lc*: ListComprehension -macro `[]`*(lc: ListComprehension, comp, typ: expr): expr = +macro `[]`*(lc: ListComprehension, comp, typ: untyped): untyped = ## List comprehension, returns a sequence. `comp` is the actual list ## comprehension, for example ``x | (x <- 1..10, x mod 2 == 0)``. `typ` is ## the type that will be stored inside the result seq. diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 7898883cf..9501f6dc7 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -1000,11 +1000,11 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1, ## ## **Warning**: Only the ``SafeDisconn`` flag is currently supported. - template addNLIfEmpty(): stmt = + template addNLIfEmpty() = if line.len == 0: line.string.add("\c\L") - template raiseSockError(): stmt {.dirty, immediate.} = + template raiseSockError() {.dirty.} = let lastError = getSocketError(socket) if flags.isDisconnectionError(lastError): setLen(line.string, 0); return socket.socketError(n, lastError = lastError) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 9eb4cf57d..65bbab3d4 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -173,24 +173,24 @@ proc osLastError*(): OSErrorCode = when defined(windows): when useWinUnicode: - template wrapUnary(varname, winApiProc, arg: expr) {.immediate.} = + template wrapUnary(varname, winApiProc, arg: untyped) = var varname = winApiProc(newWideCString(arg)) - template wrapBinary(varname, winApiProc, arg, arg2: expr) {.immediate.} = + template wrapBinary(varname, winApiProc, arg, arg2: untyped) = var varname = winApiProc(newWideCString(arg), arg2) proc findFirstFile(a: string, b: var WIN32_FIND_DATA): Handle = result = findFirstFileW(newWideCString(a), b) - template findNextFile(a, b: expr): expr = findNextFileW(a, b) - template getCommandLine(): expr = getCommandLineW() + template findNextFile(a, b: untyped): untyped = findNextFileW(a, b) + template getCommandLine(): untyped = getCommandLineW() - template getFilename(f: expr): expr = + template getFilename(f: untyped): untyped = $cast[WideCString](addr(f.cFilename[0])) else: - template findFirstFile(a, b: expr): expr = findFirstFileA(a, b) - template findNextFile(a, b: expr): expr = findNextFileA(a, b) - template getCommandLine(): expr = getCommandLineA() + template findFirstFile(a, b: untyped): untyped = findFirstFileA(a, b) + template findNextFile(a, b: untyped): untyped = findNextFileA(a, b) + template getCommandLine(): untyped = getCommandLineA() - template getFilename(f: expr): expr = $f.cFilename + template getFilename(f: untyped): untyped = $f.cFilename proc skipFindData(f: WIN32_FIND_DATA): bool {.inline.} = # Note - takes advantage of null delimiter in the cstring diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 9b6cf45c5..bfc32bc71 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -475,7 +475,7 @@ proc isNilOrWhitespace*(s: string): bool {.noSideEffect, procvar, rtl, extern: " result = true for c in s: - if not c.isSpace(): + if not c.isSpaceAscii(): return false proc substrEq(s: string, pos: int, substr: string): bool = diff --git a/lib/pure/times.nim b/lib/pure/times.nim index d6cb5c9da..d6eb29e1c 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -998,21 +998,14 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) = info.monthday = value[j..j+1].parseInt() j += 2 of "ddd": - case value[j..j+2].toLower() - of "sun": - info.weekday = dSun - of "mon": - info.weekday = dMon - of "tue": - info.weekday = dTue - of "wed": - info.weekday = dWed - of "thu": - info.weekday = dThu - of "fri": - info.weekday = dFri - of "sat": - info.weekday = dSat + case value[j..j+2].toLowerAscii() + of "sun": info.weekday = dSun + of "mon": info.weekday = dMon + of "tue": info.weekday = dTue + of "wed": info.weekday = dWed + of "thu": info.weekday = dThu + of "fri": info.weekday = dFri + of "sat": info.weekday = dSat else: raise newException(ValueError, "Couldn't parse day of week (ddd), got: " & value[j..j+2]) @@ -1066,31 +1059,19 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) = j += 2 info.month = Month(month-1) of "MMM": - case value[j..j+2].toLower(): - of "jan": - info.month = mJan - of "feb": - info.month = mFeb - of "mar": - info.month = mMar - of "apr": - info.month = mApr - of "may": - info.month = mMay - of "jun": - info.month = mJun - of "jul": - info.month = mJul - of "aug": - info.month = mAug - of "sep": - info.month = mSep - of "oct": - info.month = mOct - of "nov": - info.month = mNov - of "dec": - info.month = mDec + case value[j..j+2].toLowerAscii(): + of "jan": info.month = mJan + of "feb": info.month = mFeb + of "mar": info.month = mMar + of "apr": info.month = mApr + of "may": info.month = mMay + of "jun": info.month = mJun + of "jul": info.month = mJul + of "aug": info.month = mAug + of "sep": info.month = mSep + of "oct": info.month = mOct + of "nov": info.month = mNov + of "dec": info.month = mDec else: raise newException(ValueError, "Couldn't parse month (MMM), got: " & value) @@ -1187,7 +1168,7 @@ proc parseToken(info: var TimeInfo; token, value: string; j: var int) = "Couldn't parse timezone offset (zzz), got: " & value[j]) j += 6 of "ZZZ": - info.tzname = value[j..j+2].toUpper() + info.tzname = value[j..j+2].toUpperAscii() j += 3 else: # Ignore the token and move forward in the value string by the same length diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index 7e3983a0d..92ddc3e75 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -77,7 +77,7 @@ checkpoints = @[] proc shouldRun(testName: string): bool = result = true -template suite*(name: expr, body: stmt): stmt {.immediate, dirty.} = +template suite*(name, body) {.dirty.} = ## Declare a test suite identified by `name` with optional ``setup`` ## and/or ``teardown`` section. ## @@ -106,13 +106,13 @@ template suite*(name: expr, body: stmt): stmt {.immediate, dirty.} = ## [OK] 2 + 2 = 4 ## [OK] (2 + -2) != 4 block: - template setup(setupBody: stmt): stmt {.immediate, dirty.} = + template setup(setupBody: untyped) {.dirty.} = var testSetupIMPLFlag = true - template testSetupIMPL: stmt {.immediate, dirty.} = setupBody + template testSetupIMPL: untyped {.dirty.} = setupBody - template teardown(teardownBody: stmt): stmt {.immediate, dirty.} = + template teardown(teardownBody: untyped) {.dirty.} = var testTeardownIMPLFlag = true - template testTeardownIMPL: stmt {.immediate, dirty.} = teardownBody + template testTeardownIMPL: untyped {.dirty.} = teardownBody body @@ -135,7 +135,7 @@ proc testDone(name: string, s: TestStatus) = else: rawPrint() -template test*(name: expr, body: stmt): stmt {.immediate, dirty.} = +template test*(name, body) {.dirty.} = ## Define a single test case identified by `name`. ## ## .. code-block:: nim @@ -226,7 +226,7 @@ template skip* = testStatusIMPL = SKIPPED checkpoints = @[] -macro check*(conditions: stmt): stmt {.immediate.} = +macro check*(conditions: untyped): untyped = ## Verify if a statement or a list of statements is true. ## A helpful error message and set checkpoints are printed out on ## failure (if ``outputLevel`` is not ``PRINT_NONE``). @@ -318,7 +318,7 @@ macro check*(conditions: stmt): stmt {.immediate.} = result = getAst(rewrite(checked, checked.lineinfo, checked.toStrLit)) -template require*(conditions: stmt): stmt {.immediate.} = +template require*(conditions: untyped) = ## Same as `check` except any failed test causes the program to quit ## immediately. Any teardown statements are not executed and the failed ## test output is not generated. @@ -328,7 +328,7 @@ template require*(conditions: stmt): stmt {.immediate.} = check conditions abortOnError = savedAbortOnError -macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} = +macro expect*(exceptions: varargs[typed], body: untyped): untyped = ## Test if `body` raises an exception found in the passed `exceptions`. ## The test passes if the raised exception is part of the acceptable ## exceptions. Otherwise, it fails. diff --git a/lib/system.nim b/lib/system.nim index b4919db2d..2b19b5633 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -338,15 +338,15 @@ proc `<` *[T](x, y: ref T): bool {.magic: "LtPtr", noSideEffect.} proc `<` *[T](x, y: ptr T): bool {.magic: "LtPtr", noSideEffect.} proc `<` *(x, y: pointer): bool {.magic: "LtPtr", noSideEffect.} -template `!=` * (x, y: expr): expr {.immediate.} = +template `!=` * (x, y: untyped): untyped = ## unequals operator. This is a shorthand for ``not (x == y)``. not (x == y) -template `>=` * (x, y: expr): expr {.immediate.} = +template `>=` * (x, y: untyped): untyped = ## "is greater or equals" operator. This is the same as ``y <= x``. y <= x -template `>` * (x, y: expr): expr {.immediate.} = +template `>` * (x, y: untyped): untyped = ## "is greater" operator. This is the same as ``y < x``. y < x @@ -1098,13 +1098,13 @@ proc contains*[T](s: Slice[T], value: T): bool {.noSideEffect, inline.} = ## assert((1..3).contains(4) == false) result = s.a <= value and value <= s.b -template `in` * (x, y: expr): expr {.immediate, dirty.} = contains(y, x) +template `in` * (x, y: untyped): untyped {.dirty.} = contains(y, x) ## Sugar for contains ## ## .. code-block:: Nim ## assert(1 in (1..3) == true) ## assert(5 in (1..3) == false) -template `notin` * (x, y: expr): expr {.immediate, dirty.} = not contains(y, x) +template `notin` * (x, y: untyped): untyped {.dirty.} = not contains(y, x) ## Sugar for not containing ## ## .. code-block:: Nim @@ -1123,7 +1123,7 @@ proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.} ## ## assert(test[int](3) == 3) ## assert(test[string]("xyz") == 0) -template `isnot` *(x, y: expr): expr {.immediate.} = not (x is y) +template `isnot` *(x, y: untyped): untyped = not (x is y) ## Negated version of `is`. Equivalent to ``not(x is y)``. proc `of` *[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.} @@ -1742,11 +1742,11 @@ proc swap*[T](a, b: var T) {.magic: "Swap", noSideEffect.} ## swaps the values `a` and `b`. This is often more efficient than ## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms. -template `>=%` *(x, y: expr): expr {.immediate.} = y <=% x +template `>=%` *(x, y: untyped): untyped = y <=% x ## treats `x` and `y` as unsigned and compares them. ## Returns true iff ``unsigned(x) >= unsigned(y)``. -template `>%` *(x, y: expr): expr {.immediate.} = y <% x +template `>%` *(x, y: untyped): untyped = y <% x ## treats `x` and `y` as unsigned and compares them. ## Returns true iff ``unsigned(x) > unsigned(y)``. @@ -1874,7 +1874,7 @@ iterator countdown*[T](a, b: T, step = 1): T {.inline.} = yield res dec(res, step) -template countupImpl(incr: stmt) {.immediate, dirty.} = +template countupImpl(incr: untyped) {.dirty.} = when T is IntLikeForCount: var res = int(a) while res <= int(b): @@ -3181,7 +3181,7 @@ proc `/`*(x, y: int): float {.inline, noSideEffect.} = ## integer division that results in a float. result = toFloat(x) / toFloat(y) -template spliceImpl(s, a, L, b: expr): stmt {.immediate.} = +template spliceImpl(s, a, L, b: untyped): untyped = # make room for additional elements or cut: var slen = s.len var shift = b.len - L @@ -3467,7 +3467,7 @@ iterator mitems*(a: var string): var char {.inline.} = when not defined(nimhygiene): {.pragma: inject.} -template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} = +template onFailedAssert*(msg, code: untyped): untyped {.dirty.} = ## Sets an assertion failure handler that will intercept any assert ## statements following `onFailedAssert` in the current module scope. ## @@ -3480,7 +3480,7 @@ template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} = ## e.lineinfo = instantiationInfo(-2) ## raise e ## - template failedAssertImpl(msgIMPL: string): stmt {.dirty.} = + template failedAssertImpl(msgIMPL: string): untyped {.dirty.} = let msg = msgIMPL code @@ -3643,7 +3643,7 @@ proc `==` *(x, y: cstring): bool {.magic: "EqCString", noSideEffect, elif x.isNil or y.isNil: result = false else: result = strcmp(x, y) == 0 -template closureScope*(body: untyped): stmt = +template closureScope*(body: untyped): untyped = ## Useful when creating a closure in a loop to capture local loop variables by ## their current iteration values. Example: ## diff --git a/tests/macros/tdumptree.nim b/tests/macros/tdumptree.nim index e5160b7ba..58b011b45 100644 --- a/tests/macros/tdumptree.nim +++ b/tests/macros/tdumptree.nim @@ -3,7 +3,7 @@ msg: '''StmtList VarSection IdentDefs Ident !"x" - nil + Empty Call DotExpr Ident !"foo" diff --git a/todo.txt b/todo.txt index 235d79b78..38d0fef58 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,9 @@ version 1.0 battle plan ======================= -- Deprecate ``immediate`` for templates and macros +- tests/stdlib/tnre.nim +- tests/closure/tflatmap.nim + - fix "high priority" bugs - try to fix as many compiler crashes as reasonable diff --git a/web/news/version_0_15_released.rst b/web/news/version_0_15_released.rst index e16bdc9ae..c440161c4 100644 --- a/web/news/version_0_15_released.rst +++ b/web/news/version_0_15_released.rst @@ -30,6 +30,10 @@ Changes affecting backwards compatibility discussion. - Overloading the special operators ``.``, ``.()``, ``.=``, ``()`` now should be enabled via ``{.experimental.}``. +- ``immediate`` templates and macros are now deprecated. + Instead use ``untyped`` parameters. +- The metatype ``expr`` is deprecated. Use ``untyped`` instead. +- The metatype ``stmt`` is deprecated. Use ``typed`` instead. Library Additions -- cgit 1.4.1-2-gfad0 From 7d62f031f64dd84690c7b97c086ce5bfbad8de8f Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Sat, 30 Jul 2016 16:19:53 +0800 Subject: remove sfFakeConst --- compiler/ast.nim | 1 - compiler/ccgexprs.nim | 5 +---- compiler/ccgstmts.nim | 2 -- compiler/semfold.nim | 2 +- compiler/transf.nim | 10 ++-------- 5 files changed, 4 insertions(+), 16 deletions(-) (limited to 'compiler/semfold.nim') diff --git a/compiler/ast.nim b/compiler/ast.nim index 8a3c76435..306fcdedc 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -271,7 +271,6 @@ type TSymFlags* = set[TSymFlag] const - sfFakeConst* = sfDeadCodeElim # const cannot be put into a data section sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher sfNoInit* = sfMainModule # don't generate code to init the variable diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 3f12fed2c..75a7cb3bb 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2003,10 +2003,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = internalError(n.info, "expr: proc not init " & sym.name.s) putLocIntoDest(p, d, sym.loc) of skConst: - if sfFakeConst in sym.flags: - if sfGlobal in sym.flags: genVarPrototype(p.module, sym) - putLocIntoDest(p, d, sym.loc) - elif isSimpleConst(sym.typ): + if isSimpleConst(sym.typ): putIntoDest(p, d, n.typ, genLiteral(p, sym.ast, sym.typ), OnStatic) else: genComplexConst(p, sym, d) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 4836527a2..a5ce147c3 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -269,8 +269,6 @@ proc genConstStmt(p: BProc, t: PNode) = if it.kind != nkConstDef: internalError(t.info, "genConstStmt") var c = it.sons[0].sym if c.typ.containsCompileTimeOnly: continue - if sfFakeConst in c.flags: - genSingleVar(p, it) elif c.typ.kind in ConstantDataTypes and lfNoDecl notin c.loc.flags and c.ast.len != 0: if not emitLazily(c): requestConstImpl(p, c) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 7c734e33b..02f238ae6 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -648,7 +648,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode = if isDefined(s.name): result = newStrNodeT(lookupSymbol(s.name), n) else: - if sfFakeConst notin s.flags: result = copyTree(s.ast) + result = copyTree(s.ast) of {skProc, skMethod}: result = n of skType: diff --git a/compiler/transf.nim b/compiler/transf.nim index 25988fb8c..d64276cfb 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -204,14 +204,8 @@ proc transformConstSection(c: PTransf, v: PNode): PTransNode = if it.kind != nkConstDef: internalError(it.info, "transformConstSection") if it.sons[0].kind != nkSym: internalError(it.info, "transformConstSection") - if sfFakeConst in it[0].sym.flags: - var b = newNodeI(nkConstDef, it.info) - addSon(b, it[0]) - addSon(b, ast.emptyNode) # no type description - addSon(b, transform(c, it[2]).PNode) - result[i] = PTransNode(b) - else: - result[i] = PTransNode(it) + + result[i] = PTransNode(it) proc hasContinue(n: PNode): bool = case n.kind -- cgit 1.4.1-2-gfad0