[pypy-svn] r20170 - in pypy/branch/somepbc-refactoring/pypy: annotation rpython

pedronis at codespeak.net pedronis at codespeak.net
Tue Nov 22 19:42:43 CET 2005


Author: pedronis
Date: Tue Nov 22 19:42:42 2005
New Revision: 20170

Modified:
   pypy/branch/somepbc-refactoring/pypy/annotation/description.py
   pypy/branch/somepbc-refactoring/pypy/rpython/normalizecalls.py
   pypy/branch/somepbc-refactoring/pypy/rpython/rpbc.py
Log:
(arigo, mwh, pedronis)

test_easy_call passes, but not much else new.



Modified: pypy/branch/somepbc-refactoring/pypy/annotation/description.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/description.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/description.py	Tue Nov 22 19:42:42 2005
@@ -14,15 +14,15 @@
         self.descs = { desc: True }
         self.patterns = {}    # set of "call shapes" in the sense of
                               # pypy.interpreter.argument.Argument
-        self.calltables = {}  # see calltable_add_row()
+        self.calltables = {}  # see calltable_lookup_row()
 
     def update(self, other):
         self.descs.update(other.descs)
         self.patterns.update(other.patterns)
 
-    def calltable_add_row(self, callshape, row):
-        # this code builds and updates a table of which graph to call
-        # at which call site.  Each call site gets a row of graphs,
+    def calltable_lookup_row(self, callshape, row):
+        # this code looks up a table of which graph to
+        # call at which call site.  Each call site gets a row of graphs,
         # sharable with other call sites.  Each column is a FunctionDesc.
         # There is one such table per "call shape".
         table = self.calltables.setdefault(callshape, [])
@@ -41,15 +41,28 @@
                             msg = ("incompatible specializations in a call"
                                    " to %r")
                             raise Exception(msg % (merged_desc,))
-                    # done.  Start over again, because this expanded row
-                    # could now be merged with other rows...
-                    del table[i]
-                    self.calltable_add_row(callshape, merged)
-                    return
+                    # done.
+                    return i, merged
             #else: no common graph
-        else:
-            # add this as a new row.
-            table.append(row)
+        raise LookupError
+
+    def calltable_add_row(self, callshape, row):
+        table = self.calltables.setdefault(callshape, [])
+        while True:
+            try:
+                index, merged = self.calltable_lookup_row(callshape, row)
+            except LookupError:
+                # no compatible row.  Add this new one.
+                table.append(row)
+            else:
+                if merged != row:
+                    # remove the existing row
+                    del table[index]
+                    # Start over again with this expanded row
+                    # which can possibly be further merged with other rows
+                    row = merged
+                    continue
+            return
 
 
 class AttrFamily:
@@ -190,16 +203,21 @@
         return self.bookkeeper.getmethoddesc(self, classdef, name)
 
     def consider_call_site(bookkeeper, family, descs, args):
-        from pypy.annotation.model import s_ImpossibleValue
+        row = FunctionDesc.row_to_consider(descs, args)
+        family.calltable_add_row(args.rawshape(), row)
+    consider_call_site = staticmethod(consider_call_site)
+
+    def row_to_consider(descs, args):
         # see comments in CallFamily
+        from pypy.annotation.model import s_ImpossibleValue
         row = {}
         for desc in descs:
             def enlist(graph, ignore):
                 row[desc] = graph
                 return s_ImpossibleValue   # meaningless
             desc.pycall(enlist, args, s_ImpossibleValue)
-        family.calltable_add_row(args.rawshape(), row)
-    consider_call_site = staticmethod(consider_call_site)
+        return row
+    row_to_consider = staticmethod(row_to_consider)
 
 
 class ClassDesc(Desc):

Modified: pypy/branch/somepbc-refactoring/pypy/rpython/normalizecalls.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/rpython/normalizecalls.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/rpython/normalizecalls.py	Tue Nov 22 19:42:42 2005
@@ -11,159 +11,164 @@
 from pypy.rpython.objectmodel import instantiate
 
 
-def normalize_function_signatures(annotator):
-    """Make sure that all functions called in a group have exactly
-    the same signature, by hacking their flow graphs if needed.
-    """
-    call_families = annotator.getpbccallfamilies()
-
-    # for methods, we create or complete a corresponding function-only
-    # family with call patterns that have the extra 'self' argument
-    for family in call_families.infos():
-        prevkey = None
-        for classdef, func in family.objects:
-            if classdef is not None:
-                # add (None, func) to the func_family
-                if prevkey is None:
-                    prevkey = (None, func)
-                else:
-                    call_families.union((None, func), prevkey)
-        if prevkey is not None:
-            # copy the patterns from family to func_family with the
-            # extra self argument
-            _, _, func_family = call_families.find(prevkey)
-            for pattern in family.patterns:
-                argcount = pattern[0]
-                pattern = (argcount+1,) + pattern[1:]
-                func_family.patterns[pattern] = True
-
-    # for bound method objects, make sure the im_func shows up too.
-    for family in call_families.infos():
-        first = family.objects.keys()[0][1]
-        for _, callable in family.objects:
-            if isinstance(callable, types.MethodType):
-                # for bound methods families for now just accept and check that
-                # they all refer to the same function
-                if not isinstance(first, types.MethodType):
-                    raise TyperError("call family with both bound methods and "
-                                     "%r" % (first,))
-                if first.im_func is not callable.im_func:
-                    raise TyperError("call family of bound methods: should all "
-                                     "refer to the same function")
-        # create a family for the common im_func
-        if isinstance(first, types.MethodType):
-            _, _, func_family = call_families.find((None, first.im_func))
-            for pattern in family.patterns:
-                argcount = pattern[0]
-                pattern = (argcount+1,) + pattern[1:]
-                func_family.patterns[pattern] = True
-
-    # find the most general signature of each family
-    for family in call_families.infos():
-        # collect functions in this family, ignoring:
-        #  - methods: taken care of above
-        #  - bound methods: their im_func will also show up
-        #  - classes: already handled by create_class_constructors()
-        functions = [func for classdef, func in family.objects
-                          if classdef is None and
-                not isinstance(func, (type, types.ClassType, types.MethodType))]
-        if len(functions) > 1:  # otherwise, nothing to do
-            fully_normalized = True
-            if len(family.patterns) > 1:
-                argspec = inspect.getargspec(functions[0])
-                for func in functions:
-                    if inspect.getargspec(func) != argspec:
-                        raise TyperError("don't support multiple call patterns "
-                                 "to multiple functions with different signatures for now %r" % (
-                                functions))
-                args, varargs, varkwds, _ = argspec
-                assert varargs is None, "XXX not implemented"
-                assert varkwds is None, "XXX not implemented"
-                pattern = (len(args), (), False, False)
-                fully_normalized = False
-            else:
-                pattern, = family.patterns
-            shape_cnt, shape_keys, shape_star, shape_stst = pattern
-            assert not shape_star, "XXX not implemented"
-            assert not shape_stst, "XXX not implemented"
-
-            # for the first 'shape_cnt' arguments we need to generalize to
-            # a common type
-            graph_bindings = {}
-            graph_argorders = {}
-            for func in functions:
-                assert not has_varargs(func), "XXX not implemented"
+##def normalize_function_signatures(annotator):
+##    """Make sure that all functions called in a group have exactly
+##    the same signature, by hacking their flow graphs if needed.
+##    """
+##    call_families = annotator.getpbccallfamilies()
+
+##    # for methods, we create or complete a corresponding function-only
+##    # family with call patterns that have the extra 'self' argument
+##    for family in call_families.infos():
+##        prevkey = None
+##        for classdef, func in family.objects:
+##            if classdef is not None:
+##                # add (None, func) to the func_family
+##                if prevkey is None:
+##                    prevkey = (None, func)
+##                else:
+##                    call_families.union((None, func), prevkey)
+##        if prevkey is not None:
+##            # copy the patterns from family to func_family with the
+##            # extra self argument
+##            _, _, func_family = call_families.find(prevkey)
+##            for pattern in family.patterns:
+##                argcount = pattern[0]
+##                pattern = (argcount+1,) + pattern[1:]
+##                func_family.patterns[pattern] = True
+
+##    # for bound method objects, make sure the im_func shows up too.
+##    for family in call_families.infos():
+##        first = family.objects.keys()[0][1]
+##        for _, callable in family.objects:
+##            if isinstance(callable, types.MethodType):
+##                # for bound methods families for now just accept and check that
+##                # they all refer to the same function
+##                if not isinstance(first, types.MethodType):
+##                    raise TyperError("call family with both bound methods and "
+##                                     "%r" % (first,))
+##                if first.im_func is not callable.im_func:
+##                    raise TyperError("call family of bound methods: should all "
+##                                     "refer to the same function")
+##        # create a family for the common im_func
+##        if isinstance(first, types.MethodType):
+##            _, _, func_family = call_families.find((None, first.im_func))
+##            for pattern in family.patterns:
+##                argcount = pattern[0]
+##                pattern = (argcount+1,) + pattern[1:]
+##                func_family.patterns[pattern] = True
+
+##    # find the most general signature of each family
+##    for family in call_families.infos():
+##        # collect functions in this family, ignoring:
+##        #  - methods: taken care of above
+##        #  - bound methods: their im_func will also show up
+##        #  - classes: already handled by create_class_constructors()
+##        functions = [func for classdef, func in family.objects
+##                          if classdef is None and
+##                not isinstance(func, (type, types.ClassType, types.MethodType))]
+##        if len(functions) > 1:  # otherwise, nothing to do
+
+
+def normalize_calltable_row(row):
+    if len(row) <= 1:
+        return   # nothing to do
+    fully_normalized = True
+    if len(family.patterns) > 1:
+        argspec = inspect.getargspec(functions[0])
+        for func in functions:
+            if inspect.getargspec(func) != argspec:
+                raise TyperError("don't support multiple call patterns "
+                         "to multiple functions with different signatures for now %r" % (
+                        functions))
+        args, varargs, varkwds, _ = argspec
+        assert varargs is None, "XXX not implemented"
+        assert varkwds is None, "XXX not implemented"
+        pattern = (len(args), (), False, False)
+        fully_normalized = False
+    else:
+        pattern, = family.patterns
+    shape_cnt, shape_keys, shape_star, shape_stst = pattern
+    assert not shape_star, "XXX not implemented"
+    assert not shape_stst, "XXX not implemented"
+
+    # for the first 'shape_cnt' arguments we need to generalize to
+    # a common type
+    graph_bindings = {}
+    graph_argorders = {}
+    for func in functions:
+        assert not has_varargs(func), "XXX not implemented"
+        try:
+            graph = annotator.translator.flowgraphs[func]
+        except KeyError:
+            raise TyperError("the skipped %r must not show up in a "
+                             "call family" % (func,))
+        graph_bindings[graph] = [annotator.binding(v)
+                                 for v in graph.getargs()]
+        argorder = range(shape_cnt)
+        for key in shape_keys:
+            i = list(func.func_code.co_varnames).index(key)
+            assert i not in argorder
+            argorder.append(i)
+        graph_argorders[graph] = argorder
+
+    call_nbargs = shape_cnt + len(shape_keys)
+    generalizedargs = []
+    for i in range(call_nbargs):
+        args_s = []
+        for graph, bindings in graph_bindings.items():
+            j = graph_argorders[graph][i]
+            args_s.append(bindings[j])
+        s_value = annmodel.unionof(*args_s)
+        generalizedargs.append(s_value)
+    result_s = [annotator.binding(graph.getreturnvar())
+                for graph in graph_bindings]
+    generalizedresult = annmodel.unionof(*result_s)
+
+    for func in functions:
+        graph = annotator.translator.getflowgraph(func)
+        bindings = graph_bindings[graph]
+        argorder = graph_argorders[graph]
+        need_reordering = (argorder != range(call_nbargs))
+        need_conversion = (generalizedargs != bindings)
+        if need_reordering or need_conversion:
+            oldblock = graph.startblock
+            inlist = []
+            for s_value, j in zip(generalizedargs, argorder):
+                v = Variable(graph.getargs()[j])
+                annotator.setbinding(v, s_value)
+                inlist.append(v)
+            newblock = Block(inlist)
+            # prepare the output args of newblock:
+            # 1. collect the positional arguments
+            outlist = inlist[:shape_cnt]
+            # 2. add defaults and keywords
+            defaults = func.func_defaults or ()
+            for j in range(shape_cnt, len(bindings)):
                 try:
-                    graph = annotator.translator.flowgraphs[func]
-                except KeyError:
-                    raise TyperError("the skipped %r must not show up in a "
-                                     "call family" % (func,))
-                graph_bindings[graph] = [annotator.binding(v)
-                                         for v in graph.getargs()]
-                argorder = range(shape_cnt)
-                for key in shape_keys:
-                    i = list(func.func_code.co_varnames).index(key)
-                    assert i not in argorder
-                    argorder.append(i)
-                graph_argorders[graph] = argorder
-
-            call_nbargs = shape_cnt + len(shape_keys)
-            generalizedargs = []
-            for i in range(call_nbargs):
-                args_s = []
-                for graph, bindings in graph_bindings.items():
-                    j = graph_argorders[graph][i]
-                    args_s.append(bindings[j])
-                s_value = annmodel.unionof(*args_s)
-                generalizedargs.append(s_value)
-            result_s = [annotator.binding(graph.getreturnvar())
-                        for graph in graph_bindings]
-            generalizedresult = annmodel.unionof(*result_s)
-
-            for func in functions:
-                graph = annotator.translator.getflowgraph(func)
-                bindings = graph_bindings[graph]
-                argorder = graph_argorders[graph]
-                need_reordering = (argorder != range(call_nbargs))
-                need_conversion = (generalizedargs != bindings)
-                if need_reordering or need_conversion:
-                    oldblock = graph.startblock
-                    inlist = []
-                    for s_value, j in zip(generalizedargs, argorder):
-                        v = Variable(graph.getargs()[j])
-                        annotator.setbinding(v, s_value)
-                        inlist.append(v)
-                    newblock = Block(inlist)
-                    # prepare the output args of newblock:
-                    # 1. collect the positional arguments
-                    outlist = inlist[:shape_cnt]
-                    # 2. add defaults and keywords
-                    defaults = func.func_defaults or ()
-                    for j in range(shape_cnt, len(bindings)):
-                        try:
-                            i = argorder.index(j)
-                            v = inlist[i]
-                        except ValueError:
-                            try:
-                                default = defaults[j-len(bindings)]
-                            except IndexError:
-                                raise TyperError(
-                                    "call pattern has %d positional arguments, "
-                                    "but %r takes at least %d arguments" % (
-                                        shape_cnt, func,
-                                        len(bindings) - len(defaults)))
-                            v = Constant(default)
-                        outlist.append(v)
-                    newblock.closeblock(Link(outlist, oldblock))
-                    oldblock.isstartblock = False
-                    newblock.isstartblock = True
-                    graph.startblock = newblock
-                    # finished
-                    checkgraph(graph)
-                    annotator.annotated[newblock] = annotator.annotated[oldblock]
-                graph.normalized_for_calls = fully_normalized
-                # convert the return value too
-                annotator.setbinding(graph.getreturnvar(), generalizedresult)
+                    i = argorder.index(j)
+                    v = inlist[i]
+                except ValueError:
+                    try:
+                        default = defaults[j-len(bindings)]
+                    except IndexError:
+                        raise TyperError(
+                            "call pattern has %d positional arguments, "
+                            "but %r takes at least %d arguments" % (
+                                shape_cnt, func,
+                                len(bindings) - len(defaults)))
+                    v = Constant(default)
+                outlist.append(v)
+            newblock.closeblock(Link(outlist, oldblock))
+            oldblock.isstartblock = False
+            newblock.isstartblock = True
+            graph.startblock = newblock
+            # finished
+            checkgraph(graph)
+            annotator.annotated[newblock] = annotator.annotated[oldblock]
+        graph.normalized_for_calls = fully_normalized
+        # convert the return value too
+        annotator.setbinding(graph.getreturnvar(), generalizedresult)
 
 
 def specialize_pbcs_by_memotables(annotator):
@@ -233,7 +238,6 @@
         extra_access_sets[access_set] = len(extra_access_sets)
 
 def create_class_constructors(rtyper):
-    return    # XXX later
     # for classes that appear in families, make a __new__ PBC attribute.
     call_families = rtyper.annotator.getpbccallfamilies()
     access_sets = rtyper.annotator.getpbcaccesssets()
@@ -360,14 +364,14 @@
             id_ = assign_id(classdef, id_)
         
 def perform_normalizations(rtyper):
-    return # XXX usw.
-    create_class_constructors(rtyper)
+    #XXX later: create_class_constructors(rtyper)
     rtyper.annotator.frozen += 1
     try:
-        normalize_function_signatures(rtyper.annotator)
-        specialize_pbcs_by_memotables(rtyper.annotator) 
-        merge_classpbc_getattr_into_classdef(rtyper)
-        assign_inheritance_ids(rtyper.annotator)
+        pass
+        #XXX later: normalize_function_signatures(rtyper.annotator)
+        #XXX later: specialize_pbcs_by_memotables(rtyper.annotator) 
+        #XXX later: merge_classpbc_getattr_into_classdef(rtyper)
+        #XXX later: assign_inheritance_ids(rtyper.annotator)
     finally:
         rtyper.annotator.frozen -= 1
-    create_instantiate_functions(rtyper.annotator)
+    #XXX later: create_instantiate_functions(rtyper.annotator)

Modified: pypy/branch/somepbc-refactoring/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/rpython/rpbc.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/rpython/rpbc.py	Tue Nov 22 19:42:42 2005
@@ -75,6 +75,7 @@
         self.rtyper = rtyper
         self.s_pbc = s_pbc
         self._function_signatures = None
+        self.callfamily = s_pbc.descriptions.iterkeys().next().getcallfamily()
         if len(s_pbc.descriptions) == 1:
             # a single function
             self.lowleveltype = Void
@@ -123,22 +124,40 @@
         return f
 
     def rtype_simple_call(self, hop):
-        f, rinputs, rresult = self.function_signatures().itervalues().next()
+        bk = self.rtyper.annotator.bookkeeper
+        args = bk.build_args("simple_call", hop.args_s[1:])
+        descs = self.s_pbc.descriptions.keys()
+        row = description.FunctionDesc.row_to_consider(descs, args)
+        index, merged = self.callfamily.calltable_lookup_row(args.rawshape(),
+                                                             row)
+        assert len(merged) == 1   # for now
+        [(funcdesc, graph)] = merged.items()
+        llfnobj = self.rtyper.getcallable(graph)
+        vlist = [hop.inputconst(typeOf(llfnobj), llfnobj)]
+        # XXX use callparse again here
+        vlist += [hop.inputarg(self.rtyper.bindingrepr(graph.getargs()[i]), arg=i+1)
+                  for i in range(len(graph.getargs()))]
+        rresult = self.rtyper.bindingrepr(graph.getreturnvar())
+        hop.exception_is_here()
+        v = hop.genop('direct_call', vlist, resulttype = rresult)
+        return hop.llops.convertvar(v, rresult, hop.r_result)
 
-        if getattr(self.rtyper.type_system_deref(f).graph, 'normalized_for_calls', False):
-            # should not have an argument count mismatch
-            assert len(rinputs) == hop.nb_args-1, "normalization bug"
-            vlist = hop.inputargs(self, *rinputs)
-        else:
-            # if not normalized, should be a call to a known function
-            # or to functions all with same signature
-            funcs = self.function_signatures().keys()
-            assert samesig(funcs), "normalization bug"
-            func = funcs[0]
-            vlist = [hop.inputarg(self, arg=0)]
-            vlist += callparse.callparse('simple_call', func, rinputs, hop)
+##        f, rinputs, rresult = self.function_signatures().itervalues().next()
 
-        return self.call(hop, f, vlist, rresult)
+##        if getattr(self.rtyper.type_system_deref(f).graph, 'normalized_for_calls', False):
+##            # should not have an argument count mismatch
+##            assert len(rinputs) == hop.nb_args-1, "normalization bug"
+##            vlist = hop.inputargs(self, *rinputs)
+##        else:
+##            # if not normalized, should be a call to a known function
+##            # or to functions all with same signature
+##            funcs = self.function_signatures().keys()
+##            assert samesig(funcs), "normalization bug"
+##            func = funcs[0]
+##            vlist = [hop.inputarg(self, arg=0)]
+##            vlist += callparse.callparse('simple_call', func, rinputs, hop)
+
+##        return self.call(hop, f, vlist, rresult)
 
     def call(self, hop, f, vlist, rresult):
         if self.lowleveltype is Void:



More information about the Pypy-commit mailing list