[pypy-svn] r45043 - in pypy/dist/pypy/lang/scheme: . test

jlg at codespeak.net jlg at codespeak.net
Sat Jul 14 09:59:20 CEST 2007


Author: jlg
Date: Sat Jul 14 09:59:18 2007
New Revision: 45043

Modified:
   pypy/dist/pypy/lang/scheme/TODO.txt
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/ssparser.py
   pypy/dist/pypy/lang/scheme/test/test_eval.py
Log:
more work on numbers

Modified: pypy/dist/pypy/lang/scheme/TODO.txt
==============================================================================
--- pypy/dist/pypy/lang/scheme/TODO.txt	(original)
+++ pypy/dist/pypy/lang/scheme/TODO.txt	Sat Jul 14 09:59:18 2007
@@ -11,23 +11,22 @@
 - symbols vs identifier, which name is better
   - global dict for symbols _obarray_
 
-- implement key funcions
+- implement key functions
   (apply, reduce, mapcar and so on)
   # reduce will not make into python 3.0 ;)
 
 - comparison: < > eq? eqv?
 
- - exact/inexact numbers
-
 Do in some future
 -----------------
 
 Here starts the real fun!
 
+- quasi-quotations
 - macros
 - delayed evaluation
 - continuations
 - proper tail-recursion
-  - mutulally recursive procedures (r5rs p.12)
-- switch to bytecode generation + eval instead of evaluating AST
+  - mutually recursive procedures (r5rs p.12)
+- switch to byte-code generation + eval instead of evaluating AST
 

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Sat Jul 14 09:59:18 2007
@@ -13,7 +13,7 @@
 
 class WrongArgType(SchemeException):
     def __str__(self):
-        return "Wrong argument type"
+        return "Wrong argument type: {%s}!=%s" % (self.args[0], self.args[1])
 
 class SchemeQuit(SchemeException):
     """raised on (quit) evaluation"""
@@ -96,50 +96,54 @@
 class W_Real(W_Number):
     def __init__(self, val):
         self.exact = False
-        self.floatval = val
+        self.realval = val
 
     def to_string(self):
-        return str(self.floatval)
+        return str(self.realval)
 
     def to_number(self):
         return self.to_float()
 
     def to_fixnum(self):
-        return int(self.floatval)
+        return int(self.realval)
 
     def to_float(self):
-        return self.floatval
+        return self.realval
 
     def round(self):
-        int_part = int(self.floatval)
-        if self.floatval > 0:
-            if self.floatval >= (int_part + 0.5):
+        int_part = int(self.realval)
+        if self.realval > 0:
+            if self.realval >= (int_part + 0.5):
                 return int_part + 1
 
             return int_part
 
         else:
-            if self.floatval <= (int_part - 0.5):
+            if self.realval <= (int_part - 0.5):
                 return int_part - 1
 
             return int_part
 
+    def is_integer(self):
+        return self.realval == self.round()
+
 class W_Integer(W_Real):
     def __init__(self, val):
-        self.fixnumval = val
+        self.intval = val
+        self.realval = val
         self.exact = True
 
     def to_string(self):
-        return str(self.fixnumval)
+        return str(self.intval)
 
     def to_number(self):
         return self.to_fixnum()
 
     def to_fixnum(self):
-        return self.fixnumval
+        return self.intval
 
     def to_float(self):
-        return float(self.fixnumval)
+        return float(self.intval)
 
 class W_Pair(W_Root):
     def __init__(self, car, cdr):
@@ -185,6 +189,7 @@
         arg_lst = []
         arg = lst
         while not isinstance(arg, W_Nil):
+            assert isinstance(arg, W_Pair)
             arg_lst.append(arg.car.eval(ctx))
             arg = arg.cdr
 
@@ -217,6 +222,7 @@
                 self.args.append(Formal(arg.to_string(), True))
                 break
             else:
+                assert isinstance(arg, W_Pair)
                 assert isinstance(arg.car, W_Identifier)
                 #list of argument names, not evaluated
                 self.args.append(Formal(arg.car.to_string(), False))
@@ -301,7 +307,7 @@
         """ % (attr_name, oper))
 
     exec code.compile() in local_locals
-    local_locals[attr_name]._annspecialcase_ = 'specialize:argtype(1,2)'
+    local_locals[attr_name]._annspecialcase_ = 'specialize:argtype(1)'
     setattr(Op, attr_name, local_locals[attr_name])
 
     attr_name = "do_unary_oper"
@@ -354,14 +360,14 @@
             raise WrongArgsNumber
 
         if not isinstance(lst[0], W_Number):
-            raise WrongArgType
+            raise WrongArgType(1, 'Number')
 
         return W_Boolean(self.predicate(lst[0]))
 
 class IntegerP(PredicateNumber):
     def predicate(self, w_obj):
         if not w_obj.exact:
-            return w_obj.to_float() == w_obj.round()
+            return w_obj.is_integer()
 
         return True
 
@@ -381,11 +387,30 @@
     def predicate(self, w_obj):
         return not w_obj.exact
 
+class ZeroP(PredicateNumber):
+    def predicate(self, w_obj):
+        return w_obj.to_number() == 0.0
+
+class OddP(PredicateNumber):
+    def predicate(self, w_obj):
+        if not w_obj.is_integer():
+            raise WrongArgType(1, "Integer")
+
+        return w_obj.round() % 2 != 0
+
+class EvenP(PredicateNumber):
+    def predicate(self, w_obj):
+        if not w_obj.is_integer():
+            raise WrongArgType(1, "Integer")
+
+        return w_obj.round() % 2 == 0
+
 ##
 # Macro
 ##
 class Define(W_Macro):
     def call(self, ctx, lst):
+        assert isinstance(lst, W_Pair)
         w_identifier = lst.car
         assert isinstance(w_identifier, W_Identifier)
 
@@ -395,6 +420,7 @@
 
 class Sete(W_Macro):
     def call(self, ctx, lst):
+        assert isinstance(lst, W_Pair)
         w_identifier = lst.car
         assert isinstance(w_identifier, W_Identifier)
 
@@ -404,6 +430,7 @@
 
 class MacroIf(W_Macro):
     def call(self, ctx, lst):
+        assert isinstance(lst, W_Pair)
         w_condition = lst.car
         w_then = lst.cdr.car
         if isinstance(lst.cdr.cdr, W_Nil):
@@ -427,11 +454,13 @@
 class Car(W_Procedure):
     def procedure(self, ctx, lst):
         w_pair = lst[0]
+        assert isinstance(w_pair, W_Pair)
         return w_pair.car
 
 class Cdr(W_Procedure):
     def procedure(self, ctx, lst):
         w_pair = lst[0]
+        assert isinstance(w_pair, W_Pair)
         return w_pair.cdr
 
 class Quit(W_Procedure):
@@ -441,11 +470,12 @@
 class Lambda(W_Macro):
     def call(self, ctx, lst):
         w_args = lst.car
-        w_body = lst.cdr #.car
+        w_body = lst.cdr
         return W_Lambda(w_args, w_body, ctx.copy())
 
 class Let(W_Macro):
     def call(self, ctx, lst):
+        assert isinstance(lst, W_Pair)
         local_ctx = ctx.copy()
         w_formal = lst.car
         while not isinstance(w_formal, W_Nil):
@@ -459,6 +489,7 @@
 
 class Letrec(W_Macro):
     def call(self, ctx, lst):
+        assert isinstance(lst, W_Pair)
         local_ctx = ctx.copy()
 
         #bound variables
@@ -478,11 +509,12 @@
 
         return self.eval_body(local_ctx, lst.cdr)
 
-def Literal(sexpr):
+def literal(sexpr):
     return W_Pair(W_Identifier('quote'), W_Pair(sexpr, W_Nil()))
 
 class Quote(W_Macro):
     def call(self, ctx, lst):
+        assert isinstance(lst, W_Pair)
         return lst.car
 
 ##
@@ -521,6 +553,9 @@
         'number?': NumberP,
         'exact?': ExactP,
         'inexact?': InexactP,
+        'zero?': ZeroP,
+        'odd?': OddP,
+        'even?': EvenP,
             #macros
         'define': Define,
         'set!': Sete,

Modified: pypy/dist/pypy/lang/scheme/ssparser.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/ssparser.py	(original)
+++ pypy/dist/pypy/lang/scheme/ssparser.py	Sat Jul 14 09:59:18 2007
@@ -2,7 +2,7 @@
 from pypy.rlib.parsing.pypackrat import PackratParser
 from pypy.rlib.parsing.makepackrat import BacktrackException, Status
 from pypy.lang.scheme.object import W_Pair, W_Integer, W_String, W_Identifier, \
-        W_Nil, W_Boolean, W_Real, Literal
+        W_Nil, W_Boolean, W_Real, literal
 
 def unquote(s):
     str_lst = []
@@ -59,7 +59,7 @@
     literal:
        `'`
        s = sexpr
-       return {Literal(s)};
+       return {literal(s)};
     
     sexpr:
         list

Modified: pypy/dist/pypy/lang/scheme/test/test_eval.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/test/test_eval.py	(original)
+++ pypy/dist/pypy/lang/scheme/test/test_eval.py	Sat Jul 14 09:59:18 2007
@@ -399,7 +399,23 @@
 def test_exactness():
     assert eval_noctx("(exact? 42)").to_boolean()
     assert not eval_noctx("(exact? 42.0)").to_boolean()
+    py.test.raises(WrongArgType, eval_noctx, "(exact? 'a)" )
 
     assert not eval_noctx("(inexact? 42)").to_boolean()
     assert eval_noctx("(inexact? 42.0)").to_boolean()
+    py.test.raises(WrongArgType, eval_noctx, "(inexact? 'a)" )
+
+def test_number_predicates():
+    assert eval_noctx("(zero? 0)").to_boolean()
+    assert eval_noctx("(zero? 0.0)").to_boolean()
+    assert not eval_noctx("(zero? 1.0)").to_boolean()
+    py.test.raises(WrongArgType, eval_noctx, "(zero? 'a)" )
+
+    assert not eval_noctx("(odd? 0)").to_boolean()
+    assert eval_noctx("(odd? 1)").to_boolean()
+    py.test.raises(WrongArgType, eval_noctx, "(odd? 1.1)" )
+
+    assert eval_noctx("(even? 0)").to_boolean()
+    assert not eval_noctx("(even? 1)").to_boolean()
+    py.test.raises(WrongArgType, eval_noctx, "(even? 1.1)" )
 



More information about the Pypy-commit mailing list