mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-01 19:02:18 +00:00
Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
# general_handler_body
|
||||
# }
|
||||
# {LA1:
|
||||
# labeled_branch_body_LA1
|
||||
# goto LA_END;
|
||||
# }
|
||||
# {LA2:
|
||||
# labeled_branch_body_LA2
|
||||
# finallyPart()
|
||||
# raise;
|
||||
# goto LA_END;
|
||||
# }
|
||||
# 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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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}:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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})
|
||||
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 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
|
||||
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:
|
||||
|
||||
@@ -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``
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
50
tests/casestmt/tduplicates.nim
Normal file
50
tests/casestmt/tduplicates.nim
Normal file
@@ -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
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user