[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