Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
commit
c3d544221b
20 changed files with 222 additions and 165 deletions
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue