[pypy-svn] r45447 - in pypy/dist/pypy/lang/scheme: . test
jlg at codespeak.net
jlg at codespeak.net
Wed Aug 1 16:23:20 CEST 2007
Author: jlg
Date: Wed Aug 1 16:23:19 2007
New Revision: 45447
Modified:
pypy/dist/pypy/lang/scheme/execution.py
pypy/dist/pypy/lang/scheme/object.py
pypy/dist/pypy/lang/scheme/ssparser.py
pypy/dist/pypy/lang/scheme/test/test_macro.py
pypy/dist/pypy/lang/scheme/test/test_parser.py
Log:
bug in macro expansions removed, SyntacticClosure is no more, instead we have PairClosure and SymbolClosure; parsing for ellipsis; macros with flat ellipsis works
Modified: pypy/dist/pypy/lang/scheme/execution.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/execution.py (original)
+++ pypy/dist/pypy/lang/scheme/execution.py Wed Aug 1 16:23:19 2007
@@ -83,13 +83,11 @@
self.closure = closure
def _dispatch(self, symb):
- if isinstance(symb, W_Symbol):
- return (self, symb.name)
+ if isinstance(symb, SymbolClosure):
+ return (symb.closure, symb.name)
- elif isinstance(symb, SyntacticClosure):
- symbol = symb.sexpr
- if isinstance(symbol, W_Symbol):
- return (symb.closure, symbol.name)
+ elif isinstance(symb, W_Symbol):
+ return (self, symb.name)
raise SchemeSyntaxError
Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py (original)
+++ pypy/dist/pypy/lang/scheme/object.py Wed Aug 1 16:23:19 2007
@@ -77,6 +77,8 @@
def eq_symbol(self, w_symb):
return w_symb is self
+w_ellipsis = W_Symbol("...")
+
def symbol(name):
#use this to create new symbols, it stores all symbols
#in W_Symbol.obarray dict
@@ -205,6 +207,9 @@
#end proper list with dotted
return car + " . " + cdr.to_string()
+ def __repr__(self):
+ return "<W_Pair " + self.to_string() + ">"
+
def eval_tr(self, ctx):
oper = self.car.eval(ctx)
if not isinstance(oper, W_Callable):
@@ -316,7 +321,7 @@
return "#<procedure %s>" % (self.pname,)
def procedure_tr(self, ctx, lst):
- """must be tail-recursive aware, uses eval_body"""
+ #must be tail-recursive aware, uses eval_body
#ctx is a caller context, which is joyfully ignored
local_ctx = self.closure.copy()
@@ -619,7 +624,7 @@
class MacroIf(W_Macro):
def call_tr(self, ctx, lst):
- """if needs to be tail-recursive aware"""
+ #if needs to be tail-recursive aware
if not isinstance(lst, W_Pair):
raise SchemeSyntaxError
w_condition = lst.car
@@ -667,7 +672,7 @@
class LetStar(W_Macro):
def call_tr(self, ctx, lst):
- """let* uses eval_body, so it is tail-recursive aware"""
+ #let* uses eval_body, so it is tail-recursive aware
if not isinstance(lst, W_Pair):
raise SchemeSyntaxError
local_ctx = ctx.copy()
@@ -856,6 +861,11 @@
#closes template in syntactic enviroment at the point of definition
return W_Transformer(syntax_lst, ctx)
+class Ellipsis(Exception):
+ def __init__(self, expr, level):
+ self.expr = expr
+ self.level = level
+
class SyntaxRule(object):
def __init__(self, pattern, template, literals):
self.pattern = pattern
@@ -886,6 +896,13 @@
if w_form is not w_literal:
return (False, {})
+ w_pattcdr = w_patt.cdr
+ if isinstance(w_pattcdr, W_Pair) and w_pattcdr.car is w_ellipsis:
+ #w_pattcar should be matched 0-inf times in ellipsis
+ print w_patt, w_expr
+ match_dict[w_pattcar.to_string()] = Ellipsis(w_expr, 1)
+ return (True, match_dict)
+
if isinstance(w_pattcar, W_Pair):
if not isinstance(w_exprcar, W_Pair):
return (False, {})
@@ -897,28 +914,60 @@
match_dict.update(match_nested)
match_dict[w_pattcar.to_string()] = w_exprcar
+
w_patt = w_patt.cdr
w_expr = w_expr.cdr
- if w_expr is w_nil and w_patt is w_nil:
- return (True, match_dict)
+ if (w_expr is w_nil) and (w_patt is w_nil):
+ return (True, match_dict)
+
+ if w_patt is w_nil:
+ return (False, {})
+
+ #w_patt is symbol or primitive //as cdr of dotted list
+ match_dict[w_patt.to_string()] = w_expr
+ return (True, match_dict)
return (False, {})
-class SyntacticClosure(W_Root):
- def __init__(self, ctx, sexpr):
- assert not isinstance(sexpr, SyntacticClosure)
- assert isinstance(sexpr, W_Root)
- self.sexpr = sexpr
+class SymbolClosure(W_Symbol):
+ def __init__(self, ctx, symbol):
+ assert isinstance(symbol, W_Symbol)
+ assert not isinstance(symbol, SymbolClosure)
+ self.symbol = symbol
+ self.name = symbol.name
self.closure = ctx
def eval_tr(self, ctx):
#this symbol is in Syntactic Closure
- return self.sexpr.eval_tr(self.closure)
+ return self.symbol.eval_tr(self.closure)
+
+ def to_string(self):
+ #return "#<closure: " + self.sexpr.to_string() + ">"
+ return self.symbol.to_string()
+
+ def __repr__(self):
+ return "<sc:W_Symbol " + self.to_string() + ">"
+
+class PairClosure(W_Pair):
+ def __init__(self, ctx, pair):
+ assert isinstance(pair, W_Pair)
+ assert not isinstance(pair, PairClosure)
+ self.pair = pair
+ self.car = pair.car
+ self.cdr = pair.cdr
+ self.closure = ctx
+
+ def eval_tr(self, ctx):
+ #this pair is in Syntactic Closure
+ return self.pair.eval_tr(self.closure)
def to_string(self):
#return "#<closure: " + self.sexpr.to_string() + ">"
- return self.sexpr.to_string()
+ return self.pair.to_string()
+
+ def __repr__(self):
+ return "<sc:W_Pair " + self.to_string() + ">"
class W_Transformer(W_Procedure):
def __init__(self, syntax_lst, ctx, pname=""):
@@ -950,16 +999,31 @@
# enviroment at the point of use
#not always needed, because w_sub can have no W_Symbol inside
- if isinstance(w_sub, W_Symbol) or isinstance(w_sub, W_Pair):
- return SyntacticClosure(ctx, w_sub)
+ if isinstance(w_sub, W_Symbol) and \
+ not isinstance(w_sub, SymbolClosure):
+ return SymbolClosure(ctx, w_sub)
+
+ if isinstance(w_sub, W_Pair) and \
+ not isinstance(w_sub, PairClosure):
+ return PairClosure(ctx, w_sub)
+
+ if isinstance(w_sub, Ellipsis):
+ raise w_sub
return w_sub
return sexpr
elif isinstance(sexpr, W_Pair):
- w_pair = W_Pair(self.substitute(ctx, sexpr.car, match_dict),
- self.substitute(ctx, sexpr.cdr, match_dict))
+ try:
+ w_pair = W_Pair(self.substitute(ctx, sexpr.car, match_dict),
+ self.substitute(ctx, sexpr.cdr, match_dict))
+ except Ellipsis, e:
+ scdr = sexpr.cdr
+ if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis:
+ return e.expr
+ else:
+ raise SchemeSyntaxError
w_paircar = w_pair.car
if isinstance(w_paircar, W_Symbol):
@@ -972,8 +1036,7 @@
except UnboundVariable:
pass
- elif isinstance(w_paircar, SyntacticClosure) and \
- isinstance(w_paircar.sexpr, W_Symbol):
+ elif isinstance(w_paircar, SymbolClosure):
try:
#ops, which context?
w_macro = ctx.get(w_paircar.sexpr.to_string())
@@ -1043,7 +1106,6 @@
w_formal = lst.car
while isinstance(w_formal, W_Pair):
w_def = w_formal.get_car_as_pair()
- #evaluate the values in caller ctx
w_transformer = w_def.get_cdr_as_pair().car.eval(ctx)
if not isinstance(w_transformer, W_Transformer):
raise SchemeSyntaxError
Modified: pypy/dist/pypy/lang/scheme/ssparser.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/ssparser.py (original)
+++ pypy/dist/pypy/lang/scheme/ssparser.py Wed Aug 1 16:23:19 2007
@@ -2,7 +2,8 @@
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, symbol, \
- w_nil, W_Boolean, W_Real, quote, qq, unquote, unquote_splicing
+ w_nil, W_Boolean, W_Real, quote, qq, unquote, unquote_splicing, \
+ w_ellipsis
def str_unquote(s):
str_lst = []
@@ -29,13 +30,18 @@
IGNORE*
return {symbol(c)};
+ ELLIPSIS:
+ c = '...'
+ IGNORE*
+ return {w_ellipsis};
+
FIXNUM:
c = `\-?(0|([1-9][0-9]*))`
IGNORE*
return {W_Integer(int(c))};
FLOAT:
- c = `\-?[0-9]*\.[0-9]*`
+ c = `\-?([0-9]*\.[0-9]+|[0-9]+\.[0-9]*)`
IGNORE*
return {W_Real(float(c))};
@@ -83,6 +89,7 @@
| qq
| unquote_splicing
| unquote
+ | ELLIPSIS
| FLOAT
| FIXNUM
| BOOLEAN
Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/test/test_macro.py (original)
+++ pypy/dist/pypy/lang/scheme/test/test_macro.py Wed Aug 1 16:23:19 2007
@@ -236,6 +236,19 @@
assert eval_(ctx, "(my-or #f 42)").to_number() == 42
assert eval_(ctx, "(my-or #f #f 82)").to_number() == 82
+def test_macro_expand():
+ ctx = ExecutionContext()
+ eval_(ctx, """(define-syntax foo (syntax-rules ()
+ ((foo) #t)
+ ((foo arg) arg)))""")
+ eval_(ctx, """(define-syntax bar (syntax-rules ()
+ ((bar) (foo))
+ ((bar arg) (foo arg))))""")
+
+ w_expr = parse("(bar 42)")[0]
+ #should expand directly (recursively) to 42
+ assert ctx.get("bar").expand(ctx, w_expr).to_string() == "42"
+
def test_let_syntax():
ctx = ExecutionContext()
w_result = \
@@ -260,3 +273,32 @@
assert eval_(ctx, "a").to_number() == 0
+def test_reverse():
+ ctx = ExecutionContext()
+ eval_(ctx, """(define-syntax reverse-order
+ (syntax-rules ()
+ ((_ e) (reverse-order e ()))
+ ((_ (e . rest) r)
+ (reverse-order rest (e . r)))
+ ((_ () r) r)))""")
+
+ w_result = eval_(ctx, "(reverse-order (2 3 -))")
+ assert w_result.to_number() == 1
+
+def test_ellipsis_symbol():
+ ctx = ExecutionContext()
+ eval_(ctx, """(define-syntax or (syntax-rules ()
+ ((or) #f)
+ ((or e) e)
+ ((or e1 e2 ...)
+ (let ((temp e1))
+ (if temp
+ temp
+ (or e2 ...))))))""")
+
+ assert eval_(ctx, "(or 12)").to_number() == 12
+ assert eval_(ctx, "(or 12 42)").to_number() == 12
+ assert eval_(ctx, "(or #f 42)").to_number() == 42
+ assert eval_(ctx, "(or #f #f 82)").to_number() == 82
+ assert eval_(ctx, "(or #f #f #f 162)").to_number() == 162
+
Modified: pypy/dist/pypy/lang/scheme/test/test_parser.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/test/test_parser.py (original)
+++ pypy/dist/pypy/lang/scheme/test/test_parser.py Wed Aug 1 16:23:19 2007
@@ -2,6 +2,7 @@
from pypy.lang.scheme.ssparser import parse
from pypy.lang.scheme.object import W_Boolean, W_Real, W_Integer, W_String
from pypy.lang.scheme.object import W_Pair, W_Nil, W_Symbol, W_Symbol
+from pypy.rlib.parsing.makepackrat import BacktrackException
def parse_sexpr(expr):
return parse(expr)[0]
@@ -56,6 +57,15 @@
assert isinstance(w_float, W_Real)
assert unwrap(w_float) == -123456.1234
+ w_float = parse_sexpr('.1234')
+ assert isinstance(w_float, W_Real)
+ assert unwrap(w_float) == 0.1234
+ w_float = parse_sexpr('12.')
+ assert isinstance(w_float, W_Real)
+ assert unwrap(w_float) == 12.0
+
+ py.test.raises(BacktrackException, parse_sexpr, '.')
+
def test_sexpr():
w_list = parse_sexpr('( 1 )')
assert isinstance(w_list, W_Pair)
@@ -155,3 +165,8 @@
assert unwrap(t) == ['unquote-splicing', ['list',
['unquote-splicing', 'b'], 3]]
+def test_ellipsis():
+ w_float = parse_sexpr('...')
+ assert isinstance(w_float, W_Symbol)
+ assert unwrap(w_float) == "..."
+
More information about the pypy-svn
mailing list