From 2d39a18faa67e3f8c366450cf67405527405a0b0 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 9 May 2013 03:20:55 +0200 Subject: better effects handling for callbacks --- compiler/sempass2.nim | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'compiler') 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 ..