[pypy-svn] r24438 - in pypy/dist/pypy/translator/squeak: . test

nik at codespeak.net nik at codespeak.net
Thu Mar 16 11:10:21 CET 2006


Author: nik
Date: Thu Mar 16 11:10:19 2006
New Revision: 24438

Added:
   pypy/dist/pypy/translator/squeak/opformatter.py
Modified:
   pypy/dist/pypy/translator/squeak/gensqueak.py
   pypy/dist/pypy/translator/squeak/test/test_llops.py
Log:
rip out the code generation for llops and put it in its own module.
somewhat improve handling of the various integer types. there's still
some quite ugly code around.


Modified: pypy/dist/pypy/translator/squeak/gensqueak.py
==============================================================================
--- pypy/dist/pypy/translator/squeak/gensqueak.py	(original)
+++ pypy/dist/pypy/translator/squeak/gensqueak.py	Thu Mar 16 11:10:19 2006
@@ -3,8 +3,8 @@
 from pypy.objspace.flow.model import last_exception, checkgraph
 from pypy.translator.gensupp import NameManager
 from pypy.translator.squeak.message import Message, camel_case
+from pypy.translator.squeak.opformatter import OpFormatter
 from pypy.rpython.ootypesystem.ootype import Instance, ROOT
-from pypy.rpython.rarithmetic import r_int, r_uint
 from pypy import conftest
 try:
     set
@@ -196,46 +196,6 @@
 
 class CallableNode(CodeNode):
 
-    selectormap = {
-        #'setitem:with:': 'at:put:',
-        #'getitem:':      'at:',
-        'new':           'new',
-        'runtimenew':    'new',
-        'classof':       'class',
-        'sameAs':        'yourself', 
-    }
-
-    primitive_ops = {
-        'abs':       'abs',
-        'is_true':   'isZero not',
-        'neg':       'negated',
-        'invert':    'bitInvert', # maybe bitInvert32?
-
-        'add':       '+',
-        'sub':       '-',
-        'eq':        '=',
-        'mul':       '*',
-        'div':       '//',
-        'floordiv':  '//',
-    }
-    
-    primitive_opprefixes = "int", "uint", "llong", "ullong", "float"
-
-    primitive_wrapping_ops = "neg", "invert", "add", "sub", "mul"
-
-    primitive_masks = {
-        # XXX horrendous, but I can't figure out how to do this cleanly
-        "int": (Message("maskInt"),
-                """maskInt: i 
-                    ((i <= %s) & (i >= %s)) ifTrue: [^i].
-                    ^ i + %s \\\\ %s - %s
-                  """ % (sys.maxint, -sys.maxint-1,
-                      sys.maxint+1, 2*(sys.maxint+1), sys.maxint+1)),
-        "uint": (Message("maskUint"),
-                """maskUint: i 
-                    ^ i bitAnd: %s""" % r_uint.MASK),
-    }
-
     def render_body(self, startblock):
         self.loops = LoopFinder(startblock).loops
         args = self.arguments(startblock)
@@ -260,93 +220,6 @@
         else:
             raise TypeError, "expr(%r)" % (v,)
 
-    def oper(self, op):
-        opname_parts = op.opname.split("_")
-        if opname_parts[0] in self.primitive_opprefixes:
-            return self.oper_primitive(
-                    op, opname_parts[0], "_".join(opname_parts[1:]))
-        op_method = getattr(self, "op_%s" % op.opname, None)
-        if op_method is not None:
-            return op_method(op)
-        else:
-            name = op.opname
-            receiver = self.expr(op.args[0])
-            args = [self.expr(arg) for arg in op.args[1:]]
-            return self.assignment(op, receiver, name, args)
-
-    def oper_primitive(self, op, ptype, opname):
-        receiver = self.expr(op.args[0])
-        args = [self.expr(arg) for arg in op.args[1:]]
-        sel = Message(self.primitive_ops[opname])
-        message = "%s %s" % (receiver, sel.signature(args))
-        if opname in self.primitive_wrapping_ops \
-                and self.primitive_masks.has_key(ptype):
-            mask_selector, mask_code = self.primitive_masks[ptype]
-            helper = HelperNode(self.gen, mask_selector, mask_code)
-            message = helper.apply(["(%s)" % message])
-            self.gen.schedule_node(helper)
-        return "%s := %s." % (self.expr(op.result), message)
-
-    def assignment(self, op, receiver_name, sel_name, arg_names):
-        sel_name = camel_case(sel_name)
-        if op.opname != "oosend":
-            sel_name = self.selectormap.get(sel_name, sel_name)
-        sel = Message(sel_name)
-        return "%s := %s %s." % (self.expr(op.result),
-                receiver_name, sel.signature(arg_names))
-
-    def op_oosend(self, op):
-        message = op.args[0].value
-        if hasattr(self, "self") and op.args[1] == self.self:
-            receiver = "self"
-        else:
-            receiver = self.expr(op.args[1])
-        args = [self.expr(a) for a in op.args[2:]]
-        self.gen.schedule_node(
-                MethodNode(self.gen, op.args[1].concretetype, message))
-        return self.assignment(op, receiver, message, args)
-
-    def op_oogetfield(self, op):
-        INST = op.args[0].concretetype
-        receiver = self.expr(op.args[0])
-        field_name = self.unique_field(INST, op.args[1].value)
-        if hasattr(self, "self") and op.args[0] == self.self:
-            # Private field access
-            # Could also directly substitute op.result with name
-            # everywhere for optimization.
-            return "%s := %s." % (self.expr(op.result), camel_case(field_name))
-        else:
-            # Public field access
-            self.gen.schedule_node(GetterNode(self.gen, INST, field_name))
-            return self.assignment(op, receiver, field_name, [])
-
-    def op_oosetfield(self, op):
-        # Note that the result variable is never used
-        INST = op.args[0].concretetype
-        field_name = self.unique_field(INST, op.args[1].value)
-        field_value = self.expr(op.args[2])
-        if hasattr(self, "self") and op.args[0] == self.self:
-            # Private field access
-            return "%s := %s." % (field_name, field_value)
-        else:
-            # Public field access
-            self.gen.schedule_node(SetterNode(self.gen, INST, field_name))
-            receiver = self.expr(op.args[0])
-            return "%s %s: %s." % (receiver, field_name, field_value)
-
-    def op_oodowncast(self, op):
-        return "%s := %s." % (self.expr(op.result), self.expr(op.args[0]))
-
-    def op_direct_call(self, op):
-        # XXX not sure if static methods of a specific class should
-        # be treated differently.
-        receiver = "PyFunctions"
-        callable_name = self.expr(op.args[0])
-        args = [self.expr(a) for a in op.args[1:]]
-        self.gen.schedule_node(
-            FunctionNode(self.gen, op.args[0].value.graph))
-        return self.assignment(op, receiver, callable_name, args)
-
     def render_return(self, args):
         if len(args) == 2:
             # exception
@@ -373,8 +246,9 @@
                 yield '"skip1"'
                 return
             yield "["
+        formatter = OpFormatter(self.gen, self)
         for op in block.operations:
-            yield "%s" % self.oper(op)
+            yield "%s" % formatter.format(op)
         if len(block.exits) == 0:
             for line in self.render_return(block.inputargs):
                 yield line
@@ -410,6 +284,7 @@
         self.gen = gen
         self.INSTANCE = INSTANCE
         self.name = method_name
+        self.self = None # Will be set upon rendering
         self.hash_key = (INSTANCE, method_name)
 
     def dependencies(self):
@@ -435,6 +310,7 @@
         self.gen = gen
         self.graph = graph
         self.name = gen.nameof(graph.func)
+        self.self = None
         self.hash_key = graph
 
     def dependencies(self):

Added: pypy/dist/pypy/translator/squeak/opformatter.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/squeak/opformatter.py	Thu Mar 16 11:10:19 2006
@@ -0,0 +1,164 @@
+import sys
+from pypy.objspace.flow.model import Constant, Variable
+from pypy.rpython.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
+from pypy.rpython.ootypesystem.ootype import Instance
+from pypy.translator.squeak.message import Message, camel_case
+
+def _setup_int_masks():
+    """Generates code for helpers to mask the various integer types."""
+    masks = {}
+    for name, r_type in ("int", r_int), ("uint", r_uint), \
+            ("llong", r_longlong), ("ullong", r_ulonglong):
+        helper_name = "mask%s" % name.capitalize()
+        if name[0] == "u":
+            # Unsigned integer type
+            code = """%s: i 
+                ^ i bitAnd: %s""" % (helper_name, r_type.MASK)
+        else:
+            # Signed integer type
+            code = """%s: i
+                (i <= %s) & (i >= %s) ifTrue: [^i].
+                (i < 0) ifTrue: [^i bitAnd: %s]
+                        ifFalse: [^(((i negated) - 1) bitAnd: %s) negated - 1]
+                """ % (helper_name, r_type.MASK>>1, -(r_type.MASK>>1)-1,
+                        r_type.MASK>>1, r_type.MASK>>1)
+        masks[name] = helper_name, code
+    return masks
+
+class OpFormatter:
+
+    ops = {
+        'new':         'new',
+        'runtimenew':  'new',
+        'classof':     'class',
+        'same_as':     'yourself', 
+    }
+
+    number_ops = {
+        'abs':       'abs',
+        'is_true':   'isZero not',
+        'neg':       'negated',
+        'invert':    'bitInvert', # maybe bitInvert32?
+
+        'add':       '+',
+        'sub':       '-',
+        'eq':        '=',
+        'mul':       '*',
+        'div':       '//',
+        'floordiv':  '//',
+    }
+    
+    number_opprefixes = "int", "uint", "llong", "ullong", "float"
+
+    wrapping_ops = "neg", "invert", "add", "sub", "mul"
+
+    int_masks = _setup_int_masks()
+
+    def __init__(self, gen, node):
+        self.gen = gen
+        self.node = node
+
+    def expr(self, v):
+        # XXX this code duplicated in gensqueak.py
+        if isinstance(v, Variable):
+            return camel_case(v.name)
+        elif isinstance(v, Constant):
+            if isinstance(v.concretetype, Instance):
+                const_id = self.gen.unique_name(
+                        v, "const_%s" % self.gen.nameof(v.value._TYPE))
+                self.gen.constant_insts[v] = const_id
+                return "(PyConstants getConstant: '%s')" % const_id
+            return self.gen.nameof(v.value)
+        else:
+            raise TypeError, "expr(%r)" % (v,)
+
+    def format(self, op):
+        opname_parts = op.opname.split("_")
+        if opname_parts[0] in self.number_opprefixes:
+            return self.format_number_op(
+                    op, opname_parts[0], "_".join(opname_parts[1:]))
+        op_method = getattr(self, "op_%s" % op.opname, None)
+        if op_method is not None:
+            return op_method(op)
+        else:
+            name = op.opname
+            name = self.ops.get(name, name)
+            receiver = self.expr(op.args[0])
+            args = [self.expr(arg) for arg in op.args[1:]]
+            return self.assignment(op, receiver, name, args)
+
+    def format_number_op(self, op, ptype, opname):
+        receiver = self.expr(op.args[0])
+        args = [self.expr(arg) for arg in op.args[1:]]
+        sel = Message(self.number_ops[opname])
+        message = "%s %s" % (receiver, sel.signature(args))
+        if opname in self.wrapping_ops \
+                and self.int_masks.has_key(ptype):
+            from pypy.translator.squeak.gensqueak import HelperNode
+            mask_name, mask_code = self.int_masks[ptype]
+            helper = HelperNode(self.gen, Message(mask_name), mask_code)
+            message = helper.apply(["(%s)" % message])
+            self.gen.schedule_node(helper)
+        return "%s := %s." % (self.expr(op.result), message)
+
+    def assignment(self, op, receiver_name, sel_name, arg_names):
+        sel = Message(sel_name)
+        return "%s := %s %s." % (self.expr(op.result),
+                receiver_name, sel.signature(arg_names))
+
+    def op_oosend(self, op):
+        message = op.args[0].value
+        if op.args[1] == self.node.self:
+            receiver = "self"
+        else:
+            receiver = self.expr(op.args[1])
+        args = [self.expr(a) for a in op.args[2:]]
+        from pypy.translator.squeak.gensqueak import MethodNode
+        self.gen.schedule_node(
+                MethodNode(self.gen, op.args[1].concretetype, message))
+        return self.assignment(op, receiver, message, args)
+
+    def op_oogetfield(self, op):
+        INST = op.args[0].concretetype
+        receiver = self.expr(op.args[0])
+        field_name = self.node.unique_field(INST, op.args[1].value)
+        if op.args[0] == self.node.self:
+            # Private field access
+            # Could also directly substitute op.result with name
+            # everywhere for optimization.
+            return "%s := %s." % (self.expr(op.result), field_name)
+        else:
+            # Public field access
+            from pypy.translator.squeak.gensqueak import GetterNode
+            self.gen.schedule_node(GetterNode(self.gen, INST, field_name))
+            return self.assignment(op, receiver, field_name, [])
+
+    def op_oosetfield(self, op):
+        # Note that the result variable is never used
+        INST = op.args[0].concretetype
+        field_name = self.node.unique_field(INST, op.args[1].value)
+        field_value = self.expr(op.args[2])
+        if op.args[0] == self.node.self:
+            # Private field access
+            return "%s := %s." % (field_name, field_value)
+        else:
+            # Public field access
+            from pypy.translator.squeak.gensqueak import SetterNode
+            self.gen.schedule_node(SetterNode(self.gen, INST, field_name))
+            receiver = self.expr(op.args[0])
+            return "%s %s: %s." % (receiver, field_name, field_value)
+
+    def op_oodowncast(self, op):
+        return "%s := %s." % (self.expr(op.result), self.expr(op.args[0]))
+
+    def op_direct_call(self, op):
+        # XXX not sure if static methods of a specific class should
+        # be treated differently.
+        from pypy.translator.squeak.gensqueak import FunctionNode
+        receiver = "PyFunctions"
+        callable_name = self.expr(op.args[0])
+        args = [self.expr(a) for a in op.args[1:]]
+        self.gen.schedule_node(
+            FunctionNode(self.gen, op.args[0].value.graph))
+        return self.assignment(op, receiver, callable_name, args)
+

Modified: pypy/dist/pypy/translator/squeak/test/test_llops.py
==============================================================================
--- pypy/dist/pypy/translator/squeak/test/test_llops.py	(original)
+++ pypy/dist/pypy/translator/squeak/test/test_llops.py	Thu Mar 16 11:10:19 2006
@@ -11,7 +11,6 @@
     RESTYPE = testcase[1] 
     args = testcase[2:]
 
-    llopfunc = getattr(llop, llopname)
     arg_signature = ", ".join(["v%s" % n for n in range(len(args))])
     exec """def lloptest(%s):
         return llop.%s(%s, %s)""" \



More information about the Pypy-commit mailing list