def test_lexical_scope(self): assert self.eval(""" (begin (define-syntax swap (syntax-rules () ((swap a b) ((lambda (tmp) (set! a b) (set! b tmp)) a)))) (define foo 4) (define tmp 5) (swap foo tmp) (cons foo tmp))""") == pair(5, 4) assert self.eval(""" (begin (define foo 10) (define-syntax stx (syntax-rules () ((_ a) (cons a foo)))) ((lambda (foo) (stx foo)) 100))""") == pair(100, 10) assert self.eval(""" (begin (define-syntax def10 (syntax-rules () ((_ var) (define var 10)))) (def10 foo) foo)""") == 10
def test_basic_literal(self): assert self.eval(""" (begin (define <-> 5) (define-syntax my-syntax (syntax-rules (<->) ((_ a <-> b) (list b a)))) ; assignment doesn't change lexical binding (set! <-> 6) (my-syntax 3 <-> 4))""") == pair(4, pair(3, None))
def test_apply(self): assert self.eval("(apply +)") == 0 assert self.eval("(apply + 1 '())") == 1 assert self.eval("(apply + '(1))") == 1 assert self.eval("(apply + (list 1))") == 1 assert self.eval("(apply + 1 '(2))") == 3 assert self.eval("(apply - 3 '(2 1))") == 0 assert self.eval("(apply (lambda (x) x) 1 '())") == 1 assert_raises(WrongArgNumber, self.eval, "(apply (lambda (x) x) 1 '(2))") assert self.eval("(apply (lambda x x) 1 '(2 3))") == pair(1, pair(2, pair(3, None)))
def test_lambda(self): assert self.eval("((lambda (x) x) 5)") == 5 assert self.eval("((lambda (x) (+ x 1)) 5)") == 6 assert self.eval("((lambda () 5))") == 5 assert self.eval("((lambda x (first x)) 1 2)") == 1 assert self.eval("((lambda x (first x)) 1 2 3 4 5)") == 1 assert self.eval("((lambda x (first x)) 1)") == 1 assert self.eval("((lambda x x) 1 2)") == pair(1, pair(2, None)) assert self.eval("((lambda (x . y) x) 1)") == 1 assert self.eval("((lambda (x . y) y) 1)") == None assert self.eval("((lambda (x . y) (first y)) 1 2 3)") == 2
def test_improper_list(self): m = macro("(() ((_ a . b) b))") assert trans(m, "(_ 1)") == None assert trans(m, "(_ 1 2)") == pair(2, None) assert trans(m, "(_ 1 . 2)") == 2 assert trans(m, "(_ 1 . (2 3))") == pair(2, pair(3, None)) assert_raises(SyntaxError, trans, m, "(_)") m = macro("(() ((_ a . 2) a))") assert trans(m, "(_ 5 . 2)") == 5 assert_raises(SyntaxError, trans, m, "(_ 5 2)") assert_raises(SyntaxError, trans, m, "(_ 5 . 3)")
def test_apply(self): assert self.eval('(apply +)') == 0 assert self.eval("(apply + 1 '())") == 1 assert self.eval("(apply + '(1))") == 1 assert self.eval("(apply + (list 1))") == 1 assert self.eval("(apply + 1 '(2))") == 3 assert self.eval("(apply - 3 '(2 1))") == 0 assert self.eval("(apply (lambda (x) x) 1 '())") == 1 assert_raises(WrongArgNumber, self.eval, "(apply (lambda (x) x) 1 '(2))") assert self.eval("(apply (lambda x x) 1 '(2 3))") == pair( 1, pair(2, pair(3, None)))
def test_map(self): assert self.eval("(map + '(1 2) '(3 4))") == pair(4, pair(6, None)) assert self.eval("(map + '(1 2 3))") == pair(1, pair(2, pair(3, None))) assert self.eval("(map (lambda (x y) (pair x y)) '(1 2) '(3 4))") == \ pair(pair(1, 3), pair(pair(2, 4), None)) assert_raises(WrongArgNumber, self.eval, "(map (lambda (x y) (pair x y)) '(1 2))") assert_raises(WrongArgType, self.eval, "(map + '(1 2 3 . 4))") assert_raises(MiscError, self.eval, "(map + '(1 2) '(3 4 5))")
def test_pair(self): assert self.eval('(pair 1 2)') == pair(1, 2) assert self.eval('(cons 1 2)') == pair(1, 2) assert self.eval('(first (pair 1 2))') == 1 assert self.eval('(car (pair 1 2))') == 1 assert self.eval('(rest (pair 1 2))') == 2 assert self.eval('(cdr (pair 1 2))') == 2 assert self.eval("""(begin (define foo (pair 1 2)) (set-car! foo 3) foo)""") == pair(3, 2) assert self.eval("""(begin (define foo (pair 1 2)) (set-cdr! foo 3) foo)""") == pair(1, 3)
def filter_dc(expr): if isinstance(expr, DynamicClosure): return filter_dc(expr.expression) if isinstance(expr, pair): return pair(filter_dc(expr.first), filter_dc(expr.rest)) return expr
def test_map(self): assert self.eval("(map + '(1 2) '(3 4))") == pair(4, pair(6, None)) assert self.eval("(map + '(1 2 3))") == pair(1, pair(2, pair(3, None))) assert self.eval("(map (lambda (x y) (pair x y)) '(1 2) '(3 4))") == pair(pair(1, 3), pair(pair(2, 4), None)) assert_raises(WrongArgNumber, self.eval, "(map (lambda (x y) (pair x y)) '(1 2))") assert_raises(WrongArgType, self.eval, "(map + '(1 2 3 . 4))") assert_raises(MiscError, self.eval, "(map + '(1 2) '(3 4 5))")
def test_set_x(self): assert self.eval(""" (begin (define foo 5) (define bar foo) (set! foo 6) (pair foo bar))""") == pair(6, 5) assert self.eval("(set! pair 10)") == 10 assert_raises(UnboundVariable, self.eval, "(set! var-not-exist 10)")
def test_pair(self): assert self.eval("(pair 1 2)") == pair(1, 2) assert self.eval("(cons 1 2)") == pair(1, 2) assert self.eval("(first (pair 1 2))") == 1 assert self.eval("(car (pair 1 2))") == 1 assert self.eval("(rest (pair 1 2))") == 2 assert self.eval("(cdr (pair 1 2))") == 2 assert ( self.eval( """(begin (define foo (pair 1 2)) (set-car! foo 3) foo)""" ) == pair(3, 2) ) assert ( self.eval( """(begin (define foo (pair 1 2)) (set-cdr! foo 3) foo)""" ) == pair(1, 3) )
def test_list(self): assert self.eval('(list 1 2 3)') == pair(1, pair(2, pair(3, None)))
def test_quasiquote(self): assert p("`1") == pair(sym('quasiquote'), pair(1, None)) assert p("`,1") == pair(sym('quasiquote'), pair(pair(sym('unquote'), pair(1, None)), None)) assert p("`(1 ,(+ 1 5) ,@(list 1 2))") == \ pair(sym("quasiquote"), pair(pair(1, pair(pair(sym("unquote"), pair(pair(sym("+"), pair(1, pair(5, None))), None)), pair(pair(sym("unquote-slicing"), pair(pair(sym("list"), pair(1, pair(2, None))), None)), None))), None))
def test_quote(self): assert p("'1") == pair(sym('quote'), pair(1, None)) assert p("''1") == pair(sym('quote'), pair(pair(sym('quote'), pair(1, None)), None))
def test_pair(self): assert p('(1 . 2)') == pair(1, 2) assert p('(1 .2)') == pair(1, 2) assert p('(1 2 . 3)') == pair(1, pair(2, 3))
def test_list(self): assert p('(1 2 3)') == pair(1, pair(2, pair(3, None))) assert p('(1)') == pair(1, None) assert p('()') == None assert p('(1 2 3 4)') == pair(1, pair(2, pair(3, pair(4, None))))
def test_list(self): assert p('(1 2 3)') == pair(1, pair(2, pair(3, None))) assert p('(1)') == pair(1, None) assert p('()') == None
def test_variable(self): m = macro("(() ((_ a) a))") assert trans(m, "(_ 5)") == 5 assert trans(m, "(_ (1 2))") == pair(1, pair(2, None)) assert_raises(SyntaxError, trans, m, "(_ 1 2)")
def test_list(self): assert self.eval("(list 1 2 3)") == pair(1, pair(2, pair(3, None)))