diff options
-rw-r--r-- | changelog.md | 3 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 50 | ||||
-rw-r--r-- | compiler/nimsets.nim | 5 | ||||
-rw-r--r-- | compiler/semcall.nim | 21 | ||||
-rw-r--r-- | compiler/semstmts.nim | 9 | ||||
-rw-r--r-- | compiler/semtypes.nim | 15 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 59 | ||||
-rw-r--r-- | doc/manual/generics.txt | 26 | ||||
-rw-r--r-- | lib/pure/collections/tables.nim | 41 | ||||
-rw-r--r-- | lib/pure/httpclient.nim | 11 | ||||
-rw-r--r-- | lib/pure/net.nim | 10 | ||||
-rw-r--r-- | lib/pure/osproc.nim | 4 | ||||
-rw-r--r-- | lib/pure/parsecsv.nim | 22 | ||||
-rw-r--r-- | lib/pure/terminal.nim | 4 | ||||
-rw-r--r-- | lib/system.nim | 2 | ||||
-rw-r--r-- | tests/casestmt/tduplicates.nim | 50 | ||||
-rw-r--r-- | tests/cpp/tcppraise.nim | 22 | ||||
-rw-r--r-- | tests/generics/tspecial_numeric_inference.nim | 21 | ||||
-rw-r--r-- | tests/iter/titer2.nim | 11 | ||||
-rw-r--r-- | tests/testament/tester.nim | 5 |
20 files changed, 224 insertions, 167 deletions
diff --git a/changelog.md b/changelog.md index 73d7e7d9b..cc57a9188 100644 --- a/changelog.md +++ b/changelog.md @@ -241,9 +241,6 @@ styledEcho "Red on Green.", resetStyle and it no longer raises an OS error but returns an ``osInvalidSocket`` when creation fails. - ``newNativeSocket`` is now named ``createNativeSocket``. -- Type inference for generic type parameters involving numeric types is now symetric. See - [Generic type inference for numeric types](https://nim-lang.org/docs/manual.html#generics-generic-type-inference-fornumeric-types) - for more information. - The ``deprecated`` pragma now supports a user-definable warning message for procs. ```nim diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 9c7bced33..a69495a4b 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -788,30 +788,13 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = # myDiv(4, 9); # } catch (NimExceptionType1&) { # body - # goto LA_END; # } catch (NimExceptionType2&) { # finallyPart() # raise; - # goto LA_END; - # } catch (NimExceptionType3&) {goto LA1;} - # } catch (NimExceptionType4&) {goto LA1;} - # } catch (NimExceptionType5&) {goto LA2;} - # } catch (NimExceptionType6&) {goto LA2;} - # catch(...) { - # // general handler - # goto LA_END; - # } - # {LA1: - # labeled_branch_body_LA1 - # goto LA_END; # } - # {LA2: - # labeled_branch_body_LA2 - # finallyPart() - # raise; - # goto LA_END; + # catch(...) { + # general_handler_body # } - # LA_END: # finallyPart(); template genExceptBranchBody(body: PNode) {.dirty.} = @@ -819,22 +802,19 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n") expr(p, body, d) linefmt(p, cpsStmts, "#popCurrentException();$n") - linefmt(p, cpsStmts, "goto $1;$n", end_label) - if not isEmptyType(t.typ) and d.k == locNone: getTemp(p, t.typ, d) genLineDir(p, t) + let end_label = getLabel(p) discard cgsym(p.module, "Exception") add(p.nestedTryStmts, t) startBlock(p, "try {$n") expr(p, t[0], d) - endBlock(p, ropecg(p.module, "}")) + endBlock(p) - let end_label = getLabel(p) var catchAllPresent = false - var labeled_branches: seq[tuple[label: Rope, body: PNode]] = @[] # generated after labels discovered inc p.inExceptBlock for i in 1..<t.len: @@ -849,20 +829,12 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = startBlock(p, "catch (...) {$n") genExceptBranchBody(t[i][0]) endBlock(p) - - elif t[i].len == 2: - startBlock(p, "catch ($1*) {$n", getTypeDesc(p.module, t[i][0].typ)) - genExceptBranchBody(t[i][^1]) - endBlock(p) - else: - # cpp can't catch multiple types in one statement so we need a label and goto - let label = getLabel(p) - labeled_branches.add((label, t[i][^1])) for j in 0..t[i].len-2: assert(t[i][j].kind == nkType) - linefmt(p, cpsStmts, "catch ($1*) {goto $2;}$n", - [getTypeDesc(p.module, t[i][j].typ), label]) + startBlock(p, "catch ($1*) {$n", getTypeDesc(p.module, t[i][j].typ)) + genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type + endBlock(p) if not catchAllPresent and t[^1].kind == nkFinally: # finally requires catch all presence @@ -871,14 +843,6 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = line(p, cpsStmts, ~"throw;$n") endBlock(p) - # generate labeled branches bodies - for label, body in labeled_branches.items(): - startBlock(p) - fixLabel(p, label) - genExceptBranchBody(body) - endBlock(p) - fixLabel(p, end_label) - dec p.inExceptBlock discard pop(p.nestedTryStmts) diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim index 94507adf0..bda753e85 100644 --- a/compiler/nimsets.nim +++ b/compiler/nimsets.nim @@ -151,6 +151,11 @@ proc complement*(a: PNode): PNode = for i in countup(0, high(x)): x[i] = not x[i] result = toTreeSet(x, a.typ, a.info) +proc deduplicate*(a: PNode): PNode = + var x: TBitSet + toBitSet(a, x) + result = toTreeSet(x, a.typ, a.info) + proc cardSet(s: PNode): BiggestInt = # here we can do better than converting it into a compact set # we just count the elements directly diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 5bdd817d5..6fef11c48 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -169,21 +169,24 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors): else: add(candidates, err.sym.getProcHeader(prefer)) add(candidates, "\n") - if err.firstMismatch != 0 and n.len > 2: - add(candidates, " first type mismatch at position: " & $err.firstMismatch & - "\n required type: ") + if err.firstMismatch != 0 and n.len > 1: + let cond = n.len > 2 + if cond: + candidates.add(" first type mismatch at position: " & $err.firstMismatch & + "\n required type: ") var wanted, got: PType = nil if err.firstMismatch < err.sym.typ.len: wanted = err.sym.typ.sons[err.firstMismatch] - candidates.add typeToString(wanted) + if cond: candidates.add typeToString(wanted) else: - candidates.add "none" + if cond: candidates.add "none" if err.firstMismatch < n.len: - candidates.add "\n but expression '" - candidates.add renderTree(n[err.firstMismatch]) - candidates.add "' is of type: " + if cond: + candidates.add "\n but expression '" + candidates.add renderTree(n[err.firstMismatch]) + candidates.add "' is of type: " got = n[err.firstMismatch].typ - candidates.add typeToString(got) + if cond: candidates.add typeToString(got) if wanted != nil and got != nil: effectProblem(wanted, got, candidates) candidates.add "\n" diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 18b9a347b..1e3265eae 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -692,6 +692,12 @@ proc implicitIterator(c: PContext, it: string, arg: PNode): PNode = result.add arg result = semExprNoDeref(c, result, {efWantIterator}) +proc isTrivalStmtExpr(n: PNode): bool = + for i in 0 .. n.len-2: + if n[i].kind notin {nkEmpty, nkCommentStmt}: + return false + result = true + proc semFor(c: PContext, n: PNode): PNode = result = n checkMinSonsLen(n, 3) @@ -699,6 +705,9 @@ proc semFor(c: PContext, n: PNode): PNode = openScope(c) n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator}) var call = n.sons[length-2] + if call.kind == nkStmtListExpr and isTrivalStmtExpr(call): + call = call.lastSon + n.sons[length-2] = call let isCallExpr = call.kind in nkCallKinds if isCallExpr and call[0].kind == nkSym and call[0].sym.magic in {mFields, mFieldPairs, mOmpParFor}: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index df274c7db..50c2e287e 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -497,8 +497,8 @@ proc semCaseBranchSetElem(c: PContext, t, b: PNode, proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, covered: var BiggestInt) = - - for i in countup(0, sonsLen(branch) - 2): + let lastIndex = sonsLen(branch) - 2 + for i in 0..lastIndex: var b = branch.sons[i] if b.kind == nkRange: branch.sons[i] = b @@ -516,14 +516,21 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, branch.sons[i] = skipConv(fitNode(c, t.sons[0].typ, r, r.info)) inc(covered) else: + if r.kind == nkCurly: + r = r.deduplicate + # first element is special and will overwrite: branch.sons[i]: branch.sons[i] = semCaseBranchSetElem(c, t, r[0], covered) + # other elements have to be added to ``branch`` for j in 1 ..< r.len: branch.add(semCaseBranchSetElem(c, t, r[j], covered)) # caution! last son of branch must be the actions to execute: - var L = branch.len - swap(branch.sons[L-2], branch.sons[L-1]) + swap(branch.sons[^2], branch.sons[^1]) + checkForOverlap(c, t, i, branchIndex) + + # Elements added above needs to be checked for overlaps. + for i in lastIndex.succ..(sonsLen(branch) - 2): checkForOverlap(c, t, i, branchIndex) proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index aba36d24d..9f802a10e 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -915,24 +915,25 @@ proc isCovariantPtr(c: var TCandidate, f, a: PType): bool = else: return false -proc maxNumericType(prev, candidate: PType): PType = - let c = candidate.skipTypes({tyRange}) - template greater(s) = - if c.kind in s: result = c - case prev.kind - of tyInt: greater({tyInt64}) - of tyInt8: greater({tyInt, tyInt16, tyInt32, tyInt64}) - of tyInt16: greater({tyInt, tyInt32, tyInt64}) - of tyInt32: greater({tyInt64}) - - of tyUInt: greater({tyUInt64}) - of tyUInt8: greater({tyUInt, tyUInt16, tyUInt32, tyUInt64}) - of tyUInt16: greater({tyUInt, tyUInt32, tyUInt64}) - of tyUInt32: greater({tyUInt64}) - - of tyFloat32: greater({tyFloat64, tyFloat128}) - of tyFloat64: greater({tyFloat128}) - else: discard +when false: + proc maxNumericType(prev, candidate: PType): PType = + let c = candidate.skipTypes({tyRange}) + template greater(s) = + if c.kind in s: result = c + case prev.kind + of tyInt: greater({tyInt64}) + of tyInt8: greater({tyInt, tyInt16, tyInt32, tyInt64}) + of tyInt16: greater({tyInt, tyInt32, tyInt64}) + of tyInt32: greater({tyInt64}) + + of tyUInt: greater({tyUInt64}) + of tyUInt8: greater({tyUInt, tyUInt16, tyUInt32, tyUInt64}) + of tyUInt16: greater({tyUInt, tyUInt32, tyUInt64}) + of tyUInt32: greater({tyUInt64}) + + of tyFloat32: greater({tyFloat64, tyFloat128}) + of tyFloat64: greater({tyFloat128}) + else: discard proc typeRelImpl(c: var TCandidate, f, aOrig: PType, flags: TTypeRelFlags = {}): TTypeRelation = @@ -1145,12 +1146,12 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, fRange = prev let ff = f.sons[1].skipTypes({tyTypeDesc}) let aa = a.sons[1].skipTypes({tyTypeDesc}) - + if f.sons[0].kind != tyGenericParam and aa.kind == tyEmpty: - result = isGeneric + result = isGeneric else: result = typeRel(c, ff, aa) - + if result < isGeneric: if nimEnableCovariance and trNoCovariance notin flags and @@ -1631,13 +1632,15 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType, # Special type binding rule for numeric types. # See section "Generic type inference for numeric types" of the # manual for further details: - let rebinding = maxNumericType(x.skipTypes({tyRange}), a) - if rebinding != nil: - put(c, f, rebinding) - result = isGeneric - else: - result = typeRel(c, x, a) # check if it fits - if result > isGeneric: result = isGeneric + when false: + let rebinding = maxNumericType(x.skipTypes({tyRange}), a) + if rebinding != nil: + put(c, f, rebinding) + result = isGeneric + else: + discard + result = typeRel(c, x, a) # check if it fits + if result > isGeneric: result = isGeneric of tyStatic: let prev = PType(idTableGet(c.bindings, f)) if prev == nil: diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt index 30055f035..4c908fefe 100644 --- a/doc/manual/generics.txt +++ b/doc/manual/generics.txt @@ -713,29 +713,3 @@ definition): But a ``bind`` is rarely useful because symbol binding from the definition scope is the default. - -Generic type inference for numeric types ----------------------------------------- - -A `numeric`:idx: type is any signed, unsigned integer type, floating point -type or a subrange thereof. Let ``maxNumericType(T1, T2)`` be the "greater" -type of ``T1`` and ``T2``, that is the type that uses more bits. For -example ``maxNumericType(int32, int64) == int64``. ``maxNumericType`` is only -defined for numeric types of the same class (signed, unsigned, floating point). -``maxNumericType`` strips away subranges, -``maxNumericType(subrangeof(int16), int8)`` produces ``int16`` not its -subrange. The definition ``maxNumericType`` is extended to take a variable -number of arguments in the obvious way; -``maxNumericType(x, y, z) == maxNumericType(maxNumericType(x, y), z)``. - -A generic type parameter ``T`` that is bound to multiple numeric types ``N1``, -``N2``, ``N3``, ... during type checking is inferred to -be ``maxNumericType(N1, N2, N3, ...)``. This special type inference rule ensures -that the builtin arithmetic operators can be written in an intuitive way: - -.. code-block:: nim - proc `@`[T: int|int16|int32](x, y: T): T - - 4'i32 @ 6'i64 # inferred to be of type ``int64`` - - 4'i64 @ 6'i32 # inferred to be of type ``int64`` diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 777beabc3..c97846f92 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -955,6 +955,17 @@ proc `[]=`*[A](t: var CountTable[A], key: A, val: int) = #t.data[h].key = key #t.data[h].val = val +proc inc*[A](t: var CountTable[A], key: A, val = 1) = + ## increments `t[key]` by `val`. + var index = rawGet(t, key) + if index >= 0: + inc(t.data[index].val, val) + if t.data[index].val == 0: dec(t.counter) + else: + if mustRehash(len(t.data), t.counter): enlarge(t) + rawInsert(t, t.data, key, val) + inc(t.counter) + proc initCountTable*[A](initialSize=64): CountTable[A] = ## creates a new count table that is empty. ## @@ -969,7 +980,7 @@ proc toCountTable*[A](keys: openArray[A]): CountTable[A] = ## creates a new count table with every key in `keys` having a count ## of how many times it occurs in `keys`. result = initCountTable[A](rightSize(keys.len)) - for key in items(keys): result.inc key + for key in items(keys): result.inc(key) proc `$`*[A](t: CountTable[A]): string = ## The `$` operator for count tables. @@ -980,17 +991,6 @@ proc `==`*[A](s, t: CountTable[A]): bool = ## contain the same keys with the same count. Insert order does not matter. equalsImpl(s, t) -proc inc*[A](t: var CountTable[A], key: A, val = 1) = - ## increments `t[key]` by `val`. - var index = rawGet(t, key) - if index >= 0: - inc(t.data[index].val, val) - if t.data[index].val == 0: dec(t.counter) - else: - if mustRehash(len(t.data), t.counter): enlarge(t) - rawInsert(t, t.data, key, val) - inc(t.counter) - proc smallest*[A](t: CountTable[A]): tuple[key: A, val: int] = ## returns the (key,val)-pair with the smallest `val`. Efficiency: O(n) assert t.len > 0 @@ -1088,6 +1088,10 @@ proc `[]=`*[A](t: CountTableRef[A], key: A, val: int) = assert val > 0 t[][key] = val +proc inc*[A](t: CountTableRef[A], key: A, val = 1) = + ## increments `t[key]` by `val`. + t[].inc(key, val) + proc newCountTable*[A](initialSize=64): CountTableRef[A] = ## creates a new count table that is empty. ## @@ -1098,9 +1102,10 @@ proc newCountTable*[A](initialSize=64): CountTableRef[A] = result[] = initCountTable[A](initialSize) proc newCountTable*[A](keys: openArray[A]): CountTableRef[A] = - ## creates a new count table with every key in `keys` having a count of 1. + ## creates a new count table with every key in `keys` having a count + ## of how many times it occurs in `keys`. result = newCountTable[A](rightSize(keys.len)) - for key in items(keys): result[key] = 1 + for key in items(keys): result.inc(key) proc `$`*[A](t: CountTableRef[A]): string = ## The `$` operator for count tables. @@ -1114,10 +1119,6 @@ proc `==`*[A](s, t: CountTableRef[A]): bool = elif isNil(t): result = false else: result = s[] == t[] -proc inc*[A](t: CountTableRef[A], key: A, val = 1) = - ## increments `t[key]` by `val`. - t[].inc(key, val) - proc smallest*[A](t: CountTableRef[A]): (A, int) = ## returns the (key,val)-pair with the smallest `val`. Efficiency: O(n) t[].smallest @@ -1316,7 +1317,6 @@ when isMainModule: assert a == b assert a == c - block: #6250 let a = {3: 1}.toOrderedTable @@ -1332,6 +1332,5 @@ when isMainModule: assert((b == a) == true) block: # CountTable.smallest - var t = initCountTable[int]() - for v in items([0, 0, 5, 5, 5]): t.inc(v) + let t = toCountTable([0, 0, 5, 5, 5]) doAssert t.smallest == (0, 2) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index f81e80766..648481ca5 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -507,7 +507,7 @@ proc request*(url: string, httpMethod: string, extraHeaders = "", port = net.Port(443) else: raise newException(HttpRequestError, - "SSL support is not available. Cannot connect over SSL.") + "SSL support is not available. Cannot connect over SSL. Compile with -d:ssl to enable.") if r.port != "": port = net.Port(r.port.parseInt) @@ -540,7 +540,8 @@ proc request*(url: string, httpMethod: string, extraHeaders = "", "so a secure connection could not be established.") sslContext.wrapConnectedSocket(s, handshakeAsClient, hostUrl.hostname) else: - raise newException(HttpRequestError, "SSL support not available. Cannot connect via proxy over SSL") + raise newException(HttpRequestError, "SSL support not available. Cannot " & + "connect via proxy over SSL. Compile with -d:ssl to enable.") else: if timeout == -1: s.connect(r.hostname, port) @@ -1087,7 +1088,7 @@ proc newConnection(client: HttpClient | AsyncHttpClient, if isSsl and not defined(ssl): raise newException(HttpRequestError, - "SSL support is not available. Cannot connect over SSL.") + "SSL support is not available. Cannot connect over SSL. Compile with -d:ssl to enable.") if client.connected: client.close() @@ -1137,7 +1138,7 @@ proc newConnection(client: HttpClient | AsyncHttpClient, client.socket, handshakeAsClient, url.hostname) else: raise newException(HttpRequestError, - "SSL support is not available. Cannot connect over SSL.") + "SSL support is not available. Cannot connect over SSL. Compile with -d:ssl to enable.") # May be connected through proxy but remember actual URL being accessed client.currentURL = url @@ -1333,4 +1334,4 @@ proc downloadFile*(client: AsyncHttpClient, url: string, finally: result.addCallback( proc () = client.getBody = true - ) \ No newline at end of file + ) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 99d868847..af9eea51a 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -430,8 +430,14 @@ when defineSsl: raise newException(SSLError, "No error reported.") if err == -1: raiseOSError(osLastError()) - var errStr = ErrErrorString(err, nil) - raise newException(SSLError, $errStr) + var errStr = $ErrErrorString(err, nil) + case err + of 336032814, 336032784: + errStr = "Please upgrade your OpenSSL library, it does not support the " & + "necessary protocols. OpenSSL error is: " & errStr + else: + discard + raise newException(SSLError, errStr) proc getExtraData*(ctx: SSLContext, index: int): RootRef = ## Retrieves arbitrary data stored inside SSLContext. diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 1625845d1..c1c727fc6 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -306,7 +306,7 @@ proc execProcesses*(cmds: openArray[string], raiseOSError(err) if rexit >= 0: - result = max(result, q[rexit].peekExitCode()) + result = max(result, abs(q[rexit].peekExitCode())) if afterRunEvent != nil: afterRunEvent(rexit, q[rexit]) close(q[rexit]) if i < len(cmds): @@ -331,7 +331,7 @@ proc execProcesses*(cmds: openArray[string], if beforeRunEvent != nil: beforeRunEvent(i) var p = startProcess(cmds[i], options=options + {poEvalCommand}) - result = max(waitForExit(p), result) + result = max(abs(waitForExit(p)), result) if afterRunEvent != nil: afterRunEvent(i, p) close(p) diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim index 071858b7c..358ce829d 100644 --- a/lib/pure/parsecsv.nim +++ b/lib/pure/parsecsv.nim @@ -32,7 +32,7 @@ ## import parsecsv ## import os ## # Prepare a file -## var content = """One,Two,Three,Four +## let content = """One,Two,Three,Four ## 1,2,3,4 ## 10,20,30,40 ## 100,200,300,400 @@ -123,7 +123,7 @@ proc parseField(my: var CsvParser, a: var string) = if buf[pos] == my.quote and my.quote != '\0': inc(pos) while true: - var c = buf[pos] + let c = buf[pos] if c == '\0': my.bufpos = pos # can continue after exception? error(my, pos, my.quote & " expected") @@ -153,7 +153,7 @@ proc parseField(my: var CsvParser, a: var string) = inc(pos) else: while true: - var c = buf[pos] + let c = buf[pos] if c == my.sep: break if c in {'\c', '\l', '\0'}: break add(a, c) @@ -171,9 +171,9 @@ proc readRow*(my: var CsvParser, columns = 0): bool = ## ## Blank lines are skipped. var col = 0 # current column - var oldpos = my.bufpos + let oldpos = my.bufpos while my.buf[my.bufpos] != '\0': - var oldlen = my.row.len + let oldlen = my.row.len if oldlen < col+1: setLen(my.row, col+1) my.row[col] = "" @@ -208,16 +208,16 @@ proc close*(my: var CsvParser) {.inline.} = proc readHeaderRow*(my: var CsvParser) = ## Reads the first row and creates a look-up table for column numbers ## See also `rowEntry <#rowEntry.CsvParser.string>`_. - var present = my.readRow() + let present = my.readRow() if present: my.headers = my.row -proc rowEntry*(my: var CsvParser, entry: string): string = - ## Reads a specified `entry` from the current row. +proc rowEntry*(my: var CsvParser, entry: string): var string = + ## Acceses a specified `entry` from the current row. ## ## Assumes that `readHeaderRow <#readHeaderRow.CsvParser>`_ has already been ## called. - var index = my.headers.find(entry) + let index = my.headers.find(entry) if index >= 0: result = my.row[index] @@ -237,14 +237,14 @@ when isMainModule: import os import strutils block: # Tests for reading the header row - var content = "One,Two,Three,Four\n1,2,3,4\n10,20,30,40,\n100,200,300,400\n" + let content = "One,Two,Three,Four\n1,2,3,4\n10,20,30,40,\n100,200,300,400\n" writeFile("temp.csv", content) var p: CsvParser p.open("temp.csv") p.readHeaderRow() while p.readRow(): - var zeros = repeat('0', p.currRow-2) + let zeros = repeat('0', p.currRow-2) doAssert p.rowEntry("One") == "1" & zeros doAssert p.rowEntry("Two") == "2" & zeros doAssert p.rowEntry("Three") == "3" & zeros diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 032d3360f..6ed04c0d8 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -372,7 +372,7 @@ proc cursorForward*(f: File, count=1) = inc(p.x, count) setCursorPos(h, p.x, p.y) else: - f.write("{stylePrefix}{count}C") + f.write(fmt"{stylePrefix}{count}C") proc cursorBackward*(f: File, count=1) = ## Moves the cursor backward by `count` columns. @@ -382,7 +382,7 @@ proc cursorBackward*(f: File, count=1) = dec(p.x, count) setCursorPos(h, p.x, p.y) else: - f.write("{stylePrefix}{count}D") + f.write(fmt"{stylePrefix}{count}D") when true: discard diff --git a/lib/system.nim b/lib/system.nim index 6815932e2..2b2ce7008 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1917,7 +1917,7 @@ proc `$` *(x: float): string {.magic: "FloatToStr", noSideEffect.} proc `$` *(x: bool): string {.magic: "BoolToStr", noSideEffect.} ## The stringify operator for a boolean argument. Returns `x` ## converted to the string "false" or "true". -# + proc `$` *(x: char): string {.magic: "CharToStr", noSideEffect.} ## The stringify operator for a character argument. Returns `x` ## converted to a string. diff --git a/tests/casestmt/tduplicates.nim b/tests/casestmt/tduplicates.nim new file mode 100644 index 000000000..f9fc1cc26 --- /dev/null +++ b/tests/casestmt/tduplicates.nim @@ -0,0 +1,50 @@ +discard """ + output: ''' +OK +OK +OK + ''' +""" + +type Kind = enum A, B +var k = A + +template reject(b) = + static: doAssert(not compiles(b)) + +reject: + var i = 2 + case i + of [1, 1]: discard + else: discard + +reject: + var i = 2 + case i + of 1, { 1..2 }: discard + else: discard + +reject: + var i = 2 + case i + of { 1, 1 }: discard + of { 1, 1 }: discard + else: discard + +reject: + case k + of [A, A]: discard + +var i = 2 +case i +of { 1, 1 }: discard +of { 2, 2 }: echo "OK" +else: discard + +case i +of { 10..30, 15..25, 5..15, 25..35 }: discard +else: echo "OK" + +case k +of {A, A..A}: echo "OK" +of B: discard \ No newline at end of file diff --git a/tests/cpp/tcppraise.nim b/tests/cpp/tcppraise.nim index 7db9c0cfa..f359a2e8b 100644 --- a/tests/cpp/tcppraise.nim +++ b/tests/cpp/tcppraise.nim @@ -3,7 +3,9 @@ discard """ output: '''foo bar Need odd and >= 3 digits## -baz''' +baz +caught +''' """ # bug #1888 @@ -15,3 +17,21 @@ try: except ValueError: echo getCurrentExceptionMsg(), "##" echo "baz" + + +# bug 7232 +try: + discard +except KeyError, ValueError: + echo "except handler" # should not be invoked + + +#bug 7239 +try: + try: + raise newException(ValueError, "asdf") + except KeyError, ValueError: + raise +except: + echo "caught" + diff --git a/tests/generics/tspecial_numeric_inference.nim b/tests/generics/tspecial_numeric_inference.nim index d93544ba4..41a84a5e9 100644 --- a/tests/generics/tspecial_numeric_inference.nim +++ b/tests/generics/tspecial_numeric_inference.nim @@ -1,12 +1,21 @@ discard """ - output: '''int64 -int64''' + output: '''false''' """ -import typetraits +when false: + import typetraits -proc `@`[T: SomeInteger](x, y: T): T = x + proc `@`[T: SomeInteger](x, y: T): T = x -echo(type(5'i64 @ 6'i32)) + echo(type(5'i64 @ 6'i32)) -echo(type(5'i32 @ 6'i64)) + echo(type(5'i32 @ 6'i64)) + +import sets +# bug #7247 +type + n8 = range[0'i8..127'i8] + +var tab = initSet[n8]() + +echo tab.contains(8) diff --git a/tests/iter/titer2.nim b/tests/iter/titer2.nim index 4a7f76883..f60aed73a 100644 --- a/tests/iter/titer2.nim +++ b/tests/iter/titer2.nim @@ -2,7 +2,12 @@ discard """ output: '''true 3 4 -5''' +5 +0 +1 +2 +3 +4''' cmd: "nim $target --gc:none --hints:on --warnings:off $options $file" """ @@ -55,3 +60,7 @@ echo "true" # bug #1560 for i in @[3, 4, 5]: echo($i) + +# bug #6992 +for i in 0 ..< 5u32: + echo i diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index 918de881f..06f5fec7d 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -294,7 +294,6 @@ proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec, proc testSpec(r: var TResults, test: TTest, target = targetC) = let tname = test.name.addFileExt(".nim") #echo "TESTING ", tname - inc(r.total) var expected: TSpec if test.action != actionRunNoSpec: expected = parseSpec(tname) @@ -305,12 +304,14 @@ proc testSpec(r: var TResults, test: TTest, target = targetC) = if expected.err == reIgnored: r.addResult(test, target, "", "", reIgnored) inc(r.skipped) + inc(r.total) return if expected.targets == {}: expected.targets.incl(target) for target in expected.targets: + inc(r.total) if target notin targets: r.addResult(test, target, "", "", reIgnored) inc(r.skipped) @@ -490,7 +491,7 @@ proc main() = else: echo r, r.data backend.close() var failed = r.total - r.passed - r.skipped - if failed > 0: + if failed != 0: echo "FAILURE! total: ", r.total, " passed: ", r.passed, " skipped: ", r.skipped quit(QuitFailure) |