def test_recursive_macro(): ctx = ExecutionContext() eval_( ctx, """(define-syntax my-or (syntax-rules () ((my-or) #f) ((my-or arg) arg) ((my-or arg1 arg2) (if arg1 arg1 (my-or arg2))) ((my-or arg1 arg2 arg3) (if arg1 arg1 (my-or arg2 arg3)))))""") assert eval_(ctx, "(my-or)").to_boolean() is False assert eval_(ctx, "(my-or 12)").to_number() == 12 #should expand recursively and after that eval w_expr = parse_("(my-or 12 42)") assert ctx.get("my-or").expand(ctx, w_expr).to_string() == \ "(if 12 12 42)" w_expr = parse_("(my-or 12 42 82)") assert ctx.get("my-or").expand(ctx, w_expr).to_string() == \ "(if 12 12 (if 42 42 82))" assert eval_(ctx, "(my-or 12 42)").to_number() == 12 assert eval_(ctx, "(my-or #f 42)").to_number() == 42 assert eval_(ctx, "(my-or #f #f 82)").to_number() == 82
def test_recursive_macro(): ctx = ExecutionContext() eval_(ctx, """(define-syntax my-or (syntax-rules () ((my-or) #f) ((my-or arg) arg) ((my-or arg1 arg2) (if arg1 arg1 (my-or arg2))) ((my-or arg1 arg2 arg3) (if arg1 arg1 (my-or arg2 arg3)))))""") assert eval_(ctx, "(my-or)").to_boolean() is False assert eval_(ctx, "(my-or 12)").to_number() == 12 #should expand recursively and after that eval w_expr = parse_("(my-or 12 42)") assert ctx.get("my-or").expand(ctx, w_expr).to_string() == \ "(if 12 12 42)" w_expr = parse_("(my-or 12 42 82)") assert ctx.get("my-or").expand(ctx, w_expr).to_string() == \ "(if 12 12 (if 42 42 82))" assert eval_(ctx, "(my-or 12 42)").to_number() == 12 assert eval_(ctx, "(my-or #f 42)").to_number() == 42 assert eval_(ctx, "(my-or #f #f 82)").to_number() == 82
def test_loop(): ctx = ExecutionContext() eval_(ctx, "(define k 'none)") eval_(ctx, "(define num 'none)") w_result = eval_( ctx, """ (call/cc (lambda (return) (letrec ((loop (lambda (n) (if (zero? n) 0 (begin (call/cc (lambda (cc) (set! k cc) (return n))) (set! num n) (loop (- n 1))))))) (loop 10))))""", ) assert w_result.to_number() == 10 assert isinstance(ctx.get("k"), Continuation) assert ctx.get("num").to_string() == "none" for i in range(9, -1, -1): w_result = eval_(ctx, "(k)") assert w_result.to_number() == i assert ctx.get("num").to_number() == i + 1 w_result = eval_(ctx, "(k)") assert w_result.to_number() == 0 assert ctx.get("num").to_number() == 1
def test_loop(): ctx = ExecutionContext() eval_(ctx, "(define k 'none)") eval_(ctx, "(define num 'none)") w_result = eval_( ctx, """ (call/cc (lambda (return) (letrec ((loop (lambda (n) (if (zero? n) 0 (begin (call/cc (lambda (cc) (set! k cc) (return n))) (set! num n) (loop (- n 1))))))) (loop 10))))""") assert w_result.to_number() == 10 assert isinstance(ctx.get("k"), Continuation) assert ctx.get("num").to_string() == "none" for i in range(9, -1, -1): w_result = eval_(ctx, "(k)") assert w_result.to_number() == i assert ctx.get("num").to_number() == i + 1 w_result = eval_(ctx, "(k)") assert w_result.to_number() == 0 assert ctx.get("num").to_number() == 1
def test_let_define(): ctx = ExecutionContext() eval_( ctx, """(define oo (let ((cont (call/cc (lambda (k) k)))) cont))""") assert isinstance(ctx.get("oo"), Continuation) eval_(ctx, "(oo +)") assert ctx.get("oo") is ctx.get("+")
def test_ctx(): w_fnum = W_Integer(12) w_symb = W_Symbol("symb") ctx = ExecutionContext() ctx.put("v1", w_fnum) ctx.put("symb", w_symb) assert w_symb is ctx.get("symb") assert w_fnum is ctx.get("v1") py.test.raises(UnboundVariable, ctx.get, "no_such_key")
def test_ctx(): w_fnum = W_Integer(12) w_symb = W_Symbol("symb") ctx = ExecutionContext() ctx.put("v1", w_fnum) ctx.put("symb", w_symb) assert w_symb is ctx.get("symb") assert w_fnum is ctx.get("v1") py.test.raises(UnboundVariable, ctx.get, "no_such_key")
def test_let_define(): ctx = ExecutionContext() eval_( ctx, """(define oo (let ((cont (call/cc (lambda (k) k)))) cont))""", ) assert isinstance(ctx.get("oo"), Continuation) eval_(ctx, "(oo +)") assert ctx.get("oo") is ctx.get("+")
def test_if_evaluation(): ctx = ExecutionContext() eval_(ctx, "(define then #f)") eval_(ctx, "(define else #f)") eval_(ctx, "(if #t (define then #t) (define else #t))") assert ctx.get("then").to_boolean() is True assert ctx.get("else").to_boolean() is False eval_(ctx, "(define then #f)") eval_(ctx, "(define else #f)") eval_(ctx, "(if #f (define then #t) (define else #t))") assert ctx.get("then").to_boolean() is False assert ctx.get("else").to_boolean() is True
def test_if_evaluation(): ctx = ExecutionContext() eval_(ctx, "(define then #f)") eval_(ctx, "(define else #f)") eval_(ctx, "(if #t (define then #t) (define else #t))") assert ctx.get("then").to_boolean() is True assert ctx.get("else").to_boolean() is False eval_(ctx, "(define then #f)") eval_(ctx, "(define else #f)") eval_(ctx, "(if #f (define then #t) (define else #t))") assert ctx.get("then").to_boolean() is False assert ctx.get("else").to_boolean() is True
def test_lambda_call(): ctx = ExecutionContext() eval_(ctx, "(define c1 'none)") eval_(ctx, "(define c2 'none)") eval_( ctx, """(define fun (lambda (x y z) (call/cc (lambda (k) (set! c1 k))) (+ x y z)))""") assert ctx.get("c1").to_string() == "none" assert ctx.get("c2").to_string() == "none" eval_( ctx, """(fun (call/cc (lambda (k) (set! c2 k) 1)) 2 3)""") w_result = eval_(ctx, "(c1)") assert w_result.to_number() == 6 w_result = eval_(ctx, "(c2 0)") assert w_result.to_number() == 5 w_result = eval_(ctx, "(c1)") assert w_result.to_number() == 5 w_result = eval_(ctx, "(c2 5)") assert w_result.to_number() == 10 w_result = eval_(ctx, "(c1)") assert w_result.to_number() == 10
def test_ctx_define(): ctx = ExecutionContext() eval_(ctx, "(define v1 42)") assert ctx.get("v1").to_number() == 42 w_num = eval_(ctx, "v1") assert w_num.to_number() == 42 eval_(ctx, "(define v2 2.1)") assert ctx.get("v2").to_number() == 2.1 w_num = eval_(ctx, "(+ 1 v1 v2)") assert w_num.to_number() == 45.1 eval_(ctx, "(define v2 3.1)") w_num = eval_(ctx, "(+ 1 v1 v2)") assert w_num.to_number() == 46.1
def test_ctx_define(): ctx = ExecutionContext() eval_(ctx, "(define v1 42)") assert ctx.get("v1").to_number() == 42 w_num = eval_(ctx, "v1") assert w_num.to_number() == 42 eval_(ctx, "(define v2 2.1)") assert ctx.get("v2").to_number() == 2.1 w_num = eval_(ctx, "(+ 1 v1 v2)") assert w_num.to_number() == 45.1 eval_(ctx, "(define v2 3.1)") w_num = eval_(ctx, "(+ 1 v1 v2)") assert w_num.to_number() == 46.1
def test_hefty1_computation(): ctx = ExecutionContext() eval_(ctx, "(define side-effects '())") eval_( ctx, """ (define (hefty-computation do-other-stuff) (letrec ((loop (lambda (n) (set! side-effects (cons (list 'hefty-a n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (set! side-effects (cons (list 'hefty-b n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (set! side-effects (cons (list 'hefty-c n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (if (zero? n) '() (loop (- n 1)))))) (loop 1)))""") eval_( ctx, """ (define (superfluous-computation do-other-stuff) (letrec ((loop (lambda () (set! side-effects (cons 'break side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (loop)))) (loop)))""") eval_(ctx, "(hefty-computation superfluous-computation)") assert ctx.get("side-effects").to_string() == \ """(break (hefty-c 0) break (hefty-b 0) break (hefty-a 0) break (hefty-c 1) break (hefty-b 1) break (hefty-a 1))"""
def test_begin(): ctx = ExecutionContext() w_global = W_Integer(0) ctx.put("var", w_global) w_result = eval_(ctx, "(begin (set! var 11) (+ var 33))") assert w_result.to_number() == 44 assert ctx.get("var").to_number() == 11
def test_begin(): ctx = ExecutionContext() w_global = W_Integer(0) ctx.put("var", w_global) w_result = eval_(ctx, "(begin (set! var 11) (+ var 33))") assert w_result.to_number() == 44 assert ctx.get("var").to_number() == 11
def test_sete(): ctx = ExecutionContext() eval_(ctx, "(define x 42)") loc1 = ctx.get_location("x") eval_(ctx, "(set! x 43)") loc2 = ctx.get_location("x") assert ctx.get("x").to_number() == 43 assert loc1 is loc2 py.test.raises(UnboundVariable, eval_, ctx, "(set! y 42)")
def test_sete(): ctx = ExecutionContext() eval_(ctx, "(define x 42)") loc1 = ctx.get_location("x") eval_(ctx, "(set! x 43)") loc2 = ctx.get_location("x") assert ctx.get("x").to_number() == 43 assert loc1 is loc2 py.test.raises(UnboundVariable, eval_, ctx, "(set! y 42)")
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)
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)
def test_deep_recursion(): ctx = ExecutionContext() eval_(ctx, "(define a 0)") eval_(ctx, """ (define loop (lambda (n) (set! a (+ a 1)) (if (= n 0) n (loop (- n 1)))))""") eval_(ctx, "(loop 2000)") assert ctx.get("a").to_number() == 2001
def test_evaluator(): ctx = ExecutionContext() eval_(ctx, "(define a 0)") w_obj = parse("(let () (set! a 42) a)")[0] (w_expr, new_ctx) = w_obj.eval_tr(ctx) assert ctx.get("a").to_number() == 42 assert isinstance(w_expr, W_Symbol) assert new_ctx is not ctx assert isinstance(new_ctx, ExecutionContext) (w_obj, newer_ctx) = w_expr.eval_tr(new_ctx) assert isinstance(w_obj, W_Number) assert w_obj.to_number() == 42 assert newer_ctx is None
def test_deep_recursion(): ctx = ExecutionContext() eval_(ctx, "(define a 0)") eval_( ctx, """ (define loop (lambda (n) (set! a (+ a 1)) (if (= n 0) n (loop (- n 1)))))""") eval_(ctx, "(loop 2000)") assert ctx.get("a").to_number() == 2001
def test_evaluator(): ctx = ExecutionContext() eval_(ctx, "(define a 0)") w_obj = parse("(let () (set! a 42) a)")[0] (w_expr, new_ctx) = w_obj.eval_tr(ctx) assert ctx.get("a").to_number() == 42 assert isinstance(w_expr, W_Symbol) assert new_ctx is not ctx assert isinstance(new_ctx, ExecutionContext) (w_obj, newer_ctx) = w_expr.eval_tr(new_ctx) assert isinstance(w_obj, W_Number) assert w_obj.to_number() == 42 assert newer_ctx is None
def test_lambda_fac(): ctx = ExecutionContext() eval_(ctx, """ (define fac (lambda (n) (if (= n 1) n (* (fac (- n 1)) n))))""") assert isinstance(ctx.get("fac"), W_Lambda) w_result = eval_(ctx, "(fac 4)") assert w_result.to_number() == 24 w_result = eval_(ctx, "(fac 5)") assert w_result.to_number() == 120
def test_let(): ctx = ExecutionContext() w_global = W_Integer(0) ctx.put("var", w_global) w_result = eval_(ctx, "(let ((var 42) (x (+ 2 var))) (+ var x))") assert w_result.to_number() == 44 assert ctx.get("var") is w_global w_result = eval_(ctx, """ (let ((x (lambda () 1))) (let ((y (lambda () (x))) (x (lambda () 2))) (y)))""") assert w_result.to_number() == 1 py.test.raises(UnboundVariable, eval_noctx, "(let ((y 0) (x y)) x)")
def test_callcc_callcc(): ctx = ExecutionContext() w_procedure = eval_(ctx, "(call/cc call/cc)") assert isinstance(w_procedure, W_Procedure) print w_procedure eval_(ctx, "(define cont 'none)") w_result = eval_( ctx, """((call/cc call/cc) (lambda (k) (set! cont k) 'done))""") assert w_result.to_string() == "done" assert isinstance(eval_(ctx, "cont"), W_Procedure) eval_(ctx, "(cont +)") assert eval_(ctx, "cont") is ctx.get("+")
def test_lambda_fac(): ctx = ExecutionContext() eval_( ctx, """ (define fac (lambda (n) (if (= n 1) n (* (fac (- n 1)) n))))""") assert isinstance(ctx.get("fac"), W_Lambda) w_result = eval_(ctx, "(fac 4)") assert w_result.to_number() == 24 w_result = eval_(ctx, "(fac 5)") assert w_result.to_number() == 120
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_let(): ctx = ExecutionContext() w_global = W_Integer(0) ctx.put("var", w_global) w_result = eval_(ctx, "(let ((var 42) (x (+ 2 var))) (+ var x))") assert w_result.to_number() == 44 assert ctx.get("var") is w_global w_result = eval_( ctx, """ (let ((x (lambda () 1))) (let ((y (lambda () (x))) (x (lambda () 2))) (y)))""") assert w_result.to_number() == 1 py.test.raises(UnboundVariable, eval_noctx, "(let ((y 0) (x y)) x)")
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_callcc_callcc(): ctx = ExecutionContext() w_procedure = eval_(ctx, "(call/cc call/cc)") assert isinstance(w_procedure, W_Procedure) print w_procedure eval_(ctx, "(define cont 'none)") w_result = eval_( ctx, """((call/cc call/cc) (lambda (k) (set! cont k) 'done))""", ) assert w_result.to_string() == "done" assert isinstance(eval_(ctx, "cont"), W_Procedure) eval_(ctx, "(cont +)") assert eval_(ctx, "cont") is ctx.get("+")
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)") assert ctx.get("bar").expand(ctx, w_expr).to_string() == "(foo 42)" assert eval_(ctx, "(bar 42)").to_number() == 42 eval_(ctx, """(define-syntax foo (syntax-rules () ((foo) #t)))""") eval_(ctx, """(define-syntax bar (syntax-rules () ((bar) (quote (foo)))))""") assert eval_(ctx, "(bar)").to_string() == "(foo)"
def test_hefty2_computation(): ctx = ExecutionContext() eval_(ctx, "(define side-effects '())") eval_( ctx, """ (define (hefty-computation do-other-stuff) (letrec ((loop (lambda (n) (set! side-effects (cons (list 'hefty-a n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (set! side-effects (cons (list 'hefty-b n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (set! side-effects (cons (list 'hefty-c n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (if (zero? n) '() (loop (- n 1)))))) (loop 1)))""", ) eval_( ctx, """ (define (superfluous-computation do-other-stuff) (letrec ((loop (lambda () (lst-loop '(straight quarter-past half quarter-til)) (loop))) (lst-loop (lambda (lst) (if (pair? lst) (let ((graphic (car lst))) (set! side-effects (cons graphic side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (lst-loop (cdr lst))))))) (loop)))""", ) eval_(ctx, "(hefty-computation superfluous-computation)") assert ( ctx.get("side-effects").to_string() == """(quarter-past (hefty-c 0) straight (hefty-b 0) quarter-til (hefty-a 0) half (hefty-c 1) quarter-past (hefty-b 1) straight (hefty-a 1))""" )
def test_syntax_rules_hygenic_expansion(): ctx = ExecutionContext() w_transformer = eval_(ctx, """(syntax-rules () ((dotimes count body) (letrec ((loop (lambda (counter) (if (= counter 0) #f (begin body (loop (- counter 1))))))) (loop count))))""") w_expr = parse_("(dotimes 5 (set! counter (+ counter 1)))") py.test.raises(UnboundVariable, w_transformer.expand_eval, ctx, w_expr) eval_(ctx, "(define counter 0)") w_expr = parse_("(dotimes 5 (set! counter (+ counter 1)))") w_transformer.expand_eval(ctx, w_expr) assert ctx.get("counter").to_number() == 5
def test_hefty1_computation(): ctx = ExecutionContext() eval_(ctx, "(define side-effects '())") eval_( ctx, """ (define (hefty-computation do-other-stuff) (letrec ((loop (lambda (n) (set! side-effects (cons (list 'hefty-a n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (set! side-effects (cons (list 'hefty-b n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (set! side-effects (cons (list 'hefty-c n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (if (zero? n) '() (loop (- n 1)))))) (loop 1)))""", ) eval_( ctx, """ (define (superfluous-computation do-other-stuff) (letrec ((loop (lambda () (set! side-effects (cons 'break side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (loop)))) (loop)))""", ) eval_(ctx, "(hefty-computation superfluous-computation)") assert ( ctx.get("side-effects").to_string() == """(break (hefty-c 0) break (hefty-b 0) break (hefty-a 0) break (hefty-c 1) break (hefty-b 1) break (hefty-a 1))""" )
def test_syntax_rules_hygenic_expansion(): ctx = ExecutionContext() w_transformer = eval_( ctx, """(syntax-rules () ((dotimes count body) (letrec ((loop (lambda (counter) (if (= counter 0) #f (begin body (loop (- counter 1))))))) (loop count))))""") w_expr = parse_("(dotimes 5 (set! counter (+ counter 1)))") py.test.raises(UnboundVariable, w_transformer.expand_eval, ctx, w_expr) eval_(ctx, "(define counter 0)") w_expr = parse_("(dotimes 5 (set! counter (+ counter 1)))") w_transformer.expand_eval(ctx, w_expr) assert ctx.get("counter").to_number() == 5
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)") assert ctx.get("bar").expand(ctx, w_expr).to_string() == "(foo 42)" assert eval_(ctx, "(bar 42)").to_number() == 42 eval_( ctx, """(define-syntax foo (syntax-rules () ((foo) #t)))""") eval_( ctx, """(define-syntax bar (syntax-rules () ((bar) (quote (foo)))))""") assert eval_(ctx, "(bar)").to_string() == "(foo)"
def test_hefty2_computation(): ctx = ExecutionContext() eval_(ctx, "(define side-effects '())") eval_( ctx, """ (define (hefty-computation do-other-stuff) (letrec ((loop (lambda (n) (set! side-effects (cons (list 'hefty-a n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (set! side-effects (cons (list 'hefty-b n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (set! side-effects (cons (list 'hefty-c n) side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (if (zero? n) '() (loop (- n 1)))))) (loop 1)))""") eval_( ctx, """ (define (superfluous-computation do-other-stuff) (letrec ((loop (lambda () (lst-loop '(straight quarter-past half quarter-til)) (loop))) (lst-loop (lambda (lst) (if (pair? lst) (let ((graphic (car lst))) (set! side-effects (cons graphic side-effects)) (set! do-other-stuff (call/cc do-other-stuff)) (lst-loop (cdr lst))))))) (loop)))""") eval_(ctx, "(hefty-computation superfluous-computation)") assert ctx.get("side-effects").to_string() == \ """(quarter-past (hefty-c 0) straight (hefty-b 0) quarter-til (hefty-a 0) half (hefty-c 1) quarter-past (hefty-b 1) straight (hefty-a 1))"""
def test_lambda_call(): ctx = ExecutionContext() eval_(ctx, "(define c1 'none)") eval_(ctx, "(define c2 'none)") eval_( ctx, """(define fun (lambda (x y z) (call/cc (lambda (k) (set! c1 k))) (+ x y z)))""", ) assert ctx.get("c1").to_string() == "none" assert ctx.get("c2").to_string() == "none" eval_( ctx, """(fun (call/cc (lambda (k) (set! c2 k) 1)) 2 3)""", ) w_result = eval_(ctx, "(c1)") assert w_result.to_number() == 6 w_result = eval_(ctx, "(c2 0)") assert w_result.to_number() == 5 w_result = eval_(ctx, "(c1)") assert w_result.to_number() == 5 w_result = eval_(ctx, "(c2 5)") assert w_result.to_number() == 10 w_result = eval_(ctx, "(c1)") assert w_result.to_number() == 10