Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Araq 2018-02-26 20:48:23 +01:00
commit c3d544221b
20 changed files with 222 additions and 165 deletions

View file

@ -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)

View file

@ -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

View file

@ -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"

View file

@ -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}:

View file

@ -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,

View file

@ -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: