diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 02c31163ae..2050a746b4 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -109,3 +109,4 @@ proc initDefines*() = defineSymbol("nimGenericInOutFlags") when false: defineSymbol("nimHasOpt") defineSymbol("nimNoArrayToCstringConversion") + defineSymbol("nimNewRoof") diff --git a/compiler/liftlocals.nim b/compiler/liftlocals.nim new file mode 100644 index 0000000000..3610a14862 --- /dev/null +++ b/compiler/liftlocals.nim @@ -0,0 +1,70 @@ +# +# +# The Nim Compiler +# (c) Copyright 2015 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements the '.liftLocals' pragma. + +import + intsets, strutils, options, ast, astalgo, msgs, + idents, renderer, types, lowerings + +from pragmas import getPragmaVal +from wordrecg import wLiftLocals + +type + Ctx = object + partialParam: PSym + objType: PType + +proc interestingVar(s: PSym): bool {.inline.} = + result = s.kind in {skVar, skLet, skTemp, skForVar, skResult} and + sfGlobal notin s.flags + +proc lookupOrAdd(c: var Ctx; s: PSym; info: TLineInfo): PNode = + let field = addUniqueField(c.objType, s) + var deref = newNodeI(nkHiddenDeref, info) + deref.typ = c.objType + add(deref, newSymNode(c.partialParam, info)) + result = newNodeI(nkDotExpr, info) + add(result, deref) + add(result, newSymNode(field)) + result.typ = field.typ + +proc liftLocals(n: PNode; i: int; c: var Ctx) = + let it = n[i] + case it.kind + of nkSym: + if interestingVar(it.sym): + n[i] = lookupOrAdd(c, it.sym, it.info) + of procDefs, nkTypeSection: discard + else: + for i in 0 ..< it.safeLen: + liftLocals(it, i, c) + +proc lookupParam(params, dest: PNode): PSym = + if dest.kind != nkIdent: return nil + for i in 1 ..< params.len: + if params[i].kind == nkSym and params[i].sym.name.id == dest.ident.id: + return params[i].sym + +proc liftLocalsIfRequested*(prc: PSym; n: PNode): PNode = + let liftDest = getPragmaVal(prc.ast, wLiftLocals) + if liftDest == nil: return n + let partialParam = lookupParam(prc.typ.n, liftDest) + if partialParam.isNil: + localError(liftDest.info, "'$1' is not a parameter of '$2'" % + [$liftDest, prc.name.s]) + return n + let objType = partialParam.typ.skipTypes(abstractPtrs) + if objType.kind != tyObject or tfPartial notin objType.flags: + localError(liftDest.info, "parameter '$1' is not a pointer to a partial object" % $liftDest) + return n + var c = Ctx(partialParam: partialParam, objType: objType) + let w = newTree(nkStmtList, n) + liftLocals(w, 0, c) + result = w[0] diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 787216bb32..9612ff0aba 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -182,8 +182,9 @@ proc addField*(obj: PType; s: PSym) = field.position = sonsLen(obj.n) addSon(obj.n, newSymNode(field)) -proc addUniqueField*(obj: PType; s: PSym) = - if lookupInRecord(obj.n, s.id) == nil: +proc addUniqueField*(obj: PType; s: PSym): PSym {.discardable.} = + result = lookupInRecord(obj.n, s.id) + if result == nil: var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info) field.id = -s.id let t = skipIntLit(s.typ) @@ -191,6 +192,7 @@ proc addUniqueField*(obj: PType; s: PSym) = assert t.kind != tyStmt field.position = sonsLen(obj.n) addSon(obj.n, newSymNode(field)) + result = field proc newDotExpr(obj, b: PSym): PNode = result = newNodeI(nkDotExpr, obj.info) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index c279e088c0..5acfbc9192 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -25,7 +25,7 @@ const wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, - wOverride, wConstructor, wExportNims, wUsed} + wOverride, wConstructor, wExportNims, wUsed, wLiftLocals} converterPragmas* = procPragmas methodPragmas* = procPragmas+{wBase}-{wImportCpp} templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, @@ -70,6 +70,14 @@ const wThread, wRaises, wLocks, wTags, wGcSafe} allRoutinePragmas* = methodPragmas + iteratorPragmas + lambdaPragmas +proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode = + let p = procAst[pragmasPos] + if p.kind == nkEmpty: return nil + for it in p: + if it.kind == nkExprColonExpr and it[0].kind == nkIdent and + it[0].ident.id == ord(name): + return it[1] + proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) # implementation @@ -978,6 +986,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, noVal(it) if sym == nil: invalidPragma(it) else: sym.flags.incl sfUsed + of wLiftLocals: discard else: invalidPragma(it) else: invalidPragma(it) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 3e57d1104b..5057260a4b 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -339,7 +339,7 @@ proc makeNotType*(c: PContext, t1: PType): PType = proc nMinusOne*(n: PNode): PNode = result = newNode(nkCall, n.info, @[ - newSymNode(getSysMagic("<", mUnaryLt)), + newSymNode(getSysMagic("pred", mPred)), n]) # Remember to fix the procs below this one when you make changes! diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index d721f42abd..0803b99ece 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -168,7 +168,9 @@ proc semTypeTraits(c: PContext, n: PNode): PNode = proc semOrd(c: PContext, n: PNode): PNode = result = n let parType = n.sons[1].typ - if isOrdinalType(parType) or parType.kind == tySet: + if isOrdinalType(parType): + discard + elif parType.kind == tySet: result.typ = makeRangeType(c, firstOrd(parType), lastOrd(parType), n.info) else: localError(n.info, errOrdinalTypeExpected) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 1494c5316d..231dd80f47 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -390,7 +390,16 @@ proc isConvertibleToRange(f, a: PType): bool = # be less picky for tyRange, as that it is used for array indexing: if f.kind in {tyInt..tyInt64, tyUInt..tyUInt64} and a.kind in {tyInt..tyInt64, tyUInt..tyUInt64}: - result = true + case f.kind + of tyInt, tyInt64: result = true + of tyInt8: result = a.kind in {tyInt8, tyInt} + of tyInt16: result = a.kind in {tyInt8, tyInt16, tyInt} + of tyInt32: result = a.kind in {tyInt8, tyInt16, tyInt32, tyInt} + of tyUInt, tyUInt64: result = true + of tyUInt8: result = a.kind in {tyUInt8, tyUInt} + of tyUInt16: result = a.kind in {tyUInt8, tyUInt16, tyUInt} + of tyUInt32: result = a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt} + else: result = false elif f.kind in {tyFloat..tyFloat128} and a.kind in {tyFloat..tyFloat128}: result = true diff --git a/compiler/transf.nim b/compiler/transf.nim index 9c947fc1ed..baf801cbf1 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -21,7 +21,7 @@ import intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os, idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread, - lambdalifting, sempass2, lowerings, lookups, destroyer + lambdalifting, sempass2, lowerings, lookups, destroyer, liftlocals type PTransNode* = distinct PNode @@ -978,6 +978,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode = liftDefer(c, result) #result = liftLambdas(prc, result) when useEffectSystem: trackProc(prc, result) + result = liftLocalsIfRequested(prc, result) if c.needsDestroyPass and newDestructors: result = injectDestructorCalls(prc, result) incl(result.flags, nfTransf) diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 19e182942a..f5ba35dfb0 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -66,7 +66,7 @@ type wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wAsmNoStackFrame, wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, - wPartial, wExplain, + wPartial, wExplain, wLiftLocals, wAuto, wBool, wCatch, wChar, wClass, wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast, @@ -152,7 +152,7 @@ const "computedgoto", "injectstmt", "experimental", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", - "guard", "locks", "partial", "explain", + "guard", "locks", "partial", "explain", "liftlocals", "auto", "bool", "catch", "char", "class", "const_cast", "default", "delete", "double", diff --git a/config/nim.cfg b/config/nim.cfg index 7ac87cc334..6ae55a9b2a 100644 --- a/config/nim.cfg +++ b/config/nim.cfg @@ -202,6 +202,11 @@ vcc.cpp.linkerexe = "vccexe.exe" # set the options for specific platforms: vcc.options.always = "/nologo" +@if release: + # no debug symbols in release builds +@else: + vcc.options.always %= "${vcc.options.always} /Z7" # Get VCC to output full debug symbols in the obj file +@end vcc.cpp.options.always %= "${vcc.options.always} /EHsc" vcc.options.linker = "/nologo /DEBUG /Zi /F33554432" # set the stack size to 32 MiB vcc.cpp.options.linker %= "${vcc.options.linker}" @@ -222,8 +227,8 @@ vcc.options.linker %= "--platform:arm ${vcc.options.linker}" vcc.cpp.options.linker %= "--platform:arm ${vcc.cpp.options.linker}" @end -vcc.options.debug = "/Zi /FS /Od" -vcc.cpp.options.debug = "/Zi /FS /Od" +vcc.options.debug = "/Od" +vcc.cpp.options.debug = "/Od" vcc.options.speed = "/O2" vcc.cpp.options.speed = "/O2" vcc.options.size = "/O1" diff --git a/lib/deprecated/pure/sockets.nim b/lib/deprecated/pure/sockets.nim index 153db9ed86..f068c7d560 100644 --- a/lib/deprecated/pure/sockets.nim +++ b/lib/deprecated/pure/sockets.nim @@ -262,7 +262,7 @@ proc socket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, # TODO: Perhaps this should just raise EOS when an error occurs. when defined(Windows): - result = newTSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)), buffered) + result = newTSocket(winlean.socket(cint(domain), cint(typ), cint(protocol)), buffered) else: result = newTSocket(posix.socket(toInt(domain), toInt(typ), toInt(protocol)), buffered) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 215a301b66..a405ce1bda 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -857,13 +857,16 @@ proc close*(socket: Socket) = # shutdown i.e not wait for the peers "close notify" alert with a second # call to SSLShutdown let res = SSLShutdown(socket.sslHandle) - SSLFree(socket.sslHandle) - socket.sslHandle = nil if res == 0: discard elif res != 1: socketError(socket, res) finally: + when defineSsl: + if socket.isSSL and socket.sslHandle != nil: + SSLFree(socket.sslHandle) + socket.sslHandle = nil + socket.fd.close() proc toCInt*(opt: SOBool): cint = diff --git a/lib/pure/parseopt2.nim b/lib/pure/parseopt2.nim index 2e8dbe1402..a2ff9bf0c0 100644 --- a/lib/pure/parseopt2.nim +++ b/lib/pure/parseopt2.nim @@ -35,7 +35,7 @@ type cmd: seq[string] pos: int remainingShortOptions: string - kind*: CmdLineKind ## the dected command line token + kind*: CmdLineKind ## the detected command line token key*, val*: TaintedString ## key and value pair; ``key`` is the option ## or the argument, ``value`` is not "" if ## the option was given a value diff --git a/lib/pure/securehash.nim b/lib/pure/securehash.nim index c191466698..57c1f3631c 100644 --- a/lib/pure/securehash.nim +++ b/lib/pure/securehash.nim @@ -181,7 +181,7 @@ proc `$`*(self: SecureHash): string = result.add(toHex(int(v), 2)) proc parseSecureHash*(hash: string): SecureHash = - for i in 0.. = s.a and value <= s.b` ## @@ -2089,7 +2089,7 @@ proc clamp*[T](x, a, b: T): T = if x > b: return b return x -proc len*[T: Ordinal](x: HSlice[T, T]): int {.noSideEffect, inline.} = +proc len*[U: Ordinal; V: Ordinal](x: HSlice[U, V]): int {.noSideEffect, inline.} = ## length of ordinal slice, when x.b < x.a returns zero length ## ## .. code-block:: Nim @@ -2835,7 +2835,7 @@ when not defined(JS): #and not defined(nimscript): fmRead, ## Open the file for read access only. fmWrite, ## Open the file for write access only. ## If the file does not exist, it will be - ## created. + ## created. Existing files will be cleared! fmReadWrite, ## Open the file for read and write access. ## If the file does not exist, it will be ## created. Existing files will be cleared! @@ -3429,7 +3429,7 @@ template `..^`*(a, b: untyped): untyped = ## '..' and '^' is required. a .. ^b -template `..<`*(a, b: untyped): untyped {.dirty.} = +template `..<`*(a, b: untyped): untyped = ## a shortcut for 'a..pred(b)'. a .. pred(b) @@ -3493,14 +3493,14 @@ proc `[]`*[Idx, T, U, V](a: array[Idx, T], x: HSlice[U, V]): seq[T] = let xa = a ^^ x.a let L = (a ^^ x.b) - xa + 1 result = newSeq[T](L) - for i in 0..".} - let f = NaN echo "Nim: ", f let f32: float32 = NaN echo "Nim: ", f32, " (float)" -discard printf("C: %f (float)\n", f32) let f64: float64 = NaN echo "Nim: ", f64, " (double)" -discard printf("C: %lf (double)\n", f64) diff --git a/tests/iter/tconcat.nim b/tests/iter/tconcat.nim index 94a89b57e5..477ac5e268 100644 --- a/tests/iter/tconcat.nim +++ b/tests/iter/tconcat.nim @@ -9,7 +9,7 @@ discard """ 23''' """ -proc toIter*[T](s: Slice[T, T]): iterator: T = +proc toIter*[T](s: Slice[T]): iterator: T = iterator it: T {.closure.} = for x in s.a..s.b: yield x diff --git a/tests/misc/tvarnums.nim b/tests/misc/tvarnums.nim index a5c30c7ebf..5daa2c4b8e 100644 --- a/tests/misc/tvarnums.nim +++ b/tests/misc/tvarnums.nim @@ -67,7 +67,7 @@ proc toNum64(b: TBuffer): int64 = proc toNum(b: TBuffer): int32 = # treat first byte different: - result = ze(b[0]) and 63 + result = int32 ze(b[0]) and 63 var i = 0 Shift = 6'i32 diff --git a/tests/range/tn8vsint16.nim b/tests/range/tn8vsint16.nim new file mode 100644 index 0000000000..bf4f78e3ba --- /dev/null +++ b/tests/range/tn8vsint16.nim @@ -0,0 +1,18 @@ +discard """ + output: '''-9''' +""" + +type + n32 = range[0..high(int)] + n8* = range[0'i8..high(int8)] + +proc `+`*(a: n32, b: n32{nkIntLit}): n32 = discard + +proc `-`*(a: n8, b: n8): n8 = n8(system.`-`(a, b)) + +var x, y: n8 +var z: int16 + +# ensure this doesn't call our '-' but system.`-` for int16: +echo z - n8(9) + diff --git a/tests/stdlib/nre/captures.nim b/tests/stdlib/nre/captures.nim index fa01a20005..19c344a8db 100644 --- a/tests/stdlib/nre/captures.nim +++ b/tests/stdlib/nre/captures.nim @@ -32,7 +32,7 @@ suite "captures": test "named capture bounds": let ex1 = "foo".find(re("(?foo)(?bar)?")) check(ex1.captureBounds["foo"] == some(0..2)) - check(ex1.captureBounds["bar"] == none(Slice[int, int])) + check(ex1.captureBounds["bar"] == none(Slice[int])) test "capture count": let ex1 = re("(?foo)(?bar)?") @@ -42,7 +42,7 @@ suite "captures": test "named capture table": let ex1 = "foo".find(re("(?foo)(?bar)?")) check(ex1.captures.toTable == {"foo" : "foo", "bar" : nil}.toTable()) - check(ex1.captureBounds.toTable == {"foo" : some(0..2), "bar" : none(Slice[int, int])}.toTable()) + check(ex1.captureBounds.toTable == {"foo" : some(0..2), "bar" : none(Slice[int])}.toTable()) check(ex1.captures.toTable("") == {"foo" : "foo", "bar" : ""}.toTable()) let ex2 = "foobar".find(re("(?foo)(?bar)?")) @@ -51,7 +51,7 @@ suite "captures": test "capture sequence": let ex1 = "foo".find(re("(?foo)(?bar)?")) check(ex1.captures.toSeq == @["foo", nil]) - check(ex1.captureBounds.toSeq == @[some(0..2), none(Slice[int, int])]) + check(ex1.captureBounds.toSeq == @[some(0..2), none(Slice[int])]) check(ex1.captures.toSeq("") == @["foo", ""]) let ex2 = "foobar".find(re("(?foo)(?bar)?")) diff --git a/tests/stdlib/nre/find.nim b/tests/stdlib/nre/find.nim index c37ac56ba0..caa953ff45 100644 --- a/tests/stdlib/nre/find.nim +++ b/tests/stdlib/nre/find.nim @@ -12,7 +12,7 @@ suite "find": test "find bounds": check(toSeq(findIter("1 2 3 4 5 ", re" ")).map( - proc (a: RegexMatch): Slice[int, int] = a.matchBounds + proc (a: RegexMatch): Slice[int] = a.matchBounds ) == @[1..1, 3..3, 5..5, 7..7, 9..9]) test "overlapping find": diff --git a/tests/system/toString.nim b/tests/system/toString.nim index 1279897a7d..3e7fc7ddbd 100644 --- a/tests/system/toString.nim +++ b/tests/system/toString.nim @@ -3,9 +3,9 @@ discard """ """ doAssert "@[23, 45]" == $(@[23, 45]) -doAssert "[32, 45]" == $([32, 45]) +doAssert "[32, 45]" == $([32, 45]) doAssert "@[, foo, bar]" == $(@["", "foo", "bar"]) -doAssert "[, foo, bar]" == $(["", "foo", "bar"]) +doAssert "[, foo, bar]" == $(["", "foo", "bar"]) # bug #2395 let alphaSet: set[char] = {'a'..'c'} diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index dd5e70d501..0daf4089e5 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -30,7 +30,6 @@ Arguments: Options: --print also print results to the console --failing only show failing/ignored tests - --pedantic return non-zero status code if there are failures --targets:"c c++ js objc" run tests for specified targets (default: all) --nim:path use a particular nim executable (default: compiler/nim) """ % resultsFile @@ -439,7 +438,6 @@ proc main() = backend.open() var optPrintResults = false var optFailing = false - var optPedantic = false var p = initOptParser() p.next() @@ -447,7 +445,7 @@ proc main() = case p.key.string.normalize of "print", "verbose": optPrintResults = true of "failing": optFailing = true - of "pedantic": optPedantic = true + of "pedantic": discard "now always enabled" of "targets": targets = parseTargets(p.val.string) of "nim": compilerPrefix = p.val.string else: quit Usage @@ -488,11 +486,10 @@ proc main() = if action == "html": openDefaultBrowser(resultsFile) else: echo r, r.data backend.close() - if optPedantic: - var failed = r.total - r.passed - r.skipped - if failed > 0: - echo "FAILURE! total: ", r.total, " passed: ", r.passed, " skipped: ", r.skipped - quit(QuitFailure) + var failed = r.total - r.passed - r.skipped + if failed > 0: + echo "FAILURE! total: ", r.total, " passed: ", r.passed, " skipped: ", r.skipped + quit(QuitFailure) if paramCount() == 0: quit Usage diff --git a/tests/vm/trgba.nim b/tests/vm/trgba.nim index da1a2d0c52..923ea1b2e8 100644 --- a/tests/vm/trgba.nim +++ b/tests/vm/trgba.nim @@ -22,14 +22,14 @@ template `B=`*(self: TAggRgba8, val: byte) = template `A=`*(self: TAggRgba8, val: byte) = self[3] = val -proc ABGR* (val: int| int64): TAggRgba8 = +proc ABGR*(val: int| int64): TAggRgba8 = var V = val - result.R = V and 0xFF + result.R = byte(V and 0xFF) V = V shr 8 - result.G = V and 0xFF + result.G = byte(V and 0xFF) V = V shr 8 - result.B = V and 0xFF - result.A = (V shr 8) and 0xFF + result.B = byte(V and 0xFF) + result.A = byte((V shr 8) and 0xFF) const c1 = ABGR(0xFF007F7F) diff --git a/web/website.ini b/web/website.ini index b91e4003a5..3274b0b6cb 100644 --- a/web/website.ini +++ b/web/website.ini @@ -44,7 +44,7 @@ srcdoc2: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib;pure/strscan srcdoc2: "pure/parseopt;pure/parseopt2;pure/hashes;pure/strtabs;pure/lexbase" srcdoc2: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql" srcdoc2: "pure/streams;pure/terminal;pure/cgi;pure/unicode;pure/strmisc" -srcdoc2: "pure/htmlgen;pure/parseutils;pure/browsers" +srcdoc2: "pure/htmlgen;pure/parseutils;pure/browsers;js/jsconsole" srcdoc2: "impure/db_postgres;impure/db_mysql;impure/db_sqlite;pure/db_common" srcdoc2: "pure/httpserver;pure/httpclient;pure/smtp;impure/ssl" srcdoc2: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser" @@ -62,9 +62,10 @@ srcdoc2: "pure/nativesockets;pure/asynchttpserver;pure/net;pure/selectors;pure/f srcdoc2: "deprecated/pure/ftpclient" srcdoc2: "pure/asyncfile;pure/asyncftpclient" srcdoc2: "pure/md5;pure/rationals" -srcdoc2: "posix/posix;pure/distros" +srcdoc2: "posix/posix;pure/distros;pure/oswalkdir" srcdoc2: "pure/fenv;pure/securehash;impure/rdstdin" srcdoc2: "pure/basic2d;pure/basic3d;pure/mersenne;pure/coro;pure/httpcore" +srcdoc2: "pure/bitops;pure/nimtracker;pure/punycode;pure/volatile" ; Note: everything under 'webdoc' doesn't get listed in the index, so wrappers ; should live here