[pypy-svn] r25494 - in pypy/dist/pypy/translator/cli: . test

antocuni at codespeak.net antocuni at codespeak.net
Fri Apr 7 15:11:38 CEST 2006


Author: antocuni
Date: Fri Apr  7 15:11:23 2006
New Revision: 25494

Added:
   pypy/dist/pypy/translator/cli/database.py   (contents, props changed)
Modified:
   pypy/dist/pypy/translator/cli/class_.py
   pypy/dist/pypy/translator/cli/cts.py
   pypy/dist/pypy/translator/cli/function.py
   pypy/dist/pypy/translator/cli/gencli.py
   pypy/dist/pypy/translator/cli/metavm.py
   pypy/dist/pypy/translator/cli/test/compile.py
   pypy/dist/pypy/translator/cli/test/runtest.py
   pypy/dist/pypy/translator/cli/test/test_oo.py
Log:
Added support for unbound methods


Modified: pypy/dist/pypy/translator/cli/class_.py
==============================================================================
--- pypy/dist/pypy/translator/cli/class_.py	(original)
+++ pypy/dist/pypy/translator/cli/class_.py	Fri Apr  7 15:11:23 2006
@@ -3,7 +3,8 @@
 from pypy.translator.cli import cts
 
 class Class(Node):
-    def __init__(self, classdef):
+    def __init__(self, db, classdef):
+        self.db = db
         self.classdef = classdef
         self.namespace, self.name = cts.split_class_name(classdef._name)
 
@@ -30,9 +31,8 @@
         self._ctor()
 
         for m_name, m_meth in self.classdef._methods.iteritems():
-            # TODO: handle static, class and unbound methods
-            # TODO: should __init__ be rendered as a constructor?
-            f = Function(m_meth.graph, m_name, is_method = True)
+            # TODO: handle class and unbound methods
+            f = Function(self.db, m_meth.graph, m_name, is_method = True)
             f.render(ilasm)
 
         ilasm.end_class()

Modified: pypy/dist/pypy/translator/cli/cts.py
==============================================================================
--- pypy/dist/pypy/translator/cli/cts.py	(original)
+++ pypy/dist/pypy/translator/cli/cts.py	Fri Apr  7 15:11:23 2006
@@ -47,10 +47,10 @@
 
 def lltype_to_cts(t):
     if isinstance(t, Instance):
-        name = t._name.replace('__main__.', '') # TODO: modules
-        if name in ('Object_meta', 'Object'):
+        name = t._name
+        if 'Object_meta' in name or 'Object' in name: # TODO
             return 'object'
-        
+
         return 'class %s' % name
 
     return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t)

Added: pypy/dist/pypy/translator/cli/database.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/cli/database.py	Fri Apr  7 15:11:23 2006
@@ -0,0 +1,18 @@
+try:
+    set
+except NameError:
+    from sets import Set as set
+
+
+class LowLevelDatabase(object):
+    def __init__(self):
+        self.classes = set()
+        self.pending_graphs = []
+        self.functions = {} # graph --> function_name
+        self.methods = {} # graph --> method_name
+
+    def record_function(self, graph, name):
+        self.functions[graph] = name
+
+    def function_name(self, graph):
+        return self.functions.get(graph, None)

Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py	(original)
+++ pypy/dist/pypy/translator/cli/function.py	Fri Apr  7 15:11:23 2006
@@ -18,13 +18,13 @@
 py.log.setconsumer("cli", ansi_log) 
 
 class Function(Node, Generator):
-    def __init__(self, graph, name = None, is_method = False, is_entrypoint = False):
+    def __init__(self, db, graph, name = None, is_method = False, is_entrypoint = False):
+        self.db = db
         self.graph = graph
         self.name = name or graph.name
         self.is_method = is_method
         self.is_entrypoint = is_entrypoint
         self.blocknum = {}
-        self.classdefs = set()
         self._set_args()
         self._set_locals()
 
@@ -130,6 +130,10 @@
             self.ilasm.opcode('ret')
 
         self.ilasm.end_function()
+        if self.is_method:
+            pass # TODO
+        else:
+            self.db.record_function(self.graph, self.name)
 
     def _setup_link(self, link):
         target = link.target
@@ -197,7 +201,7 @@
                 lltype = arg.value
 
             if isinstance(lltype, Instance):
-                self.classdefs.add(lltype)
+                self.db.classes.add(lltype)
 
 
     def _render_op(self, op):
@@ -225,8 +229,9 @@
     def function_signature(self, graph):
         return cts.graph_to_signature(graph, False)
 
-    def method_signature(self, graph, name):
-        return cts.graph_to_signature(graph, True, name)
+    def method_signature(self, graph, class_name, name):
+        full_name = '%s::%s' % (class_name, name)
+        return cts.graph_to_signature(graph, True, full_name)
 
     def class_name(self, ooinstance):
         return ooinstance._name
@@ -234,7 +239,8 @@
     def emit(self, instr, *args):
         self.ilasm.opcode(instr, *args)
 
-    def call(self, func_name):
+    def call(self, graph, func_name):
+        self.db.pending_graphs.append(graph)
         self.ilasm.call(func_name)
 
     def new(self, obj):
@@ -248,10 +254,10 @@
 
     def call_method(self, obj, name):
         owner, meth = obj._lookup(name)
-        full_name = '%s::%s' % (self.class_name(obj), name)
+        signature = self.method_signature(meth.graph, self.class_name(obj), name)
         # TODO: there are cases when we don't need callvirt but a
         # plain call is sufficient
-        self.ilasm.call_method(self.method_signature(meth.graph, full_name))
+        self.ilasm.call_method(signature)
 
     def load(self, v):
         if isinstance(v, flowmodel.Variable):
@@ -265,8 +271,9 @@
                 self.ilasm.opcode('ldloc', repr(v.name))
 
         elif isinstance(v, flowmodel.Constant):
-            iltype, ilvalue = cts.llconst_to_ilasm(v)
-            self.ilasm.opcode('ldc.' + iltype, ilvalue)
+            if v.concretetype != Void:
+                iltype, ilvalue = cts.llconst_to_ilasm(v)
+                self.ilasm.opcode('ldc.' + iltype, ilvalue)
         else:
             assert False
 

Modified: pypy/dist/pypy/translator/cli/gencli.py
==============================================================================
--- pypy/dist/pypy/translator/cli/gencli.py	(original)
+++ pypy/dist/pypy/translator/cli/gencli.py	Fri Apr  7 15:11:23 2006
@@ -1,8 +1,3 @@
-try:
-    set
-except NameError:
-    from sets import Set as set
-
 import sys
 from types import MethodType
 
@@ -11,6 +6,7 @@
 from pypy.translator.cli.function import Function
 from pypy.translator.cli.class_ import Class
 from pypy.translator.cli.option import getoption
+from pypy.translator.cli.database import LowLevelDatabase
 
 
 class Tee(object):
@@ -31,7 +27,7 @@
         self.tmpdir = tmpdir
         self.translator = translator
         self.entrypoint = entrypoint
-        self.classdefs = set()
+        self.db = LowLevelDatabase()
 
         if entrypoint is None:
             self.assembly_name = self.translator.graphs[0].name
@@ -46,41 +42,41 @@
             out = Tee(sys.stdout, out)
 
         self.ilasm = IlasmGenerator(out, self.assembly_name)
-        self.gen_all_functions()
+        self.gen_entrypoint()
         self.find_superclasses()
         self.gen_classes()
+        self.gen_functions()        
         out.close()
         return self.tmpfile.strpath
 
-    def gen_all_functions(self):
+    def gen_entrypoint(self):
         if self.entrypoint:
-            self.entrypoint.render(self.ilasm)
-
-        # generate code for all 'global' functions, i.e., those who are not methods.            
-        for graph in self.translator.graphs:
+            self.db.pending_graphs += self.entrypoint.render(self.ilasm)
+        else:
+            self.db.pending_graphs.append(self.translator.graphs[0])
 
-            # TODO: remove this test
-            if graph.name.startswith('ll_'):
-                continue
+        self.gen_functions()
 
-            if '.' not in graph.name: # it's not a method
-                f = Function(graph)
+    def gen_functions(self):
+        while self.db.pending_graphs:
+            graph = self.db.pending_graphs.pop()
+            if self.db.function_name(graph) is None:
+                f = Function(self.db, graph)
                 f.render(self.ilasm)
-                self.classdefs.update(f.classdefs)
 
     def find_superclasses(self):
-        classdefs = set()
-        pendings = self.classdefs
+        classes = set()
+        pendings = self.db.classes
 
         while pendings:
             classdef = pendings.pop()
-            if classdef not in classdefs and classdef is not None:
-                classdefs.add(classdef)
+            if classdef not in classes and classdef is not None:
+                classes.add(classdef)
                 pendings.add(classdef._superclass)
 
-        self.classdefs = classdefs
+        self.db.classes = classes
 
     def gen_classes(self):
-        for classdef in self.classdefs:
-            c = Class(classdef)
+        for classdef in self.db.classes:
+            c = Class(self.db, classdef)
             c.render(self.ilasm)

Modified: pypy/dist/pypy/translator/cli/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/cli/metavm.py	(original)
+++ pypy/dist/pypy/translator/cli/metavm.py	Fri Apr  7 15:11:23 2006
@@ -50,13 +50,32 @@
 
 class _Call(MicroInstruction):
     def render(self, generator, op):
-        func_sig = generator.function_signature(op.args[0].value.graph)
+        graph = op.args[0].value.graph
+        cls = getattr(graph.func, 'class_', None)
 
-        # push parameters
-        for func_arg in op.args[1:]:
+        self._render_function(generator, graph, op.args)
+##        if cls is None:
+##            self._render_function(generator, graph, op.args)
+##        else:
+##            self._render_unbound_meth(generator, cls, graph, op.args)
+
+    def _render_unbound_meth(self, generator, cls, graph, args):
+        0/0
+        this = args[1]
+        # TODO: make sure that 'this' is compatible with 'cls'
+        for func_arg in args[1:]:
             generator.load(func_arg)
 
-        generator.call(func_sig)
+        # TODO: it doesn't work if cls is in another namespace
+        cls_name, meth_name = graph.name.rsplit('.', 1)
+        meth_sig = generator.method_signature(graph, cls_name, meth_name)
+        generator.call(graph, meth_sig) # TODO
+
+    def _render_function(self, generator, graph, args):
+        func_sig = generator.function_signature(graph)
+        for func_arg in args[1:]: # push parameters
+            generator.load(func_arg)
+        generator.call(graph, func_sig)
 
 class _New(MicroInstruction):
     def render(self, generator, op):

Modified: pypy/dist/pypy/translator/cli/test/compile.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/compile.py	(original)
+++ pypy/dist/pypy/translator/cli/test/compile.py	Fri Apr  7 15:11:23 2006
@@ -27,10 +27,15 @@
         self.x = x
 
 class Derived(Base):
-    pass
+    def __init__(self, x):
+        Base.__init__(self, x)
+
+def foo(x):
+    return x+1
 
 def bar(x, y):
-    a = Derived(42)
+    a = Derived(x)
+    return a.x
 
 
 f = compile_function(bar, [int, int])

Modified: pypy/dist/pypy/translator/cli/test/runtest.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/runtest.py	(original)
+++ pypy/dist/pypy/translator/cli/test/runtest.py	Fri Apr  7 15:11:23 2006
@@ -54,6 +54,7 @@
         ilasm.call('void class [mscorlib]System.Console::WriteLine(%s)' % ret_type)
         ilasm.opcode('ret')
         ilasm.end_function()
+        return [self.graph]
 
     def __convert_method(self, arg_type):
         _conv = {

Modified: pypy/dist/pypy/translator/cli/test/test_oo.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_oo.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_oo.py	Fri Apr  7 15:11:23 2006
@@ -19,10 +19,13 @@
     def compute_and_multiply(self, factor):
         return self.compute() * factor
 
+    def static_meth(x, y):
+        return x*y
+    static_meth = staticmethod(static_meth)
+
 class MyDerivedClass(MyClass):
     def __init__(self, x, y):
-        self.x = x
-        self.y = y
+        MyClass.__init__(self, x, y)
 
     def compute(self):
         return self.x - self.y
@@ -46,3 +49,10 @@
     base = MyClass(x, y)
     derived = MyDerivedClass(x, y)
     return helper(base) + helper(derived)
+
+def oo_static_method(x, y):
+    base = MyClass(x, y)
+    derived = MyDerivedClass(x, y)
+    return base.static_meth(x,y) + derived.static_meth(x, y)\
+           + MyClass.static_meth(x, y) + MyDerivedClass.static_meth(x, y)
+



More information about the Pypy-commit mailing list