Merge branch 'master' of github.com:Araq/Nimrod into upstream

This commit is contained in:
Zahary Karadjov 2013-05-12 16:14:46 +03:00
commit fca6e31e1d
4 changed files with 29 additions and 7 deletions

View file

@ -79,6 +79,7 @@ type
exc: PNode # stack of exceptions exc: PNode # stack of exceptions
tags: PNode # list of tags tags: PNode # list of tags
bottom: int bottom: int
owner: PSym
PEffects = var TEffects PEffects = var TEffects
@ -173,11 +174,16 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
track(tracked, b.sons[blen-1]) track(tracked, b.sons[blen-1])
tracked.bottom = oldBottom tracked.bottom = oldBottom
proc isIndirectCall(n: PNode): bool = proc isIndirectCall(n: PNode, owner: PSym): bool =
# we don't count f(...) as an indirect call if 'f' is an parameter. # we don't count f(...) as an indirect call if 'f' is an parameter.
# Instead we track expressions of type tyProc too. See the manual for # Instead we track expressions of type tyProc too. See the manual for
# details: # details:
result = n.kind != nkSym or n.sym.kind notin (routineKinds+{skParam}) if n.kind != nkSym:
result = true
elif n.sym.kind == skParam:
result = owner != n.sym.owner or owner == nil
elif n.sym.kind notin routineKinds:
result = true
proc isForwardedProc(n: PNode): bool = proc isForwardedProc(n: PNode): bool =
result = n.kind == nkSym and sfForward in n.sym.flags result = n.kind == nkSym and sfForward in n.sym.flags
@ -274,7 +280,7 @@ proc track(tracked: PEffects, n: PNode) =
elif effectList.len == 0: elif effectList.len == 0:
if isForwardedProc(a): if isForwardedProc(a):
propagateEffects(tracked, n, a.sym) propagateEffects(tracked, n, a.sym)
elif isIndirectCall(a): elif isIndirectCall(a, tracked.owner):
addEffect(tracked, createRaise(n)) addEffect(tracked, createRaise(n))
addTag(tracked, createTag(n)) addTag(tracked, createTag(n))
else: else:
@ -355,6 +361,7 @@ proc trackProc*(s: PSym, body: PNode) =
var t: TEffects var t: TEffects
t.exc = effects.sons[exceptionEffects] t.exc = effects.sons[exceptionEffects]
t.tags = effects.sons[tagEffects] t.tags = effects.sons[tagEffects]
t.owner = s
track(t, body) track(t, body)
let p = s.ast.sons[pragmasPos] let p = s.ast.sons[pragmasPos]

View file

@ -2910,7 +2910,8 @@ possibly raised exceptions; the algorithm operates on ``p``'s call graph:
raise ``system.E_Base`` (the base type of the exception hierarchy) and raise ``system.E_Base`` (the base type of the exception hierarchy) and
thus any exception unless ``T`` has an explicit ``raises`` list. thus any exception unless ``T`` has an explicit ``raises`` list.
However if the call is of the form ``f(...)`` where ``f`` is a parameter However if the call is of the form ``f(...)`` where ``f`` is a parameter
is ignored. Rule 2 compensates for this case. of the currently analysed routine it is ignored. The call is optimistically
assumed to have no effect. Rule 2 compensates for this case.
2. Every expression of some proc type wihtin a call that is not a call 2. Every expression of some proc type wihtin a call that is not a call
itself (and not nil) is assumed to be called indirectly somehow and thus itself (and not nil) is assumed to be called indirectly somehow and thus
its raises list is added to ``p``'s raises list. its raises list is added to ``p``'s raises list.
@ -2933,9 +2934,9 @@ Rules 1-2 ensure the following works:
proc doRaise() {.raises: [EIO].} = proc doRaise() {.raises: [EIO].} =
raise newException(EIO, "IO") raise newException(EIO, "IO")
proc use() = proc use() {.raises: [].} =
# doesn't compile! Can raise EIO!
noRaise(doRaise) noRaise(doRaise)
# Here the compiler inferes that EIO can be raised.
So in many cases a callback does not cause the compiler to be overly So in many cases a callback does not cause the compiler to be overly
conservative in its effect analysis. conservative in its effect analysis.

View file

@ -78,7 +78,7 @@ proc innerText*(n: PXmlNode): string =
result = "" result = ""
assert n.k == xnElement assert n.k == xnElement
for i in 0 .. n.s.len-1: for i in 0 .. n.s.len-1:
if n.s[i].k in {xnText, xnEntity}: result.add(n.fText) if n.s[i].k in {xnText, xnEntity}: result.add(n.s[i].fText)
proc tag*(n: PXmlNode): string {.inline.} = proc tag*(n: PXmlNode): string {.inline.} =
## gets the tag name of `n`. `n` has to be an ``xnElement`` node. ## gets the tag name of `n`. `n` has to be an ``xnElement`` node.

View file

@ -0,0 +1,14 @@
discard """
errormsg: 'type mismatch'
line: 7
"""
proc p(q: proc() ): proc() {.tags: [], raises: [], closure.} =
return proc () =
q()
let yay = p(proc () = raise newException(EIO, "IO"))
proc main() {.raises: [], tags: [].} = yay()
main()