diff options
author | Araq <rumpf_a@web.de> | 2013-05-09 03:20:55 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-05-09 03:20:55 +0200 |
commit | 2d39a18faa67e3f8c366450cf67405527405a0b0 (patch) | |
tree | 95436b06975a41bfb640f0ca0c3d4e69e812c006 /compiler | |
parent | 44c4b945eb8e5255aa128dad2553e290eebdd24b (diff) | |
download | Nim-2d39a18faa67e3f8c366450cf67405527405a0b0.tar.gz |
better effects handling for callbacks
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/sempass2.nim | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index f43820fa7..9213bd48d 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -174,7 +174,10 @@ proc trackTryStmt(tracked: PEffects, n: PNode) = tracked.bottom = oldBottom proc isIndirectCall(n: PNode): bool = - result = n.kind != nkSym or n.sym.kind notin routineKinds + # 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 + # details: + result = n.kind != nkSym or n.sym.kind notin (routineKinds+{skParam}) proc isForwardedProc(n: PNode): bool = result = n.kind == nkSym and sfForward in n.sym.flags @@ -236,6 +239,24 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) = let tagSpec = effectSpec(pragma, wTags) mergeTags(tracked, tagSpec, n) +proc trackOperand(tracked: PEffects, n: PNode) = + let op = n.typ + if op != nil and op.kind == tyProc and n.kind != nkNilLit: + InternalAssert op.n.sons[0].kind == nkEffectList + var effectList = op.n.sons[0] + let s = n.skipConv + if s.kind == nkSym and s.sym.kind in routineKinds: + propagateEffects(tracked, n, s.sym) + elif effectList.len == 0: + if isForwardedProc(n): + propagateEffects(tracked, n, n.sym) + else: + addEffect(tracked, createRaise(n)) + addTag(tracked, createTag(n)) + else: + mergeEffects(tracked, effectList.sons[exceptionEffects], n) + mergeTags(tracked, effectList.sons[tagEffects], n) + proc track(tracked: PEffects, n: PNode) = case n.kind of nkRaiseStmt: @@ -259,6 +280,7 @@ proc track(tracked: PEffects, n: PNode) = else: mergeEffects(tracked, effectList.sons[exceptionEffects], n) mergeTags(tracked, effectList.sons[tagEffects], n) + for i in 1 .. <len(n): trackOperand(tracked, n.sons[i]) of nkTryStmt: trackTryStmt(tracked, n) return |