Ronan Lamy avatar Ronan Lamy committed 3f3aa47 Merge

hg merge less-stringly-ops

Comments (0)

Files changed (33)

rpython/annotator/annrpython.py

     def consider_op(self, block, opindex):
         op = block.operations[opindex]
         argcells = [self.binding(a) for a in op.args]
-        consider_meth = getattr(self,'consider_op_'+op.opname,
-                                None)
-        if not consider_meth:
-            raise Exception,"unknown op: %r" % op
 
         # let's be careful about avoiding propagated SomeImpossibleValues
         # to enter an op; the latter can result in violations of the
             if isinstance(arg, annmodel.SomeImpossibleValue):
                 raise BlockedInference(self, op, opindex)
         try:
-            resultcell = consider_meth(*argcells)
+            resultcell = op.consider(self, *argcells)
         except annmodel.AnnotatorError as e: # note that UnionError is a subclass
             graph = self.bookkeeper.position_key[0]
             e.source = gather_error(self, graph, block, opindex)

rpython/annotator/argument.py

 """
 Arguments objects.
 """
-from rpython.annotator.model import SomeTuple, SomeObject
+from rpython.annotator.model import SomeTuple
+from rpython.flowspace.argument import CallSpec
 
-# for parsing call arguments
-class RPythonCallsSpace(object):
-    """Pseudo Object Space providing almost no real operation.
-    For the Arguments class: if it really needs other operations, it means
-    that the call pattern is too complex for R-Python.
-    """
-    def newtuple(self, items_s):
-        if len(items_s) == 1 and items_s[0] is Ellipsis:
-            res = SomeObject()   # hack to get a SomeObject as the *arg
-            res.from_ellipsis = True
-            return res
-        else:
-            return SomeTuple(items_s)
-
-    def unpackiterable(self, s_obj, expected_length=None):
-        if isinstance(s_obj, SomeTuple):
-            return list(s_obj.items)
-        if (s_obj.__class__ is SomeObject and
-            getattr(s_obj, 'from_ellipsis', False)):    # see newtuple()
-            return [Ellipsis]
-        raise CallPatternTooComplex("'*' argument must be SomeTuple")
-
-    def bool(self, s_tup):
-        assert isinstance(s_tup, SomeTuple)
-        return bool(s_tup.items)
-
-
-class CallPatternTooComplex(Exception):
-    pass
-
-
-class ArgumentsForTranslation(object):
-    w_starstararg = None
-    def __init__(self, space, args_w, keywords=None, keywords_w=None,
-                 w_stararg=None, w_starstararg=None):
-        self.w_stararg = w_stararg
-        assert w_starstararg is None
-        self.space = space
-        assert isinstance(args_w, list)
-        self.arguments_w = args_w
-        self.keywords = keywords
-        self.keywords_w = keywords_w
-        self.keyword_names_w = None
-
-    def __repr__(self):
-        """ NOT_RPYTHON """
-        name = self.__class__.__name__
-        if not self.keywords:
-            return '%s(%s)' % (name, self.arguments_w,)
-        else:
-            return '%s(%s, %s, %s)' % (name, self.arguments_w,
-                                       self.keywords, self.keywords_w)
-
+class ArgumentsForTranslation(CallSpec):
     @property
     def positional_args(self):
         if self.w_stararg is not None:
-            args_w = self.space.unpackiterable(self.w_stararg)
+            args_w = self.unpackiterable(self.w_stararg)
             return self.arguments_w + args_w
         else:
             return self.arguments_w
 
+    def newtuple(self, items_s):
+        return SomeTuple(items_s)
+
+    def unpackiterable(self, s_obj):
+        assert isinstance(s_obj, SomeTuple)
+        return list(s_obj.items)
+
     def fixedunpack(self, argcount):
         """The simplest argument parsing: get the 'argcount' arguments,
         or raise a real ValueError if the length is wrong."""
 
     def prepend(self, w_firstarg): # used often
         "Return a new Arguments with a new argument inserted first."
-        return ArgumentsForTranslation(self.space, [w_firstarg] + self.arguments_w,
-                                       self.keywords, self.keywords_w, self.w_stararg,
-                                       self.w_starstararg)
+        return ArgumentsForTranslation([w_firstarg] + self.arguments_w,
+                                       self.keywords, self.w_stararg)
 
     def copy(self):
-        return ArgumentsForTranslation(self.space, self.arguments_w,
-                                       self.keywords, self.keywords_w, self.w_stararg,
-                                       self.w_starstararg)
+        return ArgumentsForTranslation(self.arguments_w, self.keywords,
+                self.w_stararg)
 
     def _match_signature(self, scope_w, signature, defaults_w=None):
         """Parse args and kwargs according to the signature of a code object,
 
         args_w = self.positional_args
         num_args = len(args_w)
-        keywords = self.keywords or []
+        keywords = self.keywords
         num_kwds = len(keywords)
 
         # put as many positional input arguments into place as available
                 starargs_w = args_w[co_argcount:]
             else:
                 starargs_w = []
-            scope_w[co_argcount] = self.space.newtuple(starargs_w)
+            scope_w[co_argcount] = self.newtuple(starargs_w)
         elif num_args > co_argcount:
             raise ArgErrCount(num_args, num_kwds, signature, defaults_w, 0)
 
 
         # handle keyword arguments
         num_remainingkwds = 0
-        keywords_w = self.keywords_w
         kwds_mapping = None
         if num_kwds:
             # kwds_mapping maps target indexes in the scope (minus input_argcount)
-            # to positions in the keywords_w list
-            kwds_mapping = [-1] * (co_argcount - input_argcount)
+            # to keyword names
+            kwds_mapping = []
             # match the keywords given at the call site to the argument names
             # the called function takes
             # this function must not take a scope_w, to make the scope not
             # escape
             num_remainingkwds = len(keywords)
-            for i, name in enumerate(keywords):
-                # If name was not encoded as a string, it could be None. In that
-                # case, it's definitely not going to be in the signature.
-                if name is None:
-                    continue
+            for name in keywords:
                 j = signature.find_argname(name)
                 # if j == -1 nothing happens
                 if j < input_argcount:
                     if j >= 0:
                         raise ArgErrMultipleValues(name)
                 else:
-                    kwds_mapping[j - input_argcount] = i # map to the right index
+                    kwds_mapping.append(name)
                     num_remainingkwds -= 1
 
             if num_remainingkwds:
                 if co_argcount == 0:
                     raise ArgErrCount(num_args, num_kwds, signature, defaults_w, 0)
-                raise ArgErrUnknownKwds(self.space, num_remainingkwds, keywords,
-                                        kwds_mapping, self.keyword_names_w)
+                raise ArgErrUnknownKwds(num_remainingkwds, keywords,
+                                        kwds_mapping)
 
         # check for missing arguments and fill them from the kwds,
         # or with defaults, if available
         if input_argcount < co_argcount:
             def_first = co_argcount - (0 if defaults_w is None else len(defaults_w))
             j = 0
-            kwds_index = -1
             for i in range(input_argcount, co_argcount):
-                if kwds_mapping is not None:
-                    kwds_index = kwds_mapping[j]
-                    j += 1
-                    if kwds_index >= 0:
-                        scope_w[i] = keywords_w[kwds_index]
-                        continue
+                name = signature.argnames[i]
+                if name in keywords:
+                    scope_w[i] = keywords[name]
+                    continue
                 defnum = i - def_first
                 if defnum >= 0:
                     scope_w[i] = defaults_w[defnum]
 
     def unpack(self):
         "Return a ([w1,w2...], {'kw':w3...}) pair."
-        kwds_w = dict(zip(self.keywords, self.keywords_w)) if self.keywords else {}
-        return self.positional_args, kwds_w
+        return self.positional_args, self.keywords
 
     def match_signature(self, signature, defaults_w):
         """Parse args and kwargs according to the signature of a code object,
 
     def unmatch_signature(self, signature, data_w):
         """kind of inverse of match_signature"""
-        need_cnt = len(self.positional_args)
-        need_kwds = self.keywords or []
-        space = self.space
         argnames, varargname, kwargname = signature
         assert kwargname is None
         cnt = len(argnames)
-        data_args_w = data_w[:cnt]
+        need_cnt = len(self.positional_args)
         if varargname:
-            data_w_stararg = data_w[cnt]
-            cnt += 1
-        else:
-            data_w_stararg = space.newtuple([])
+            assert len(data_w) == cnt + 1
+            stararg_w = self.unpackiterable(data_w[cnt])
+            if stararg_w:
+                args_w = data_w[:cnt] + stararg_w
+                assert len(args_w) == need_cnt
+                assert not self.keywords
+                return ArgumentsForTranslation(args_w, {})
+            else:
+                data_w = data_w[:-1]
         assert len(data_w) == cnt
+        assert len(data_w) >= need_cnt
+        args_w = data_w[:need_cnt]
+        _kwds_w = dict(zip(argnames[need_cnt:], data_w[need_cnt:]))
+        keywords_w = [_kwds_w[key] for key in self.keywords]
+        return ArgumentsForTranslation(args_w, dict(zip(self.keywords, keywords_w)))
 
-        unfiltered_kwds_w = {}
-        if len(data_args_w) >= need_cnt:
-            args_w = data_args_w[:need_cnt]
-            for argname, w_arg in zip(argnames[need_cnt:], data_args_w[need_cnt:]):
-                unfiltered_kwds_w[argname] = w_arg
-            assert not space.bool(data_w_stararg)
-        else:
-            stararg_w = space.unpackiterable(data_w_stararg)
-            args_w = data_args_w + stararg_w
-            assert len(args_w) == need_cnt
-
-        keywords = []
-        keywords_w = []
-        for key in need_kwds:
-            keywords.append(key)
-            keywords_w.append(unfiltered_kwds_w[key])
-
-        return ArgumentsForTranslation(self.space, args_w, keywords, keywords_w)
-
-    @staticmethod
-    def fromshape(space, (shape_cnt, shape_keys, shape_star, shape_stst), data_w):
+    @classmethod
+    def fromshape(cls, (shape_cnt, shape_keys, shape_star), data_w):
         args_w = data_w[:shape_cnt]
         p = end_keys = shape_cnt + len(shape_keys)
         if shape_star:
             p += 1
         else:
             w_star = None
-        if shape_stst:
-            w_starstar = data_w[p]
-            p += 1
-        else:
-            w_starstar = None
-        return ArgumentsForTranslation(space, args_w, list(shape_keys),
-                                       data_w[shape_cnt:end_keys], w_star,
-                                       w_starstar)
+        return cls(args_w, dict(zip(shape_keys, data_w[shape_cnt:end_keys])),
+                w_star)
 
-    def flatten(self):
-        """ Argument <-> list of w_objects together with "shape" information """
-        shape_cnt, shape_keys, shape_star, shape_stst = self._rawshape()
-        data_w = self.arguments_w + [self.keywords_w[self.keywords.index(key)]
-                                         for key in shape_keys]
-        if shape_star:
-            data_w.append(self.w_stararg)
-        if shape_stst:
-            data_w.append(self.w_starstararg)
-        return (shape_cnt, shape_keys, shape_star, shape_stst), data_w
 
-    def _rawshape(self, nextra=0):
-        shape_cnt = len(self.arguments_w) + nextra       # Number of positional args
-        if self.keywords:
-            shape_keys = self.keywords[:]                # List of keywords (strings)
-            shape_keys.sort()
-        else:
-            shape_keys = []
-        shape_star = self.w_stararg is not None   # Flag: presence of *arg
-        shape_stst = self.w_starstararg is not None # Flag: presence of **kwds
-        return shape_cnt, tuple(shape_keys), shape_star, shape_stst # shape_keys are sorted
-
-
-def rawshape(args, nextra=0):
-    return args._rawshape(nextra)
+def rawshape(args):
+    return args._rawshape()
 
 
 #
 
 
 class ArgErrUnknownKwds(ArgErr):
-    def __init__(self, space, num_remainingkwds, keywords, kwds_mapping,
-                 keyword_names_w):
+    def __init__(self, num_remainingkwds, keywords, kwds_mapping):
         name = ''
         self.num_kwds = num_remainingkwds
         if num_remainingkwds == 1:
-            for i in range(len(keywords)):
-                if i not in kwds_mapping:
-                    name = keywords[i]
-                    if name is None:
-                        # We'll assume it's unicode. Encode it.
-                        # Careful, I *think* it should not be possible to
-                        # get an IndexError here but you never know.
-                        try:
-                            if keyword_names_w is None:
-                                raise IndexError
-                            # note: negative-based indexing from the end
-                            w_name = keyword_names_w[i - len(keywords)]
-                        except IndexError:
-                            name = '?'
-                        else:
-                            w_enc = space.wrap(space.sys.defaultencoding)
-                            w_err = space.wrap("replace")
-                            w_name = space.call_method(w_name, "encode", w_enc,
-                                                       w_err)
-                            name = space.str_w(w_name)
+            for name in keywords:
+                if name not in kwds_mapping:
                     break
         self.kwd_name = name
 

rpython/annotator/binaryop.py

 import py
 import operator
 from rpython.tool.pairtype import pair, pairtype
-from rpython.annotator.model import SomeObject, SomeInteger, SomeBool, s_Bool
-from rpython.annotator.model import SomeString, SomeChar, SomeList, SomeDict,\
-     SomeOrderedDict
-from rpython.annotator.model import SomeUnicodeCodePoint, SomeUnicodeString
-from rpython.annotator.model import SomeTuple, SomeImpossibleValue, s_ImpossibleValue
-from rpython.annotator.model import SomeInstance, SomeBuiltin, SomeIterator
-from rpython.annotator.model import SomePBC, SomeFloat, s_None, SomeByteArray
-from rpython.annotator.model import SomeWeakRef
-from rpython.annotator.model import SomeAddress, SomeTypedAddressAccess
-from rpython.annotator.model import SomeSingleFloat, SomeLongFloat, SomeType
-from rpython.annotator.model import unionof, UnionError, missing_operation
-from rpython.annotator.model import read_can_only_throw
-from rpython.annotator.model import add_knowntypedata, merge_knowntypedata
+from rpython.annotator.model import (
+    SomeObject, SomeInteger, SomeBool, s_Bool, SomeString, SomeChar, SomeList,
+    SomeDict, SomeOrderedDict, SomeUnicodeCodePoint, SomeUnicodeString,
+    SomeTuple, SomeImpossibleValue, s_ImpossibleValue, SomeInstance,
+    SomeBuiltin, SomeIterator, SomePBC, SomeFloat, s_None, SomeByteArray,
+    SomeWeakRef, SomeAddress, SomeTypedAddressAccess, SomeSingleFloat,
+    SomeLongFloat, SomeType, SomeConstantType, unionof, UnionError,
+    missing_operation, read_can_only_throw, add_knowntypedata,
+    merge_knowntypedata,)
 from rpython.annotator.bookkeeper import getbookkeeper
 from rpython.flowspace.model import Variable, Constant
 from rpython.rlib import rarithmetic
     getitem_key = getitem_idx_key
 
 
-class __extend__(pairtype(SomeType, SomeType)):
+class __extend__(pairtype(SomeType, SomeType),
+                 pairtype(SomeType, SomeConstantType),
+                 pairtype(SomeConstantType, SomeType),):
 
     def union((obj1, obj2)):
         result = SomeType()

rpython/annotator/bookkeeper.py

     SomeBuiltin, SomePBC, SomeInteger, TLS, SomeAddress, SomeUnicodeCodePoint,
     s_None, s_ImpossibleValue, SomeLLADTMeth, SomeBool, SomeTuple,
     SomeImpossibleValue, SomeUnicodeString, SomeList, HarmlesslyBlocked,
-    SomeWeakRef, lltype_to_annotation, SomeType, SomeByteArray)
+    SomeWeakRef, lltype_to_annotation, SomeType, SomeByteArray, SomeConstantType)
 from rpython.annotator.classdef import InstanceSource, ClassDef
 from rpython.annotator.listdef import ListDef, ListItem
 from rpython.annotator.dictdef import DictDef
 from rpython.annotator import description
 from rpython.annotator.signature import annotationoftype
-from rpython.annotator.argument import ArgumentsForTranslation, RPythonCallsSpace
+from rpython.annotator.argument import ArgumentsForTranslation
 from rpython.rlib.objectmodel import r_dict, Symbolic
 from rpython.tool.algo.unionfind import UnionFind
 from rpython.rtyper.lltypesystem import lltype, llmemory
         elif isinstance(x, llmemory.fakeaddress):
             result = SomeAddress()
         elif tp is type:
-            if (x is type(None) or      # add cases here if needed
-                x.__module__ == 'rpython.rtyper.lltypesystem.lltype'):
-                result = SomeType()
-            else:
-                result = SomePBC([self.getdesc(x)])
+            result = SomeConstantType(x, self)
         elif callable(x):
             if hasattr(x, 'im_self') and hasattr(x, 'im_func'):
                 # on top of PyPy, for cases like 'l.append' where 'l' is a
         return op
 
     def build_args(self, op, args_s):
-        space = RPythonCallsSpace()
         if op == "simple_call":
-            return ArgumentsForTranslation(space, list(args_s))
+            return ArgumentsForTranslation(list(args_s))
         elif op == "call_args":
             return ArgumentsForTranslation.fromshape(
-                    space, args_s[0].const, # shape
+                    args_s[0].const, # shape
                     list(args_s[1:]))
 
     def ondegenerated(self, what, s_value, where=None, called_from_graph=None):

rpython/annotator/builtin.py

     r_func, nimplicitarg = s_repr.const.get_r_implfunc()
 
     nbargs = len(args_s) + nimplicitarg
-    s_sigs = r_func.get_s_signatures((nbargs, (), False, False))
+    s_sigs = r_func.get_s_signatures((nbargs, (), False))
     if len(s_sigs) != 1:
         raise TyperError("cannot hlinvoke callable %r with not uniform"
                          "annotations: %r" % (s_repr.const,

rpython/annotator/description.py

                                              self.name,
                                              flags)
 
+    @staticmethod
     def consider_call_site(bookkeeper, family, descs, args, s_result, op):
-        shape = rawshape(args, nextra=1)     # account for the extra 'self'
+        cnt, keys, star = rawshape(args)
+        shape = cnt + 1, keys, star  # account for the extra 'self'
         row = FunctionDesc.row_to_consider(descs, args, op)
         family.calltable_add_row(shape, row)
-    consider_call_site = staticmethod(consider_call_site)
 
     def rowkey(self):
         # we are computing call families and call tables that always contain
         args = args.prepend(s_self)
         return self.funcdesc.pycall(schedule, args, s_previous_result, op)
 
+    @staticmethod
     def consider_call_site(bookkeeper, family, descs, args, s_result, op):
-        shape = rawshape(args, nextra=1)    # account for the extra 'self'
+        cnt, keys, star = rawshape(args)
+        shape = cnt + 1, keys, star  # account for the extra 'self'
         row = FunctionDesc.row_to_consider(descs, args, op)
         family.calltable_add_row(shape, row)
-    consider_call_site = staticmethod(consider_call_site)
 
     def rowkey(self):
         return self.funcdesc

rpython/annotator/model.py

         else:
             return kt.__name__
 
+class SomeConstantType(SomePBC):
+    can_be_None = False
+    subset_of = None
+    def __init__(self, x, bk):
+        self.descriptions = set([bk.getdesc(x)])
+        self.knowntype = type(x)
+        self.const = x
+
 
 class SomeBuiltin(SomeObject):
     "Stands for a built-in function or method with special-cased analysis."

rpython/annotator/policy.py

 # base annotation policy for specialization
 from rpython.annotator.specialize import default_specialize as default
-from rpython.annotator.specialize import specialize_argvalue, specialize_argtype, specialize_arglistitemtype, specialize_arg_or_var
-from rpython.annotator.specialize import memo, specialize_call_location
+from rpython.annotator.specialize import (
+    specialize_argvalue, specialize_argtype, specialize_arglistitemtype,
+    specialize_arg_or_var, memo, specialize_call_location)
 
 
-class BasicAnnotatorPolicy(object):
+class AnnotatorPolicy(object):
+    """
+    Possibly subclass and pass an instance to the annotator to control
+    special-casing during annotation
+    """
 
     def event(pol, bookkeeper, what, *args):
         pass
 
-    def get_specializer(pol, tag):
-        return pol.no_specialization
-
-    def no_specialization(pol, funcdesc, args_s):
-        return funcdesc.cachedgraph(None)
-
-    def no_more_blocks_to_annotate(pol, annotator):
-        # hint to all pending specializers that we are done
-        for callback in annotator.bookkeeper.pending_specializations:
-            callback()
-        del annotator.bookkeeper.pending_specializations[:]
-
-class AnnotatorPolicy(BasicAnnotatorPolicy):
-    """
-    Possibly subclass and pass an instance to the annotator to control special casing during annotation
-    """
-
     def get_specializer(pol, directive):
         if directive is None:
             return pol.default_specialize
     def specialize__ll_and_arg(pol, *args):
         from rpython.rtyper.annlowlevel import LowLevelAnnotatorPolicy
         return LowLevelAnnotatorPolicy.specialize__ll_and_arg(*args)
+
+    def no_more_blocks_to_annotate(pol, annotator):
+        # hint to all pending specializers that we are done
+        for callback in annotator.bookkeeper.pending_specializations:
+            callback()
+        del annotator.bookkeeper.pending_specializations[:]

rpython/annotator/specialize.py

 from rpython.tool.algo.unionfind import UnionFind
 from rpython.flowspace.model import Block, Link, Variable, SpaceOperation
 from rpython.flowspace.model import checkgraph
+from rpython.flowspace.operation import op
 from rpython.annotator import model as annmodel
 from rpython.flowspace.argument import Signature
 
             argscopy = [Variable(v) for v in graph.getargs()]
             starargs = [Variable('stararg%d'%i) for i in range(nb_extra_args)]
             newstartblock = Block(argscopy[:-1] + starargs)
-            newtup = SpaceOperation('newtuple', starargs, argscopy[-1])
+            newtup = op.newtuple(*starargs)
+            newtup.result = argscopy[-1]
             newstartblock.operations.append(newtup)
             newstartblock.closeblock(Link(argscopy, graph.startblock))
             graph.startblock = newstartblock

rpython/annotator/test/test_annrpython.py

 from rpython.rlib.rarithmetic import r_singlefloat
 from rpython.rlib import objectmodel
 from rpython.flowspace.objspace import build_flow, FlowingError
+from rpython.flowspace.operation import op
 
 from rpython.translator.test import snippet
 
             return x+1
         """
         x = Variable("x")
-        result = Variable("result")
-        op = SpaceOperation("add", [x, Constant(1)], result)
+        oper = op.add(x, Constant(1))
         block = Block([x])
         fun = FunctionGraph("f", block)
-        block.operations.append(op)
-        block.closeblock(Link([result], fun.returnblock))
+        block.operations.append(oper)
+        block.closeblock(Link([oper.result], fun.returnblock))
         a = self.RPythonAnnotator()
         a.addpendingblock(fun, fun.startblock, [annmodel.SomeInteger()])
         a.complete()
         """
         i1 = Variable("i1")
         i2 = Variable("i2")
-        i3 = Variable("i3")
-        conditionres = Variable("conditionres")
-        conditionop = SpaceOperation("gt", [i1, Constant(0)], conditionres)
-        decop = SpaceOperation("add", [i2, Constant(-1)], i3)
+        conditionop = op.gt(i1, Constant(0))
+        decop = op.add(i2, Constant(-1))
         headerblock = Block([i1])
         whileblock = Block([i2])
 
         fun = FunctionGraph("f", headerblock)
         headerblock.operations.append(conditionop)
-        headerblock.exitswitch = conditionres
+        headerblock.exitswitch = conditionop.result
         headerblock.closeblock(Link([i1], fun.returnblock, False),
                                Link([i1], whileblock, True))
         whileblock.operations.append(decop)
-        whileblock.closeblock(Link([i3], headerblock))
+        whileblock.closeblock(Link([decop.result], headerblock))
 
         a = self.RPythonAnnotator()
         a.addpendingblock(fun, fun.startblock, [annmodel.SomeInteger()])
         i1 = Variable("i1")
         i2 = Variable("i2")
         i3 = Variable("i3")
-        i4 = Variable("i4")
         sum2 = Variable("sum2")
         sum3 = Variable("sum3")
-        sum4 = Variable("sum4")
-
-        conditionres = Variable("conditionres")
-        conditionop = SpaceOperation("gt", [i2, Constant(0)], conditionres)
-        decop = SpaceOperation("add", [i3, Constant(-1)], i4)
-        addop = SpaceOperation("add", [i3, sum3], sum4)
+
+        conditionop = op.gt(i2, Constant(0))
+        decop = op.add(i3, Constant(-1))
+        addop = op.add(i3, sum3)
         startblock = Block([i1])
         headerblock = Block([i2, sum2])
         whileblock = Block([i3, sum3])
         fun = FunctionGraph("f", startblock)
         startblock.closeblock(Link([i1, Constant(0)], headerblock))
         headerblock.operations.append(conditionop)
-        headerblock.exitswitch = conditionres
+        headerblock.exitswitch = conditionop.result
         headerblock.closeblock(Link([sum2], fun.returnblock, False),
                                Link([i2, sum2], whileblock, True))
         whileblock.operations.append(addop)
         whileblock.operations.append(decop)
-        whileblock.closeblock(Link([i4, sum4], headerblock))
+        whileblock.closeblock(Link([decop.result, addop.result], headerblock))
 
         a = self.RPythonAnnotator()
         a.addpendingblock(fun, fun.startblock, [annmodel.SomeInteger()])
         gf2 = graphof(a, f2)
         gf3 = graphof(a, f3)
 
-        assert fam1.calltables == {(2, (), False, False): [{fdesc1: gf1}], (1, (), False, False): [{fdesc1: gf1}]}
-        assert fam2.calltables == {(1, (), False, False): [{fdesc2: gf2, fdesc3: gf3}]}
+        assert fam1.calltables == {(2, (), False): [{fdesc1: gf1}],
+                                   (1, (), False): [{fdesc1: gf1}]}
+        assert fam2.calltables == {(1, (), False): [{fdesc2: gf2, fdesc3: gf3}]}
 
     def test_pbc_call_ins(self):
         class A(object):
         gfA_m = graphof(a, A.m.im_func)
         gfC_m = graphof(a, C.m.im_func)
 
-        assert famB_n.calltables == {(1, (), False, False): [{mdescB_n.funcdesc: gfB_n}] }
-        assert famA_m.calltables == {(1, (), False, False): [{mdescA_m.funcdesc: gfA_m, mdescC_m.funcdesc: gfC_m }] }
+        assert famB_n.calltables == {(1, (), False): [{mdescB_n.funcdesc: gfB_n}] }
+        assert famA_m.calltables == {(1, (), False): [{mdescA_m.funcdesc: gfA_m, mdescC_m.funcdesc: gfC_m }] }
 
         mdescCinit = getmdesc(C().__init__)
         famCinit = mdescCinit.getcallfamily()
         gfCinit = graphof(a, C.__init__.im_func)
 
-        assert famCinit.calltables == {(1, (), False, False): [{mdescCinit.funcdesc: gfCinit}] }
+        assert famCinit.calltables == {(1, (), False): [{mdescCinit.funcdesc: gfCinit}] }
 
     def test_isinstance_usigned(self):
         def f(x):
 
         someint = annmodel.SomeInteger()
 
-        assert (fdesc.get_s_signatures((2,(),False,False))
+        assert (fdesc.get_s_signatures((2, (), False))
                 == [([someint,someint],someint)])
 
     def test_emulated_pbc_call_callback(self):

rpython/annotator/test/test_argument.py

 # -*- coding: utf-8 -*-
 import py
 from rpython.annotator.argument import ArgumentsForTranslation, rawshape
-from rpython.flowspace.argument import Signature
+from rpython.flowspace.argument import Signature, CallSpec
 
-class DummySpace(object):
+class MockArgs(ArgumentsForTranslation):
     def newtuple(self, items):
         return tuple(items)
 
-    def bool(self, obj):
-        return bool(obj)
-
     def unpackiterable(self, it):
         return list(it)
 
 
-def make_arguments_for_translation(space, args_w, keywords_w={},
-                                   w_stararg=None, w_starstararg=None):
-    return ArgumentsForTranslation(space, args_w, keywords_w.keys(),
-                                   keywords_w.values(), w_stararg,
-                                   w_starstararg)
-
 class TestArgumentsForTranslation(object):
 
     def test_prepend(self):
-        space = DummySpace()
-        args = ArgumentsForTranslation(space, ["0"])
+        args = MockArgs(["0"])
         args1 = args.prepend("thingy")
         assert args1 is not args
         assert args1.arguments_w == ["thingy", "0"]
-        assert args1.keywords is args.keywords
-        assert args1.keywords_w is args.keywords_w
+        assert args1.keywords == args.keywords
 
     def test_fixedunpacked(self):
-        space = DummySpace()
-
-        args = ArgumentsForTranslation(space, [], ["k"], [1])
+        args = MockArgs([], {"k": 1})
         py.test.raises(ValueError, args.fixedunpack, 1)
 
-        args = ArgumentsForTranslation(space, ["a", "b"])
+        args = MockArgs(["a", "b"])
         py.test.raises(ValueError, args.fixedunpack, 0)
         py.test.raises(ValueError, args.fixedunpack, 1)
         py.test.raises(ValueError, args.fixedunpack, 3)
         assert args.fixedunpack(2) == ['a', 'b']
 
     def test_unmatch_signature(self):
-        space = DummySpace()
-        args = make_arguments_for_translation(space, [1,2,3])
+        args = MockArgs([1, 2, 3])
         sig = Signature(['a', 'b', 'c'], None, None)
         data = args.match_signature(sig, [])
         new_args = args.unmatch_signature(sig, data)
         assert args.unpack() == new_args.unpack()
 
-        args = make_arguments_for_translation(space, [1])
+        args = MockArgs([1])
         sig = Signature(['a', 'b', 'c'], None, None)
         data = args.match_signature(sig, [2, 3])
         new_args = args.unmatch_signature(sig, data)
         assert args.unpack() == new_args.unpack()
 
-        args = make_arguments_for_translation(space, [1,2,3,4,5])
+        args = MockArgs([1, 2, 3, 4, 5])
         sig = Signature(['a', 'b', 'c'], 'r', None)
         data = args.match_signature(sig, [])
         new_args = args.unmatch_signature(sig, data)
         assert args.unpack() == new_args.unpack()
 
-        args = make_arguments_for_translation(space, [1], {'c': 3, 'b': 2})
+        args = MockArgs([1], {'c': 3, 'b': 2})
         sig = Signature(['a', 'b', 'c'], None, None)
         data = args.match_signature(sig, [])
         new_args = args.unmatch_signature(sig, data)
         assert args.unpack() == new_args.unpack()
 
-        args = make_arguments_for_translation(space, [1], {'c': 5})
+        args = MockArgs([1], {'c': 5})
         sig = Signature(['a', 'b', 'c'], None, None)
         data = args.match_signature(sig, [2, 3])
         new_args = args.unmatch_signature(sig, data)
         assert args.unpack() == new_args.unpack()
 
     def test_rawshape(self):
-        space = DummySpace()
-        args = make_arguments_for_translation(space, [1,2,3])
-        assert rawshape(args) == (3, (), False, False)
+        args = MockArgs([1, 2, 3])
+        assert rawshape(args) == (3, (), False)
 
-        args = make_arguments_for_translation(space, [1])
-        assert rawshape(args, 2) == (3, (), False, False)
+        args = MockArgs([1, 2, 3, 4, 5])
+        assert rawshape(args) == (5, (), False)
 
-        args = make_arguments_for_translation(space, [1,2,3,4,5])
-        assert rawshape(args) == (5, (), False, False)
+        args = MockArgs([1], {'c': 3, 'b': 2})
+        assert rawshape(args) == (1, ('b', 'c'), False)
 
-        args = make_arguments_for_translation(space, [1], {'c': 3, 'b': 2})
-        assert rawshape(args) == (1, ('b', 'c'), False, False)
+        args = MockArgs([1], {'c': 5})
+        assert rawshape(args) == (1, ('c', ), False)
 
-        args = make_arguments_for_translation(space, [1], {'c': 5})
-        assert rawshape(args) == (1, ('c', ), False, False)
+        args = MockArgs([1], {'c': 5, 'd': 7})
+        assert rawshape(args) == (1, ('c', 'd'), False)
 
-        args = make_arguments_for_translation(space, [1], {'c': 5, 'd': 7})
-        assert rawshape(args) == (1, ('c', 'd'), False, False)
-
-        args = make_arguments_for_translation(space, [1,2,3,4,5], {'e': 5, 'd': 7})
-        assert rawshape(args) == (5, ('d', 'e'), False, False)
-
-
-    def test_flatten(self):
-        space = DummySpace()
-        args = make_arguments_for_translation(space, [1,2,3])
-        assert args.flatten() == ((3, (), False, False), [1, 2, 3])
-
-        args = make_arguments_for_translation(space, [1])
-        assert args.flatten() == ((1, (), False, False), [1])
-
-        args = make_arguments_for_translation(space, [1,2,3,4,5])
-        assert args.flatten() == ((5, (), False, False), [1,2,3,4,5])
-
-        args = make_arguments_for_translation(space, [1], {'c': 3, 'b': 2})
-        assert args.flatten() == ((1, ('b', 'c'), False, False), [1, 2, 3])
-
-        args = make_arguments_for_translation(space, [1], {'c': 5})
-        assert args.flatten() == ((1, ('c', ), False, False), [1, 5])
-
-        args = make_arguments_for_translation(space, [1], {'c': 5, 'd': 7})
-        assert args.flatten() == ((1, ('c', 'd'), False, False), [1, 5, 7])
-
-        args = make_arguments_for_translation(space, [1,2,3,4,5], {'e': 5, 'd': 7})
-        assert args.flatten() == ((5, ('d', 'e'), False, False), [1, 2, 3, 4, 5, 7, 5])
+        args = MockArgs([1, 2, 3, 4, 5], {'e': 5, 'd': 7})
+        assert rawshape(args) == (5, ('d', 'e'), False)
 
     def test_stararg_flowspace_variable(self):
-        space = DummySpace()
         var = object()
-        shape = ((2, ('g', ), True, False), [1, 2, 9, var])
-        args = make_arguments_for_translation(space, [1,2], {'g': 9},
-                                       w_stararg=var)
+        shape = ((2, ('g', ), True), [1, 2, 9, var])
+        args = MockArgs([1, 2], {'g': 9}, w_stararg=var)
         assert args.flatten() == shape
 
-        args = ArgumentsForTranslation.fromshape(space, *shape)
+        args = MockArgs.fromshape(*shape)
         assert args.flatten() == shape
 
-
     def test_fromshape(self):
-        space = DummySpace()
-        shape = ((3, (), False, False), [1, 2, 3])
-        args = ArgumentsForTranslation.fromshape(space, *shape)
+        shape = ((3, (), False), [1, 2, 3])
+        args = MockArgs.fromshape(*shape)
         assert args.flatten() == shape
 
-        shape = ((1, (), False, False), [1])
-        args = ArgumentsForTranslation.fromshape(space, *shape)
+        shape = ((1, (), False), [1])
+        args = MockArgs.fromshape(*shape)
         assert args.flatten() == shape
 
-        shape = ((5, (), False, False), [1,2,3,4,5])
-        args = ArgumentsForTranslation.fromshape(space, *shape)
+        shape = ((5, (), False), [1, 2, 3, 4, 5])
+        args = MockArgs.fromshape(*shape)
         assert args.flatten() == shape
 
-        shape = ((1, ('b', 'c'), False, False), [1, 2, 3])
-        args = ArgumentsForTranslation.fromshape(space, *shape)
+        shape = ((1, ('b', 'c'), False), [1, 2, 3])
+        args = MockArgs.fromshape(*shape)
         assert args.flatten() == shape
 
-        shape = ((1, ('c', ), False, False), [1, 5])
-        args = ArgumentsForTranslation.fromshape(space, *shape)
+        shape = ((1, ('c', ), False), [1, 5])
+        args = MockArgs.fromshape(*shape)
         assert args.flatten() == shape
 
-        shape = ((1, ('c', 'd'), False, False), [1, 5, 7])
-        args = ArgumentsForTranslation.fromshape(space, *shape)
+        shape = ((1, ('c', 'd'), False), [1, 5, 7])
+        args = MockArgs.fromshape(*shape)
         assert args.flatten() == shape
 
-        shape = ((5, ('d', 'e'), False, False), [1, 2, 3, 4, 5, 7, 5])
-        args = ArgumentsForTranslation.fromshape(space, *shape)
+        shape = ((5, ('d', 'e'), False), [1, 2, 3, 4, 5, 7, 5])
+        args = MockArgs.fromshape(*shape)
         assert args.flatten() == shape

rpython/annotator/unaryop.py

 
 class __extend__(SomeObject):
 
-    def type(obj, *moreargs):
+    def type(self, *moreargs):
         if moreargs:
             raise Exception('type() called with more than one argument')
         r = SomeType()
         bk = getbookkeeper()
-        op = bk._find_current_op(opname="type", arity=1, pos=0, s_type=obj)
+        op = bk._find_current_op(opname="type", arity=1, pos=0, s_type=self)
         r.is_type_of = [op.args[0]]
         return r
 
-    def issubtype(obj, s_cls):
-        if hasattr(obj, 'is_type_of'):
-            vars = obj.is_type_of
+    def issubtype(self, s_cls):
+        if hasattr(self, 'is_type_of'):
+            vars = self.is_type_of
             annotator = getbookkeeper().annotator
             return builtin.builtin_isinstance(annotator.binding(vars[0]),
                                               s_cls, vars)
-        if obj.is_constant() and s_cls.is_constant():
-            return immutablevalue(issubclass(obj.const, s_cls.const))
+        if self.is_constant() and s_cls.is_constant():
+            return immutablevalue(issubclass(self.const, s_cls.const))
         return s_Bool
 
-    def len(obj):
+    def len(self):
         return SomeInteger(nonneg=True)
 
-    def bool_behavior(obj, s):
-        if obj.is_immutable_constant():
-            s.const = bool(obj.const)
+    def bool_behavior(self, s):
+        if self.is_immutable_constant():
+            s.const = bool(self.const)
         else:
-            s_len = obj.len()
+            s_len = self.len()
             if s_len.is_immutable_constant():
                 s.const = s_len.const > 0
 
         r.set_knowntypedata(knowntypedata)
         return r
 
-    def hash(obj):
+    def hash(self):
         raise AnnotatorError("cannot use hash() in RPython")
 
-    def str(obj):
-        getbookkeeper().count('str', obj)
+    def str(self):
+        getbookkeeper().count('str', self)
         return SomeString()
 
-    def unicode(obj):
-        getbookkeeper().count('unicode', obj)
+    def unicode(self):
+        getbookkeeper().count('unicode', self)
         return SomeUnicodeString()
 
-    def repr(obj):
-        getbookkeeper().count('repr', obj)
+    def repr(self):
+        getbookkeeper().count('repr', self)
         return SomeString()
 
-    def hex(obj):
-        getbookkeeper().count('hex', obj)
+    def hex(self):
+        getbookkeeper().count('hex', self)
         return SomeString()
 
-    def oct(obj):
-        getbookkeeper().count('oct', obj)
+    def oct(self):
+        getbookkeeper().count('oct', self)
         return SomeString()
 
-    def id(obj):
+    def id(self):
         raise Exception("cannot use id() in RPython; "
                         "see objectmodel.compute_xxx()")
 
-    def int(obj):
+    def int(self):
         return SomeInteger()
 
-    def float(obj):
+    def float(self):
         return SomeFloat()
 
-    def delattr(obj, s_attr):
-        if obj.__class__ != SomeObject or obj.knowntype != object:
+    def delattr(self, s_attr):
+        if self.__class__ != SomeObject or self.knowntype != object:
             getbookkeeper().warning(
                 ("delattr on potentally non-SomeObjects is not RPythonic: delattr(%r,%r)" %
-                 (obj, s_attr)))
+                 (self, s_attr)))
 
-    def find_method(obj, name):
+    def find_method(self, name):
         "Look for a special-case implementation for the named method."
         try:
-            analyser = getattr(obj.__class__, 'method_' + name)
+            analyser = getattr(self.__class__, 'method_' + name)
         except AttributeError:
             return None
         else:
-            return SomeBuiltin(analyser, obj, name)
+            return SomeBuiltin(analyser, self, name)
 
-    def getattr(obj, s_attr):
+    def getattr(self, s_attr):
         # get a SomeBuiltin if the SomeObject has
         # a corresponding method to handle it
         if not s_attr.is_constant() or not isinstance(s_attr.const, str):
             raise AnnotatorError("getattr(%r, %r) has non-constant argument"
-                                 % (obj, s_attr))
+                                 % (self, s_attr))
         attr = s_attr.const
-        s_method = obj.find_method(attr)
+        s_method = self.find_method(attr)
         if s_method is not None:
             return s_method
         # if the SomeObject is itself a constant, allow reading its attrs
-        if obj.is_immutable_constant() and hasattr(obj.const, attr):
-            return immutablevalue(getattr(obj.const, attr))
-        raise AnnotatorError("Cannot find attribute %r on %r" % (attr, obj))
+        if self.is_immutable_constant() and hasattr(self.const, attr):
+            return immutablevalue(getattr(self.const, attr))
+        raise AnnotatorError("Cannot find attribute %r on %r" % (attr, self))
     getattr.can_only_throw = []
 
-    def bind_callables_under(obj, classdef, name):
-        return obj   # default unbound __get__ implementation
+    def bind_callables_under(self, classdef, name):
+        return self   # default unbound __get__ implementation
 
-    def simple_call(obj, *args_s):
-        return obj.call(getbookkeeper().build_args("simple_call", args_s))
+    def simple_call(self, *args_s):
+        return self.call(getbookkeeper().build_args("simple_call", args_s))
 
-    def call_args(obj, *args_s):
-        return obj.call(getbookkeeper().build_args("call_args", args_s))
+    def call_args(self, *args_s):
+        return self.call(getbookkeeper().build_args("call_args", args_s))
 
-    def call(obj, args, implicit_init=False):
+    def call(self, args, implicit_init=False):
         raise AnnotatorError("Cannot prove that the object is callable")
 
-    def op_contains(obj, s_element):
+    def op_contains(self, s_element):
         return s_Bool
     op_contains.can_only_throw = []
 
 
 class __extend__(SomeFloat):
 
-    def pos(flt):
-        return flt
+    def pos(self):
+        return self
 
-    def neg(flt):
+    def neg(self):
         return SomeFloat()
 
     abs = neg
 
 class __extend__(SomeTuple):
 
-    def len(tup):
-        return immutablevalue(len(tup.items))
+    def len(self):
+        return immutablevalue(len(self.items))
 
-    def iter(tup):
-        getbookkeeper().count("tuple_iter", tup)
-        return SomeIterator(tup)
+    def iter(self):
+        getbookkeeper().count("tuple_iter", self)
+        return SomeIterator(self)
     iter.can_only_throw = []
 
-    def getanyitem(tup):
-        return unionof(*tup.items)
+    def getanyitem(self):
+        return unionof(*self.items)
 
-    def getslice(tup, s_start, s_stop):
+    def getslice(self, s_start, s_stop):
         assert s_start.is_immutable_constant(),"tuple slicing: needs constants"
         assert s_stop.is_immutable_constant(), "tuple slicing: needs constants"
-        items = tup.items[s_start.const:s_stop.const]
+        items = self.items[s_start.const:s_stop.const]
         return SomeTuple(items)
 
 
 class __extend__(SomeList):
 
-    def method_append(lst, s_value):
-        lst.listdef.resize()
-        lst.listdef.generalize(s_value)
+    def method_append(self, s_value):
+        self.listdef.resize()
+        self.listdef.generalize(s_value)
 
-    def method_extend(lst, s_iterable):
-        lst.listdef.resize()
+    def method_extend(self, s_iterable):
+        self.listdef.resize()
         if isinstance(s_iterable, SomeList):   # unify the two lists
-            lst.listdef.agree(s_iterable.listdef)
+            self.listdef.agree(s_iterable.listdef)
         else:
             s_iter = s_iterable.iter()
-            lst.method_append(s_iter.next())
+            self.method_append(s_iter.next())
 
-    def method_reverse(lst):
-        lst.listdef.mutate()
+    def method_reverse(self):
+        self.listdef.mutate()
 
-    def method_insert(lst, s_index, s_value):
-        lst.method_append(s_value)
+    def method_insert(self, s_index, s_value):
+        self.method_append(s_value)
 
-    def method_remove(lst, s_value):
-        lst.listdef.resize()
-        lst.listdef.generalize(s_value)
+    def method_remove(self, s_value):
+        self.listdef.resize()
+        self.listdef.generalize(s_value)
 
-    def method_pop(lst, s_index=None):
-        lst.listdef.resize()
-        return lst.listdef.read_item()
+    def method_pop(self, s_index=None):
+        self.listdef.resize()
+        return self.listdef.read_item()
     method_pop.can_only_throw = [IndexError]
 
-    def method_index(lst, s_value):
+    def method_index(self, s_value):
         getbookkeeper().count("list_index")
-        lst.listdef.generalize(s_value)
+        self.listdef.generalize(s_value)
         return SomeInteger(nonneg=True)
 
-    def len(lst):
-        s_item = lst.listdef.read_item()
+    def len(self):
+        s_item = self.listdef.read_item()
         if isinstance(s_item, SomeImpossibleValue):
             return immutablevalue(0)
-        return SomeObject.len(lst)
+        return SomeObject.len(self)
 
-    def iter(lst):
-        return SomeIterator(lst)
+    def iter(self):
+        return SomeIterator(self)
     iter.can_only_throw = []
 
-    def getanyitem(lst):
-        return lst.listdef.read_item()
+    def getanyitem(self):
+        return self.listdef.read_item()
 
-    def op_contains(lst, s_element):
-        lst.listdef.generalize(s_element)
+    def op_contains(self, s_element):
+        self.listdef.generalize(s_element)
         return s_Bool
     op_contains.can_only_throw = []
 
-    def hint(lst, *args_s):
+    def hint(self, *args_s):
         hints = args_s[-1].const
         if 'maxlength' in hints:
             # only for iteration over lists or dicts at the moment,
             # not over an iterator object (because it has no known length)
             s_iterable = args_s[0]
             if isinstance(s_iterable, (SomeList, SomeDict)):
-                lst = SomeList(lst.listdef) # create a fresh copy
-                lst.listdef.resize()
-                lst.listdef.listitem.hint_maxlength = True
+                self = SomeList(self.listdef) # create a fresh copy
+                self.listdef.resize()
+                self.listdef.listitem.hint_maxlength = True
         elif 'fence' in hints:
-            lst = lst.listdef.offspring()
-        return lst
+            self = self.listdef.offspring()
+        return self
 
-    def getslice(lst, s_start, s_stop):
+    def getslice(self, s_start, s_stop):
         check_negative_slice(s_start, s_stop)
-        return lst.listdef.offspring()
+        return self.listdef.offspring()
 
-    def setslice(lst, s_start, s_stop, s_iterable):
+    def setslice(self, s_start, s_stop, s_iterable):
         check_negative_slice(s_start, s_stop)
         if not isinstance(s_iterable, SomeList):
             raise Exception("list[start:stop] = x: x must be a list")
-        lst.listdef.mutate()
-        lst.listdef.agree(s_iterable.listdef)
+        self.listdef.mutate()
+        self.listdef.agree(s_iterable.listdef)
         # note that setslice is not allowed to resize a list in RPython
 
-    def delslice(lst, s_start, s_stop):
+    def delslice(self, s_start, s_stop):
         check_negative_slice(s_start, s_stop)
-        lst.listdef.resize()
+        self.listdef.resize()
 
 def check_negative_slice(s_start, s_stop, error="slicing"):
     if isinstance(s_start, SomeInteger) and not s_start.nonneg:
 
 class __extend__(SomeDict):
 
-    def _is_empty(dct):
-        s_key = dct.dictdef.read_key()
-        s_value = dct.dictdef.read_value()
+    def _is_empty(self):
+        s_key = self.dictdef.read_key()
+        s_value = self.dictdef.read_value()
         return (isinstance(s_key, SomeImpossibleValue) or
                 isinstance(s_value, SomeImpossibleValue))
 
-    def len(dct):
-        if dct._is_empty():
+    def len(self):
+        if self._is_empty():
             return immutablevalue(0)
-        return SomeObject.len(dct)
+        return SomeObject.len(self)
 
-    def iter(dct):
-        return SomeIterator(dct)
+    def iter(self):
+        return SomeIterator(self)
     iter.can_only_throw = []
 
-    def getanyitem(dct, variant='keys'):
+    def getanyitem(self, variant='keys'):
         if variant == 'keys':
-            return dct.dictdef.read_key()
+            return self.dictdef.read_key()
         elif variant == 'values':
-            return dct.dictdef.read_value()
+            return self.dictdef.read_value()
         elif variant == 'items':
-            s_key   = dct.dictdef.read_key()
-            s_value = dct.dictdef.read_value()
+            s_key   = self.dictdef.read_key()
+            s_value = self.dictdef.read_value()
             if (isinstance(s_key, SomeImpossibleValue) or
                 isinstance(s_value, SomeImpossibleValue)):
                 return s_ImpossibleValue
         else:
             raise ValueError
 
-    def method_get(dct, key, dfl):
-        dct.dictdef.generalize_key(key)
-        dct.dictdef.generalize_value(dfl)
-        return dct.dictdef.read_value()
+    def method_get(self, key, dfl):
+        self.dictdef.generalize_key(key)
+        self.dictdef.generalize_value(dfl)
+        return self.dictdef.read_value()
 
     method_setdefault = method_get
 
-    def method_copy(dct):
-        return SomeDict(dct.dictdef)
+    def method_copy(self):
+        return SomeDict(self.dictdef)
 
     def method_update(dct1, dct2):
         if s_None.contains(dct2):
             return SomeImpossibleValue()
         dct1.dictdef.union(dct2.dictdef)
 
-    def method_keys(dct):
-        return getbookkeeper().newlist(dct.dictdef.read_key())
+    def method_keys(self):
+        return getbookkeeper().newlist(self.dictdef.read_key())
 
-    def method_values(dct):
-        return getbookkeeper().newlist(dct.dictdef.read_value())
+    def method_values(self):
+        return getbookkeeper().newlist(self.dictdef.read_value())
 
-    def method_items(dct):
-        return getbookkeeper().newlist(dct.getanyitem('items'))
+    def method_items(self):
+        return getbookkeeper().newlist(self.getanyitem('items'))
 
-    def method_iterkeys(dct):
-        return SomeIterator(dct, 'keys')
+    def method_iterkeys(self):
+        return SomeIterator(self, 'keys')
 
-    def method_itervalues(dct):
-        return SomeIterator(dct, 'values')
+    def method_itervalues(self):
+        return SomeIterator(self, 'values')
 
-    def method_iteritems(dct):
-        return SomeIterator(dct, 'items')
+    def method_iteritems(self):
+        return SomeIterator(self, 'items')
 
-    def method_clear(dct):
+    def method_clear(self):
         pass
 
-    def method_popitem(dct):
-        return dct.getanyitem('items')
+    def method_popitem(self):
+        return self.getanyitem('items')
 
-    def method_pop(dct, s_key, s_dfl=None):
-        dct.dictdef.generalize_key(s_key)
+    def method_pop(self, s_key, s_dfl=None):
+        self.dictdef.generalize_key(s_key)
         if s_dfl is not None:
-            dct.dictdef.generalize_value(s_dfl)
-        return dct.dictdef.read_value()
+            self.dictdef.generalize_value(s_dfl)
+        return self.dictdef.read_value()
 
-    def _can_only_throw(dic, *ignore):
-        if dic.dictdef.dictkey.custom_eq_hash:
+    def _can_only_throw(self, *ignore):
+        if self.dictdef.dictkey.custom_eq_hash:
             return None    # r_dict: can throw anything
         return []          # else: no possible exception
 
-    def op_contains(dct, s_element):
-        dct.dictdef.generalize_key(s_element)
-        if dct._is_empty():
+    def op_contains(self, s_element):
+        self.dictdef.generalize_key(s_element)
+        if self._is_empty():
             s_bool = SomeBool()
             s_bool.const = False
             return s_bool
 class __extend__(SomeString,
                  SomeUnicodeString):
 
-    def method_startswith(str, frag):
-        if str.is_constant() and frag.is_constant():
-            return immutablevalue(str.const.startswith(frag.const))
+    def method_startswith(self, frag):
+        if self.is_constant() and frag.is_constant():
+            return immutablevalue(self.const.startswith(frag.const))
         return s_Bool
 
-    def method_endswith(str, frag):
-        if str.is_constant() and frag.is_constant():
-            return immutablevalue(str.const.endswith(frag.const))
+    def method_endswith(self, frag):
+        if self.is_constant() and frag.is_constant():
+            return immutablevalue(self.const.endswith(frag.const))
         return s_Bool
 
-    def method_find(str, frag, start=None, end=None):
+    def method_find(self, frag, start=None, end=None):
         check_negative_slice(start, end, "find")
         return SomeInteger()
 
-    def method_rfind(str, frag, start=None, end=None):
+    def method_rfind(self, frag, start=None, end=None):
         check_negative_slice(start, end, "rfind")
         return SomeInteger()
 
-    def method_count(str, frag, start=None, end=None):
+    def method_count(self, frag, start=None, end=None):
         check_negative_slice(start, end, "count")
         return SomeInteger(nonneg=True)
 
-    def method_strip(str, chr=None):
-        return str.basestringclass(no_nul=str.no_nul)
+    def method_strip(self, chr=None):
+        return self.basestringclass(no_nul=self.no_nul)
 
-    def method_lstrip(str, chr=None):
-        return str.basestringclass(no_nul=str.no_nul)
+    def method_lstrip(self, chr=None):
+        return self.basestringclass(no_nul=self.no_nul)
 
-    def method_rstrip(str, chr=None):
-        return str.basestringclass(no_nul=str.no_nul)
+    def method_rstrip(self, chr=None):
+        return self.basestringclass(no_nul=self.no_nul)
 
-    def method_join(str, s_list):
+    def method_join(self, s_list):
         if s_None.contains(s_list):
             return SomeImpossibleValue()
-        getbookkeeper().count("str_join", str)
+        getbookkeeper().count("str_join", self)
         s_item = s_list.listdef.read_item()
         if s_None.contains(s_item):
-            if isinstance(str, SomeUnicodeString):
+            if isinstance(self, SomeUnicodeString):
                 return immutablevalue(u"")
             return immutablevalue("")
-        no_nul = str.no_nul and s_item.no_nul
-        return str.basestringclass(no_nul=no_nul)
+        no_nul = self.no_nul and s_item.no_nul
+        return self.basestringclass(no_nul=no_nul)
 
-    def iter(str):
-        return SomeIterator(str)
+    def iter(self):
+        return SomeIterator(self)
     iter.can_only_throw = []
 
-    def getanyitem(str):
-        return str.basecharclass()
+    def getanyitem(self):
+        return self.basecharclass()
 
-    def method_split(str, patt, max=-1):
-        getbookkeeper().count("str_split", str, patt)
+    def method_split(self, patt, max=-1):
+        getbookkeeper().count("str_split", self, patt)
         if max == -1 and patt.is_constant() and patt.const == "\0":
             no_nul = True
         else:
-            no_nul = str.no_nul
-        s_item = str.basestringclass(no_nul=no_nul)
+            no_nul = self.no_nul
+        s_item = self.basestringclass(no_nul=no_nul)
         return getbookkeeper().newlist(s_item)
 
-    def method_rsplit(str, patt, max=-1):
-        getbookkeeper().count("str_rsplit", str, patt)
-        s_item = str.basestringclass(no_nul=str.no_nul)
+    def method_rsplit(self, patt, max=-1):
+        getbookkeeper().count("str_rsplit", self, patt)
+        s_item = self.basestringclass(no_nul=self.no_nul)
         return getbookkeeper().newlist(s_item)
 
-    def method_replace(str, s1, s2):
-        return str.basestringclass(no_nul=str.no_nul and s2.no_nul)
+    def method_replace(self, s1, s2):
+        return self.basestringclass(no_nul=self.no_nul and s2.no_nul)
 
-    def getslice(str, s_start, s_stop):
+    def getslice(self, s_start, s_stop):
         check_negative_slice(s_start, s_stop)
-        result = str.basestringclass(no_nul=str.no_nul)
+        result = self.basestringclass(no_nul=self.no_nul)
         return result
 
-    def op_contains(str, s_element):
+    def op_contains(self, s_element):
         if s_element.is_constant() and s_element.const == "\0":
             r = SomeBool()
             bk = getbookkeeper()
-            op = bk._find_current_op(opname="contains", arity=2, pos=0, s_type=str)
+            op = bk._find_current_op(opname="contains", arity=2, pos=0, s_type=self)
             knowntypedata = {}
-            add_knowntypedata(knowntypedata, False, [op.args[0]], str.nonnulify())
+            add_knowntypedata(knowntypedata, False, [op.args[0]], self.nonnulify())
             r.set_knowntypedata(knowntypedata)
             return r
         else:
-            return SomeObject.op_contains(str, s_element)
+            return SomeObject.op_contains(self, s_element)
     op_contains.can_only_throw = []
 
     def method_format(self, *args):
         return SomeByteArray()
 
 class __extend__(SomeUnicodeString):
-    def method_encode(uni, s_enc):
+    def method_encode(self, s_enc):
         if not s_enc.is_constant():
             raise AnnotatorError("Non-constant encoding not supported")
         enc = s_enc.const
 
 
 class __extend__(SomeString):
-    def method_isdigit(str):
+    def method_isdigit(self):
         return s_Bool
 
-    def method_isalpha(str):
+    def method_isalpha(self):
         return s_Bool
 
-    def method_isalnum(str):
+    def method_isalnum(self):
         return s_Bool
 
-    def method_upper(str):
+    def method_upper(self):
         return SomeString()
 
-    def method_lower(str):
+    def method_lower(self):
         return SomeString()
 
-    def method_splitlines(str, s_keep_newlines=None):
-        s_list = getbookkeeper().newlist(str.basestringclass())
+    def method_splitlines(self, s_keep_newlines=None):
+        s_list = getbookkeeper().newlist(self.basestringclass())
         # Force the list to be resizable because ll_splitlines doesn't
         # preallocate the list.
         s_list.listdef.listitem.resize()
         return s_list
 
-    def method_decode(str, s_enc):
+    def method_decode(self, s_enc):
         if not s_enc.is_constant():
             raise AnnotatorError("Non-constant encoding not supported")
         enc = s_enc.const
 
 class __extend__(SomeChar, SomeUnicodeCodePoint):
 
-    def len(chr):
+    def len(self):
         return immutablevalue(1)
 
-    def ord(str):
+    def ord(self):
         return SomeInteger(nonneg=True)
 
 class __extend__(SomeChar):
 
-    def method_isspace(chr):
+    def method_isspace(self):
         return s_Bool
 
-    def method_isalnum(chr):
+    def method_isalnum(self):
         return s_Bool
 
-    def method_islower(chr):
+    def method_islower(self):
         return s_Bool
 
-    def method_isupper(chr):
+    def method_isupper(self):
         return s_Bool
 
-    def method_lower(chr):
-        return chr
+    def method_lower(self):
+        return self
 
-    def method_upper(chr):
-        return chr
+    def method_upper(self):
+        return self
 
 class __extend__(SomeIterator):
 
-    def iter(itr):
-        return itr
+    def iter(self):
+        return self
     iter.can_only_throw = []
 
-    def _can_only_throw(itr):
+    def _can_only_throw(self):
         can_throw = [StopIteration]
-        if isinstance(itr.s_container, SomeDict):
+        if isinstance(self.s_container, SomeDict):
             can_throw.append(RuntimeError)
         return can_throw
 
-    def next(itr):
-        if itr.variant == ("enumerate",):
-            s_item = itr.s_container.getanyitem()
+    def next(self):
+        if self.variant == ("enumerate",):
+            s_item = self.s_container.getanyitem()
             return SomeTuple((SomeInteger(nonneg=True), s_item))
-        variant = itr.variant
+        variant = self.variant
         if variant == ("reversed",):
             variant = ()
-        return itr.s_container.getanyitem(*variant)
+        return self.s_container.getanyitem(*variant)
     next.can_only_throw = _can_only_throw
     method_next = next
 
 
 class __extend__(SomeInstance):
 
-    def _true_getattr(ins, attr):
+    def _true_getattr(self, attr):
         if attr == '__class__':
-            return ins.classdef.read_attr__class__()
-        attrdef = ins.classdef.find_attribute(attr)
+            return self.classdef.read_attr__class__()
+        attrdef = self.classdef.find_attribute(attr)
         position = getbookkeeper().position_key
         attrdef.read_locations[position] = True
         s_result = attrdef.getvalue()
         # hack: if s_result is a set of methods, discard the ones
-        #       that can't possibly apply to an instance of ins.classdef.
+        #       that can't possibly apply to an instance of self.classdef.
         # XXX do it more nicely
         if isinstance(s_result, SomePBC):
-            s_result = ins.classdef.lookup_filter(s_result, attr,
-                                                  ins.flags)
+            s_result = self.classdef.lookup_filter(s_result, attr,
+                                                  self.flags)
         elif isinstance(s_result, SomeImpossibleValue):
-            ins.classdef.check_missing_attribute_update(attr)
+            self.classdef.check_missing_attribute_update(attr)
             # blocking is harmless if the attribute is explicitly listed
             # in the class or a parent class.
-            for basedef in ins.classdef.getmro():
+            for basedef in self.classdef.getmro():
                 if basedef.classdesc.all_enforced_attrs is not None:
                     if attr in basedef.classdesc.all_enforced_attrs:
                         raise HarmlesslyBlocked("get enforced attr")
         elif isinstance(s_result, SomeList):
-            s_result = ins.classdef.classdesc.maybe_return_immutable_list(
+            s_result = self.classdef.classdesc.maybe_return_immutable_list(
                 attr, s_result)
         return s_result
 
-    def getattr(ins, s_attr):
+    def getattr(self, s_attr):
         if s_attr.is_constant() and isinstance(s_attr.const, str):
             attr = s_attr.const
-            return ins._true_getattr(attr)
+            return self._true_getattr(attr)
         raise AnnotatorError("A variable argument to getattr is not RPython")
     getattr.can_only_throw = []
 
-    def setattr(ins, s_attr, s_value):
+    def setattr(self, s_attr, s_value):
         if s_attr.is_constant() and isinstance(s_attr.const, str):
             attr = s_attr.const
             # find the (possibly parent) class where this attr is defined
-            clsdef = ins.classdef.locate_attribute(attr)
+            clsdef = self.classdef.locate_attribute(attr)
             attrdef = clsdef.attrs[attr]
             attrdef.modified(clsdef)
 
             # create or update the attribute in clsdef
             clsdef.generalize_attr(attr, s_value)
 
-    def bool_behavior(ins, s):
-        if not ins.can_be_None:
+    def bool_behavior(self, s):
+        if not self.can_be_None:
             s.const = True
 
-    def iter(ins):
-        s_iterable = ins._true_getattr('__iter__')
+    def iter(self):
+        s_iterable = self._true_getattr('__iter__')
         bk = getbookkeeper()
         # record for calltables
         bk.emulate_pbc_call(bk.position_key, s_iterable, [])
         return s_iterable.call(bk.build_args("simple_call", []))
 
-    def next(ins):
-        s_next = ins._true_getattr('next')
+    def next(self):
+        s_next = self._true_getattr('next')
         bk = getbookkeeper()
         # record for calltables
         bk.emulate_pbc_call(bk.position_key, s_next, [])
         return s_next.call(bk.build_args("simple_call", []))
 
 class __extend__(SomeBuiltin):
-    def _can_only_throw(bltn, *args):
-        analyser_func = getattr(bltn.analyser, 'im_func', None)
+    def _can_only_throw(self, *args):
+        analyser_func = getattr(self.analyser, 'im_func', None)
         can_only_throw = getattr(analyser_func, 'can_only_throw', None)
         if can_only_throw is None or isinstance(can_only_throw, list):
             return can_only_throw
-        if bltn.s_self is not None:
-            return can_only_throw(bltn.s_self, *args)
+        if self.s_self is not None:
+            return can_only_throw(self.s_self, *args)
         else:
             return can_only_throw(*args)
 
-    def simple_call(bltn, *args):
-        if bltn.s_self is not None:
-            return bltn.analyser(bltn.s_self, *args)
+    def simple_call(self, *args):
+        if self.s_self is not None:
+            return self.analyser(self.s_self, *args)
         else:
-            if bltn.methodname:
-                getbookkeeper().count(bltn.methodname.replace('.', '_'), *args)
-            return bltn.analyser(*args)
+            if self.methodname:
+                getbookkeeper().count(self.methodname.replace('.', '_'), *args)
+            return self.analyser(*args)
     simple_call.can_only_throw = _can_only_throw
 
-    def call(bltn, args, implicit_init=False):
+    def call(self, args, implicit_init=False):
         args_s, kwds = args.unpack()
         # prefix keyword arguments with 's_'
         kwds_s = {}
         for key, s_value in kwds.items():
             kwds_s['s_'+key] = s_value
-        if bltn.s_self is not None:
-            return bltn.analyser(bltn.s_self, *args_s, **kwds_s)
+        if self.s_self is not None:
+            return self.analyser(self.s_self, *args_s, **kwds_s)
         else:
-            return bltn.analyser(*args_s, **kwds_s)
+            return self.analyser(*args_s, **kwds_s)
 
 
 class __extend__(SomePBC):
 
-    def getattr(pbc, s_attr):
+    def getattr(self, s_attr):
         bookkeeper = getbookkeeper()
-        return bookkeeper.pbc_getattr(pbc, s_attr)
+        return bookkeeper.pbc_getattr(self, s_attr)
     getattr.can_only_throw = []
 
-    def setattr(pbc, s_attr, s_value):
-        if not pbc.isNone():
+    def setattr(self, s_attr, s_value):
+        if not self.isNone():
             raise AnnotatorError("Cannot modify attribute of a pre-built constant")
 
-    def call(pbc, args):
+    def call(self, args):
         bookkeeper = getbookkeeper()
-        return bookkeeper.pbc_call(pbc, args)
+        return bookkeeper.pbc_call(self, args)
 
-    def bind_callables_under(pbc, classdef, name):
-        d = [desc.bind_under(classdef, name) for desc in pbc.descriptions]
-        return SomePBC(d, can_be_None=pbc.can_be_None)
+    def bind_callables_under(self, classdef, name):
+        d = [desc.bind_under(classdef, name) for desc in self.descriptions]
+        return SomePBC(d, can_be_None=self.can_be_None)
 
-    def bool_behavior(pbc, s):
-        if pbc.isNone():
+    def bool_behavior(self, s):
+        if self.isNone():
             s.const = False
-        elif not pbc.can_be_None:
+        elif not self.can_be_None:
             s.const = True
 
-    def len(pbc):
-        if pbc.isNone():
+    def len(self):
+        if self.isNone():
             # this None could later be generalized into an empty list,
             # whose length is the constant 0; so let's tentatively answer 0.
             return immutablevalue(0)
 
 class __extend__(SomePtr):
 
-    def getattr(p, s_attr):
-        assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % p.ll_ptrtype
-        example = p.ll_ptrtype._example()
+    def getattr(self, s_attr):
+        assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % self.ll_ptrtype
+        example = self.ll_ptrtype._example()
         try:
             v = example._lookup_adtmeth(s_attr.const)
         except AttributeError:
             return getbookkeeper().immutablevalue(v)
     getattr.can_only_throw = []
 
-    def len(p):
-        length = p.ll_ptrtype._example()._fixedlength()
+    def len(self):
+        length = self.ll_ptrtype._example()._fixedlength()
         if length is None:
-            return SomeObject.len(p)
+            return SomeObject.len(self)
         else:
             return immutablevalue(length)
 
-    def setattr(p, s_attr, s_value): # just doing checking
-        assert s_attr.is_constant(), "setattr on ptr %r with non-constant field-name" % p.ll_ptrtype
-        example = p.ll_ptrtype._example()
+    def setattr(self, s_attr, s_value): # just doing checking
+        assert s_attr.is_constant(), "setattr on ptr %r with non-constant field-name" % self.ll_ptrtype
+        example = self.ll_ptrtype._example()
         if getattr(example, s_attr.const) is not None:  # ignore Void s_value
             v_lltype = annotation_to_lltype(s_value)
             setattr(example, s_attr.const, v_lltype._defl())
 
-    def call(p, args):
+    def call(self, args):
         args_s, kwds_s = args.unpack()
         if kwds_s:
             raise Exception("keyword arguments to call to a low-level fn ptr")
         info = 'argument to ll function pointer call'
         llargs = [annotation_to_lltype(s_arg,info)._defl() for s_arg in args_s]
-        v = p.ll_ptrtype._example()(*llargs)
+        v = self.ll_ptrtype._example()(*llargs)
         return ll_to_annotation(v)
 
-    def bool(p):
+    def bool(self):
         return s_Bool
 
 class __extend__(SomeLLADTMeth):
 
-    def call(adtmeth, args):
+    def call(self, args):
         bookkeeper = getbookkeeper()
-        s_func = bookkeeper.immutablevalue(adtmeth.func)
-        return s_func.call(args.prepend(lltype_to_annotation(adtmeth.ll_ptrtype)))
+        s_func = bookkeeper.immutablevalue(self.func)
+        return s_func.call(args.prepend(lltype_to_annotation(self.ll_ptrtype)))
 
 #_________________________________________
 # weakrefs
 
 class __extend__(SomeWeakRef):
-    def simple_call(s_wrf):
-        if s_wrf.classdef is None:
+    def simple_call(self):
+        if self.classdef is None:
             return s_None   # known to be a dead weakref
         else:
-            return SomeInstance(s_wrf.classdef, can_be_None=True)
+            return SomeInstance(self.classdef, can_be_None=True)
 
 #_________________________________________
 # memory addresses
 from rpython.rtyper.lltypesystem import llmemory
 
 class __extend__(SomeAddress):
-    def getattr(s_addr, s_attr):
+    def getattr(self, s_attr):
         assert s_attr.is_constant()
         assert isinstance(s_attr, SomeString)
         assert s_attr.const in llmemory.supported_access_types
             llmemory.supported_access_types[s_attr.const])
     getattr.can_only_throw = []
 
-    def bool(s_addr):
+    def bool(self):
         return s_Bool

rpython/flowspace/argument.py

 """
 Arguments objects.
 """
-
+from rpython.flowspace.model import const
 
 class Signature(object):
     _immutable_ = True
     """Represents the arguments passed into a function call, i.e. the
     `a, b, *c, **d` part in `return func(a, b, *c, **d)`.
     """
-    def __init__(self, args_w, keywords=None, w_stararg=None,
-            w_starstararg=None):
+    def __init__(self, args_w, keywords=None, w_stararg=None):
         self.w_stararg = w_stararg
-        assert w_starstararg is None, "No **-unpacking in RPython"
         assert isinstance(args_w, list)
         self.arguments_w = args_w
         self.keywords = keywords or {}
 
+    def __repr__(self):
+        """ NOT_RPYTHON """
+        name = self.__class__.__name__
+        if not self.keywords:
+            return '%s(%s)' % (name, self.arguments_w,)
+        else:
+            return '%s(%s, %s)' % (name, self.arguments_w, self.keywords)
+
     def flatten(self):
         """ Argument <-> list of w_objects together with "shape" information """
-        shape_cnt  = len(self.arguments_w)    # Number of positional args
-        shape_keys = tuple(sorted(self.keywords))
-        shape_star = self.w_stararg is not None   # Flag: presence of *arg
-        shape_stst = False # Flag: presence of **kwds
+        shape_cnt, shape_keys, shape_star = self._rawshape()
         data_w = self.arguments_w + [self.keywords[key] for key in shape_keys]
         if shape_star:
             data_w.append(self.w_stararg)
-        return (shape_cnt, shape_keys, shape_star, shape_stst), data_w
+        return (shape_cnt, shape_keys, shape_star), data_w
+
+    def _rawshape(self):
+        shape_cnt = len(self.arguments_w)
+        shape_keys = tuple(sorted(self.keywords))
+        shape_star = self.w_stararg is not None   # Flag: presence of *arg
+        return shape_cnt, shape_keys, shape_star
+
+    def as_list(self):
+        assert not self.keywords
+        if self.w_stararg is None:
+            return self.arguments_w
+        else:
+            return self.arguments_w + [const(x) for x in self.w_stararg.value]

rpython/flowspace/flowcontext.py

 from rpython.tool.stdlib_opcode import host_bytecode_spec
 from rpython.flowspace.argument import CallSpec
 from rpython.flowspace.model import (Constant, Variable, Block, Link,
-    c_last_exception, SpaceOperation, const)
+    c_last_exception, const, FSException)
 from rpython.flowspace.framestate import (FrameState, recursively_unflatten,
     recursively_flatten)
 from rpython.flowspace.specialcase import (rpython_print_item,
 class StopFlowing(Exception):
     pass
 
-class Return(Exception):
-    def __init__(self, value):
-        self.value = value
-
-class FSException(Exception):
-    def __init__(self, w_type, w_value):
-        assert w_type is not None
-        self.w_type = w_type
-        self.w_value = w_value
-
-    def get_w_value(self, _):
-        return self.w_value
-
-    def __str__(self):
-        return '[%s: %s]' % (self.w_type, self.w_value)
-
-class ImplicitOperationError(FSException):
-    pass
-
 class BytecodeCorruption(Exception):
     pass
 
             if isinstance(egg.last_exception, Constant):
                 w_exc_cls = egg.last_exception
                 assert not isinstance(w_exc_cls.value, list)
-            raise ImplicitOperationError(w_exc_cls, w_exc_value)
+            raise RaiseImplicit(FSException(w_exc_cls, w_exc_value))
 
 # ____________________________________________________________
 
             return w_condition.value
         return self.recorder.guessbool(self, w_condition)
 
-    def do_operation(self, name, *args_w):
-        spaceop = SpaceOperation(name, args_w, Variable())
-        self.record(spaceop)
-        return spaceop.result
-
     def record(self, spaceop):
         recorder = self.recorder
         if getattr(recorder, 'final_state', None) is not None:
 
     def do_op(self, op):
         self.record(op)
-        if op.canraise:
-            self.guessexception(op.canraise)
+        self.guessexception(op.canraise)
         return op.result
 
     def guessexception(self, exceptions, force=False):
         """
         Catch possible exceptions implicitly.
-
-        If the FSException is not caught in the same function, it will
-        produce an exception-raising return block in the flow graph. Note that
-        even if the interpreter re-raises the exception, it will not be the
-        same ImplicitOperationError instance internally.
         """
+        if not exceptions:
+            return
         if not force and not any(isinstance(block, (ExceptBlock, FinallyBlock))
                 for block in self.blockstack):
             # The implicit exception wouldn't be caught and would later get
                 next_pos = self.handle_bytecode(next_pos)
                 self.recorder.final_state = self.getstate(next_pos)
 
-        except ImplicitOperationError, e:
-            if isinstance(e.w_type, Constant):
-                exc_cls = e.w_type.value
+        except RaiseImplicit as e:
+            w_exc = e.w_exc
+            if isinstance(w_exc.w_type, Constant):
+                exc_cls = w_exc.w_type.value
             else:
                 exc_cls = Exception
             msg = "implicit %s shouldn't occur" % exc_cls.__name__
             link = Link([w_type, w_value], self.graph.exceptblock)
             self.recorder.crnt_block.closeblock(link)
 
-        except FSException, e:
-            if e.w_type == self.space.w_ImportError:
+        except Raise as e:
+            w_exc = e.w_exc
+            if w_exc.w_type == self.space.w_ImportError:
                 msg = 'import statement always raises %s' % e
                 raise ImportError(msg)
-            link = Link([e.w_type, e.w_value], self.graph.exceptblock)
+            link = Link([w_exc.w_type, w_exc.w_value], self.graph.exceptblock)
             self.recorder.crnt_block.closeblock(link)
 
         except StopFlowing:
             pass
 
         except Return as exc:
-            w_result = exc.value
+            w_result = exc.w_value
             link = Link([w_result], self.graph.returnblock)
             self.recorder.crnt_block.closeblock(link)
 
         try:
             res = getattr(self, methodname)(oparg)
             return res if res is not None else next_instr
-        except FSException, operr:
-            return self.handle_operation_error(operr)
+        except FlowSignal as signal:
+            return self.unroll(signal)
 
-    def handle_operation_error(self, operr):
-        unroller = SApplicationException(oper