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

nik at codespeak.net nik at codespeak.net
Mon Mar 20 14:43:33 CET 2006


Author: nik
Date: Mon Mar 20 14:43:26 2006
New Revision: 24591

Modified:
   pypy/dist/pypy/translator/squeak/codeformatter.py
   pypy/dist/pypy/translator/squeak/opformatter.py
   pypy/dist/pypy/translator/squeak/test/test_llops.py
Log:
full support for floats in gensqueak.


Modified: pypy/dist/pypy/translator/squeak/codeformatter.py
==============================================================================
--- pypy/dist/pypy/translator/squeak/codeformatter.py	(original)
+++ pypy/dist/pypy/translator/squeak/codeformatter.py	Mon Mar 20 14:43:26 2006
@@ -100,7 +100,7 @@
             return self.format_Instance(value)
         elif value is None:
             return "nil"
-        elif isinstance(value, int):
+        elif isinstance(value, (int, float)):
             return str(value)
         elif isinstance(value, ootype._class):
             return self.format_Instance(value._INSTANCE)

Modified: pypy/dist/pypy/translator/squeak/opformatter.py
==============================================================================
--- pypy/dist/pypy/translator/squeak/opformatter.py	(original)
+++ pypy/dist/pypy/translator/squeak/opformatter.py	Mon Mar 20 14:43:26 2006
@@ -31,6 +31,13 @@
         'classof':     'class',
         'same_as':     'yourself', 
         'bool_not':    'not',
+
+        'cast_int_to_float': 'asFloat',
+        'float_div':   '/', # overrides the div definition in number_ops
+        'float_fmod':  r'\\', # we can't really distinguish mod and fmod
+        'float_floor': 'floor',
+        # XXX this potentially incorrect (may return LargeIntegers)
+        'cast_float_to_int': 'truncated',
     }
 
     number_ops = {
@@ -45,7 +52,7 @@
         'mul':       '*',
         'div':       '//',
         'floordiv':  '//',
-        #'truediv':   '/', # XXX fix this when we have float support
+        'truediv':   '/ asFloat',
         'mod':       r'\\',
         'eq':        '=',
         'ne':        '~=',
@@ -74,6 +81,10 @@
         self.codef = CodeFormatter(gen)
 
     def format(self, op):
+        if self.ops.has_key(op.opname):
+            name = self.ops[op.opname]
+            sent = Message(name).send_to(op.args[0], op.args[1:])
+            return self.codef.format(sent.assign_to(op.result))
         opname_parts = op.opname.split("_")
         if opname_parts[0] in self.number_opprefixes:
             return self.format_number_op(
@@ -82,26 +93,29 @@
         if op_method is not None:
             return self.codef.format(op_method(op))
         else:
-            if not self.ops.has_key(op.opname):
-                raise NotImplementedError(
+            raise NotImplementedError(
                         "operation not supported: %s" % op.opname)
-            name = self.ops[op.opname]
-            sent = Message(name).send_to(op.args[0], op.args[1:])
-            return self.codef.format(sent.assign_to(op.result))
 
     def format_number_op(self, op, ptype, opname):
-        message = Message(self.number_ops[opname])
-        sent_message = message.send_to(op.args[0], op.args[1:])
+        messages = self.number_ops[opname].split()
+        msg = Message(messages[0])
+        sent_message = msg.send_to(op.args[0], op.args[1:])
+        for add_message in messages[1:]:
+            sent_message = Message(add_message).send_to(sent_message, [])
         if opname in self.wrapping_ops \
                 and self.int_masks.has_key(ptype):
-            # XXX how do i get rid of this import?
-            from pypy.translator.squeak.node import HelperNode
-            mask_name, mask_code = self.int_masks[ptype]
-            helper = HelperNode(self.gen, Message(mask_name), mask_code)
-            sent_message = helper.apply([sent_message])
-            self.gen.schedule_node(helper)
+            sent_message = self.apply_mask_helper(sent_message, ptype)
         return self.codef.format(sent_message.assign_to(op.result))
 
+    def apply_mask_helper(self, receiver, mask_type_name):
+        # XXX how do i get rid of this import?
+        from pypy.translator.squeak.node import HelperNode
+        mask_name, mask_code = self.int_masks[mask_type_name]
+        helper = HelperNode(self.gen, Message(mask_name), mask_code)
+        result = helper.apply([receiver])
+        self.gen.schedule_node(helper)
+        return result
+
     def op_oosend(self, op):
         message_name = op.args[0].value
         message_name = self.gen.unique_method_name(
@@ -150,10 +164,16 @@
         msg = Message(function_name).send_to(FunctionNode.FUNCTIONS, op.args[1:])
         return msg.assign_to(op.result)
 
-    def op_cast_bool_to_int(self, op):
-        msg = Message("ifTrue: [1] ifFalse: [0]")
+    def cast_bool(self, op, true_repr, false_repr):
+        msg = Message("ifTrue: [%s] ifFalse: [%s]" % (true_repr, false_repr))
         return msg.send_to(op.args[0], []).assign_to(op.result)
 
+    def op_cast_bool_to_int(self, op):
+        return self.cast_bool(op, "1", "0")
+
+    def op_cast_bool_to_float(self, op):
+        return self.cast_bool(op, "1.0", "0.0")
+
     op_cast_bool_to_uint = op_cast_bool_to_int
 
     op_cast_char_to_int = noop
@@ -163,14 +183,9 @@
     op_cast_int_to_char = noop
     op_cast_int_to_unichar = noop
     op_cast_int_to_longlong = noop
-    # XXX to_float missing
 
     def masking_cast(self, op, mask):
-        from pypy.translator.squeak.node import HelperNode
-        mask_name, mask_code = self.int_masks[mask]
-        helper = HelperNode(self.gen, Message(mask_name), mask_code)
-        cast = helper.apply([op.args[0]])
-        self.gen.schedule_node(helper)
+        cast = self.apply_mask_helper(op.args[0], mask)
         return Assignment(op.result, cast)
 
     def op_cast_int_to_uint(self, op):
@@ -181,3 +196,7 @@
 
     op_truncate_longlong_to_int = noop
 
+    def op_cast_float_to_uint(self, op):
+        truncated = Message("truncated").send_to(op.args[0], [])
+        return Assignment(op.result, self.apply_mask_helper(truncated, "uint"))
+

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	Mon Mar 20 14:43:26 2006
@@ -4,7 +4,7 @@
 from pypy.rpython.annlowlevel import LowLevelAnnotatorPolicy
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Bool, Char, UniChar
-from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong
+from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong, Float
 from pypy.rpython.test.test_llinterp import interpret
 
 def optest(testcase):
@@ -61,6 +61,7 @@
     ("div", Signed, 7, 3),
     ("floordiv", Signed, 7, 3), # XXX what about division by zero?
     ("floordiv", Signed, -7, 3),
+    ("truediv", Float, 7, 4),
     ("mod", Signed, 9, 4),
     ("mod", Signed, 9, -4),
     ("eq", Bool, 1, 1),
@@ -120,6 +121,36 @@
     for t in tests:
         yield optest, t
 
+def test_floatoperations_unary():
+    for llopname in "abs", "neg", "floor":
+        exec """def lloptest():
+            return llop.float_%s(Float, -1.5)""" % llopname
+        expected_res = llinterpret(lloptest, ())
+        res = sqinterpret(lloptest, ())
+        assert expected_res == float(res) # because floor might return a squeak int
+
+def test_floatoperations_is_true():
+    def istrue():
+        return llop.float_is_true(Bool, 0.0)
+    llfunctest(istrue, ())
+
+def test_floatoperations_binary():
+    for llopname in "add", "sub", "mul", "div", "mod", "fmod", \
+            "floordiv", "truediv":
+        exec """def lloptest(i):
+            f = llop.cast_int_to_float(Float, i)
+            return llop.float_%s(Float, f, 1.25)""" % llopname
+        expected_res = llinterpret(lloptest, (3,))
+        res = sqinterpret(lloptest, (3,))
+        assert expected_res == float(res) # because of floordiv 
+
+def test_floatoperations_binary_bool():
+    for llopname in "eq", "ne", "gt", "lt", "ge", "le":
+        exec """def lloptest(i):
+            f = llop.cast_int_to_float(Float, i)
+            return llop.float_%s(Bool, f, 1.25)""" % llopname
+        yield llfunctest, lloptest, (3,)
+
 def test_booloperations():
     def bool_not(i):
         if i == 1:
@@ -146,7 +177,7 @@
         yield llfunctest, lloptest, (1, 2)
 
 def test_cast_bool():
-    tests = ("int", Signed), ("uint", Unsigned) # XXX missing float
+    tests = ("int", Signed), ("uint", Unsigned), ("float", Float)
     for target_name, target_type in tests: 
         exec """def lloptest(i):
             b = llop.int_is_true(Bool, i)
@@ -168,7 +199,7 @@
         yield llfunctest, lloptest, (1,)
 
 def test_cast_int():
-    tests = [("char", Char), ("unichar", UniChar),
+    tests = [("char", Char), ("unichar", UniChar), ("float", Float),
              ("longlong", SignedLongLong), ("uint", Unsigned)]
     for target_name, target_type in tests:
         exec """def lloptest(i):
@@ -176,9 +207,11 @@
                     % (target_name, target_type._name)
         args = (2,)
         expected_res = llinterpret(lloptest, args)
-        res = int(sqinterpret(lloptest, args))
+        res = sqinterpret(lloptest, args)
         if isinstance(expected_res, (str, unicode)):
-            res = chr(res)
+            res = chr(int(res))
+        else:
+            expected_res = str(expected_res)
         assert expected_res == res
 
 def test_cast_int_to_uint():
@@ -191,3 +224,11 @@
         return llop.cast_uint_to_int(Signed, i)
     llfunctest(lloptest, (r_uint(sys.maxint + 1),))
 
+def test_cast_float():
+    tests = [("int", Signed), ("uint", Unsigned)]
+    for target_name, target_type in tests:
+        exec """def lloptest():
+            return llop.cast_float_to_%s(%s, -1.5)""" \
+                    % (target_name, target_type._name)
+        yield llfunctest, lloptest, ()
+



More information about the Pypy-commit mailing list