[pypy-svn] r45351 - in pypy/dist/pypy/lang/scheme: . test
jlg at codespeak.net
jlg at codespeak.net
Thu Jul 26 17:27:54 CEST 2007
Author: jlg
Date: Thu Jul 26 17:27:54 2007
New Revision: 45351
Modified:
pypy/dist/pypy/lang/scheme/execution.py
pypy/dist/pypy/lang/scheme/object.py
pypy/dist/pypy/lang/scheme/test/test_macro.py
Log:
DefineSyntax and W_DerivedMacro (should not be first class object); now we can define simple macros; W_Transformer can be evaluated
Modified: pypy/dist/pypy/lang/scheme/execution.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/execution.py (original)
+++ pypy/dist/pypy/lang/scheme/execution.py Thu Jul 26 17:27:54 2007
@@ -53,6 +53,7 @@
'quote': Quote,
'quasiquote': QuasiQuote,
'syntax-rules': SyntaxRules,
+ 'define-syntax': DefineSyntax,
}
OPERATION_MAP = {}
@@ -83,9 +84,11 @@
def _dispatch(self, symb):
if isinstance(symb, W_Symbol):
return (self, symb.name)
- elif isinstance(symb, SyntacticClosure) and \
- isinstance(symb.sexpr, W_Symbol):
- return (symb.closure, symb.sexpr.name)
+
+ elif isinstance(symb, SyntacticClosure):
+ symbol = symb.sexpr
+ if isinstance(symbol, W_Symbol):
+ return (symb.closure, symbol.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 Thu Jul 26 17:27:54 2007
@@ -811,6 +811,9 @@
return W_Promise(lst.car, ctx)
+##
+# DerivedMacros
+##
class SyntaxRules(W_Macro):
def call(self, ctx, lst):
if not isinstance(lst, W_Pair):
@@ -869,36 +872,35 @@
w_patt = pattern
match_dict = {}
- while isinstance(w_patt, W_Pair):
- if w_expr is w_nil:
- return (False, {})
+ while isinstance(w_patt, W_Pair) and isinstance(w_expr, W_Pair):
w_pattcar = w_patt.car
+ w_exprcar = w_expr.car
w_literal = self.literals.get(w_pattcar.to_string(), None)
if w_literal is not None:
try:
- w_form = ctx.get(w_expr.car.to_string())
+ w_form = ctx.get(w_exprcar.to_string())
except UnboundVariable:
- w_form = w_expr.car
+ w_form = w_exprcar
if w_form is not w_literal:
return (False, {})
if isinstance(w_pattcar, W_Pair):
- if not isinstance(w_expr.car, W_Pair):
+ if not isinstance(w_exprcar, W_Pair):
return (False, {})
- (matched, match_nested) = self.match(w_expr.car, ctx, w_pattcar)
+ (matched, match_nested) = self.match(w_exprcar, ctx, w_pattcar)
if not matched:
return (False, {})
match_dict.update(match_nested)
- match_dict[w_pattcar.to_string()] = w_expr.car
+ match_dict[w_pattcar.to_string()] = w_exprcar
w_patt = w_patt.cdr
w_expr = w_expr.cdr
- if w_expr is w_nil:
+ if w_expr is w_nil and w_patt is w_nil:
return (True, match_dict)
return (False, {})
@@ -964,8 +966,35 @@
#we have lexical scopes:
# 1. in which macro was defined - self.closure
# 2. in which macro is called - ctx
- # 3. in which macro is expanded, and can introduce new bindings - expand_ctx
+ # 3. in which macro is expanded, can introduce new bindings - expand_ctx
expanded = self.expand(sexpr, ctx)
expand_ctx = self.closure.copy()
return expanded.eval(expand_ctx)
+ def procedure(self, ctx, lst):
+ return self.expand_eval(lst[0], ctx)
+
+class DefineSyntax(W_Macro):
+ def call(self, ctx, lst):
+ if not isinstance(lst, W_Pair):
+ raise SchemeSyntaxError
+
+ w_def = lst.car
+ if not isinstance(w_def, W_Symbol):
+ raise SchemeSyntaxError
+
+ w_syntax_rules = lst.get_cdr_as_pair().car
+ w_transformer = w_syntax_rules.eval(ctx)
+ assert isinstance(w_transformer, W_Transformer)
+
+ w_macro = W_DerivedMacro(w_def.name, w_transformer)
+ ctx.set(w_def.name, w_macro)
+ return w_macro
+
+class W_DerivedMacro(W_Macro):
+ def __init__(self, name, transformer):
+ self.name = name
+ self.transformer = transformer
+
+ def call(self, ctx, lst):
+ return self.transformer.expand_eval(W_Pair(W_Symbol(self.name), lst), ctx)
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 Thu Jul 26 17:27:54 2007
@@ -147,7 +147,7 @@
(letrec ((loop
(lambda (counter)
(if (= counter 0)
- ()
+ #f
(begin
body
(loop (- counter 1)))))))
@@ -174,3 +174,26 @@
eval_(ctx, "(define test 7)")
assert w_transformer.expand_eval(w_expr, ctx).to_number() == 5
+def test_transformer_eval():
+ ctx = ExecutionContext()
+ eval_(ctx, """(define foo (syntax-rules ()
+ ((_) #t)
+ ((_ bar) bar)))""")
+
+ w_foo = eval_(ctx, "(foo '(_))")
+ assert w_foo.to_boolean()
+
+ w_foobar = eval_(ctx, """(foo '(_ 42))""")
+ assert w_foobar.to_number() == 42
+
+def test_define_syntax():
+ ctx = ExecutionContext()
+ eval_(ctx, """(define-syntax foo (syntax-rules ()
+ ((_) #t)
+ ((_ bar) bar)))""")
+ w_foo = eval_(ctx, """(foo)""")
+ assert w_foo.to_boolean()
+
+ w_foobar = eval_(ctx, """(foo 42)""")
+ assert w_foobar.to_number() == 42
+
More information about the Pypy-commit
mailing list