summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-05-09 03:20:55 +0200
committerAraq <rumpf_a@web.de>2013-05-09 03:20:55 +0200
commit2d39a18faa67e3f8c366450cf67405527405a0b0 (patch)
tree95436b06975a41bfb640f0ca0c3d4e69e812c006 /compiler
parent44c4b945eb8e5255aa128dad2553e290eebdd24b (diff)
downloadNim-2d39a18faa67e3f8c366450cf67405527405a0b0.tar.gz
better effects handling for callbacks
Diffstat (limited to 'compiler')
-rw-r--r--compiler/sempass2.nim24
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