def test_syntax_rules_expand(): ctx = ExecutionContext() w_transformer = eval_(ctx, """(syntax-rules () ((_ var) (let ((temp 1)) (+ var temp))))""") w_expr = parse_("(_ 12)") w_expanded = w_transformer.expand(ctx, w_expr) assert w_expanded.to_string() == "(let ((temp 1)) (+ 12 temp))" assert w_transformer.expand_eval(ctx, w_expr).to_number() == 13 #transparency eval_(ctx, "(define temp 12)") w_expr = parse_("(_ temp)") w_expanded = w_transformer.expand(ctx, w_expr) assert w_expanded.to_string() == "(let ((temp 1)) (+ temp temp))" # the two occurrences of 'temp in (+ temp temp) are not the same symbol! assert w_transformer.expand_eval(ctx, w_expr).to_number() == 13 #define in closure, should not affect macro eval closure = ctx.copy() eval_(closure, "(define + -)") assert w_transformer.expand_eval(closure, w_expr).to_number() == 13 #define in top level - should affect macro eval eval_(ctx, "(define + -)") assert w_transformer.expand_eval(ctx, w_expr).to_number() == 11
def test_syntax_rules_expand(): ctx = ExecutionContext() w_transformer = eval_( ctx, """(syntax-rules () ((_ var) (let ((temp 1)) (+ var temp))))""") w_expr = parse_("(_ 12)") w_expanded = w_transformer.expand(ctx, w_expr) assert w_expanded.to_string() == "(let ((temp 1)) (+ 12 temp))" assert w_transformer.expand_eval(ctx, w_expr).to_number() == 13 #transparency eval_(ctx, "(define temp 12)") w_expr = parse_("(_ temp)") w_expanded = w_transformer.expand(ctx, w_expr) assert w_expanded.to_string() == "(let ((temp 1)) (+ temp temp))" # the two occurrences of 'temp in (+ temp temp) are not the same symbol! assert w_transformer.expand_eval(ctx, w_expr).to_number() == 13 #define in closure, should not affect macro eval closure = ctx.copy() eval_(closure, "(define + -)") assert w_transformer.expand_eval(closure, w_expr).to_number() == 13 #define in top level - should affect macro eval eval_(ctx, "(define + -)") assert w_transformer.expand_eval(ctx, w_expr).to_number() == 11
def test_ctx_sets(): w_fnum = W_Integer(42) w_fnum2 = W_Integer(43) w_fnum3 = W_Integer(44) ctx = ExecutionContext() ctx.put("v1", w_fnum) ctx2 = ctx.copy() assert w_fnum is ctx2.get("v1") ctx.set("v1", w_fnum2) assert w_fnum2 is ctx2.get("v1") assert w_fnum2 is ctx.get("v1") ctx2.put("v1", w_fnum3) assert w_fnum3 is ctx2.get("v1")
def test_syntax_rules_literals(): ctx = ExecutionContext() # => is literal, should be matched exactly # w_transformer created in ctx w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") w_expr = parse_("(foo 12 boo)") py.test.raises(MatchError, w_transformer.match, ctx, w_expr) w_expr = parse_("(foo bar boo)") py.test.raises(MatchError, w_transformer.match, ctx, w_expr) # exact match w_expr = parse_("(foo => boo)") # within the same context assert w_transformer.match(ctx, w_expr)[0].to_boolean() w_42 = W_Number(42) # different lexical scope, not the same bindings for => in ctx and closure closure = ctx.copy() closure.put("=>", w_42) w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") py.test.raises(MatchError, w_transformer.match, closure, w_expr) # different lexical scope, not the same bindings for => in ctx and closure ctx.put("=>", W_Number(12)) assert ctx.get("=>") is not closure.get("=>") w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") py.test.raises(MatchError, w_transformer.match, closure, w_expr) # the same object for => in ctx and closure, but different bindings # <arigo> I think this should also raise MatchError. When R5RS says # "same binding" it probably means bound to the same *location*, not # just that there is the same object in both locations ctx.put("=>", w_42) assert ctx.get("=>") is closure.get("=>") w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))") py.test.raises(MatchError, w_transformer.match, closure, w_expr)