def test_simple_defun(self): env = [] interpret(""" (defun triple (x y z) (cons x (cons y (cons z 'nil)))) """, env) assert_equals('(a b c)', interpret("(triple 'a 'b 'c)", env))
def test_function_call(self): assert_equals('(a b)', interpret("((lambda (x) (cons x '(b))) 'a)")) assert_equals('(z b c)', interpret(""" ((lambda (x y) (cons x (cdr y))) 'z '(a b c)) """))
def test_simple_defun(self): env = [] interpret( """ (defun triple (x y z) (cons x (cons y (cons z 'nil)))) """, env) assert_equals('(a b c)', interpret("(triple 'a 'b 'c)", env))
def test_function_call(self): assert_equals('(a b)', interpret("((lambda (x) (cons x '(b))) 'a)")) assert_equals( '(z b c)', interpret(""" ((lambda (x y) (cons x (cdr y))) 'z '(a b c)) """))
def test_recursive_function_with_defun(self): env = [] interpret(""" (defun subst (x y z) (cond ((atom z) (cond ((eq z y) x) ('t z))) ('t (cons (subst x y (car z)) (subst x y (cdr z)))))) """, env) assert_equals('(a m (a m c) d)', interpret("(subst 'm 'b '(a b (a b c) d))", env))
def test_recursive_function_with_defun(self): env = [] interpret( """ (defun subst (x y z) (cond ((atom z) (cond ((eq z y) x) ('t z))) ('t (cons (subst x y (car z)) (subst x y (cdr z)))))) """, env) assert_equals('(a m (a m c) d)', interpret("(subst 'm 'b '(a b (a b c) d))", env))
def test_eval_cond(self): program = """ (eval '(cond ((atom x) 'atom) ('t 'list)) '((x '(a b)))) """ assert_equals('list', interpret(program, self.env))
def test_calling_argument_as_function(self): assert_equals( '(a b c)', interpret(""" ((lambda (f) (f '(b c))) '(lambda (x) (cons 'a x))) """))
def test_eval_lambda_direct(self): program = """ (eval '((lambda (x y) (cons x (cdr y))) 'a '(b c d)) 'nil) """ assert_equals('(a c d)', interpret(program, self.env))
def test_eval_label(self): program = """ (eval '((label firstatom (lambda (x) (cond ((atom x) x) ('t (firstatom (car x)))))) y) '((y ((a b) (c d))))) """ assert_equals('a', interpret(program, self.env))
def test_recursive_function_with_label(self): assert_equals('(a m (a m c) d)', interpret(""" ((label subst (lambda (x y z) (cond ((atom z) (cond ((eq z y) x) ('t z))) ('t (cons (subst x y (car z)) (subst x y (cdr z))))))) 'm 'b '(a b (a b c) d)) """))
def test_recursive_function_with_label(self): assert_equals( '(a m (a m c) d)', interpret(""" ((label subst (lambda (x y z) (cond ((atom z) (cond ((eq z y) x) ('t z))) ('t (cons (subst x y (car z)) (subst x y (cdr z))))))) 'm 'b '(a b (a b c) d)) """))
def test_eval_lookup(self): assert_equals('a', interpret("(eval 'x '((x a) (y b)))", self.env))
def test_assoc(self): assert_equals('a', interpret("(assoc 'x '((x a) (y b)))", self.env)) assert_equals('b', interpret("(assoc 'y '((x a) (y b)))", self.env)) assert_equals('new', interpret("(assoc 'x '((x new) (x a) (y b)))", self.env))
def test_zip(self): assert_equals('((x a) (y b) (z c))', interpret("(zip '(x y z) '(a b c))", self.env))
def test_append(self): assert_equals('(a b c d)', interpret("(append '(a b) '(c d))", self.env)) assert_equals('(c d)', interpret("(append 'nil '(c d))", self.env))
def test_quote(self): assert_equals('a', interpret('(quote a)')) assert_equals('a', interpret("'a")) assert_equals('(a b c)', interpret("(quote (a b c))")) assert_equals('(a b c)', interpret("'(a b c)"))
def test_eval_lambda_lookup(self): program = """ (eval '(f '(b c)) '((f (lambda (x) (cons 'a x))))) """ assert_equals('(a b c)', interpret(program, self.env))
def test_null(self): assert_equals('f', interpret("(null 'a)", self.env)) assert_equals('t', interpret("(null 'nil)", self.env))
def test_cond(self): lisp = """ (cond ((eq 'a 'b) 'first) ((atom 'a) 'second)) """ assert_equals('second', interpret(lisp))
def test_cdr(self): assert_equals('(b c)', interpret("(cdr '(a b c))")) assert_equals('nil', interpret("(cdr '(a))"))
def test_car(self): assert_equals('a', interpret("(car '(a b c))"))
def test_eq(self): assert_equals('t', interpret("(eq 'a 'a)")) assert_equals('f', interpret("(eq 'a 'b)")) assert_equals('f', interpret("(eq '(a) '(a))"))
def test_atom(self): assert_equals('t', interpret("(atom 'a)")) assert_equals('f', interpret("(atom '(a b c))")) assert_equals('t', interpret("(atom 'nil)")) assert_equals('t', interpret("(atom (atom 'a))")) assert_equals('f', interpret("(atom '(atom 'a))"))
def test_eval_eq(self): assert_equals('t', interpret("(eval '(eq 'a 'a) 'nil)", self.env))
def test_and(self): assert_equals('t', interpret("(and (atom 'a) (eq 'a 'a))", self.env)) assert_equals('f', interpret("(and (atom 'a) (eq 'a 'b))", self.env))
def test_eval_cons(self): program = """ (eval '(cons x '(b c)) '((x a) (y b))) """ assert_equals('(a b c)', interpret(program, self.env))
def test_or(self): assert_equals('t', interpret("(or (atom 'a) (eq 'a 'b))", self.env)) assert_equals('t', interpret("(or 't 't)", self.env)) assert_equals('t', interpret("(or 'f 't)", self.env)) assert_equals('t', interpret("(or 't 'f)", self.env)) assert_equals('f', interpret("(or 'f 'f)", self.env))
def test_calling_argument_as_function(self): assert_equals('(a b c)', interpret(""" ((lambda (f) (f '(b c))) '(lambda (x) (cons 'a x))) """))
def test_not(self): assert_equals('f', interpret("(not (eq 'a 'a))", self.env)) assert_equals('t', interpret("(not (eq 'a 'b))", self.env))
def test_cons(self): assert_equals('(a b c)', interpret("(cons 'a '(b c))")) assert_equals('(a)', interpret("(cons 'a 'nil)")) assert_equals('(a b c)', interpret("(cons 'a (cons 'b (cons 'c 'nil)))")) assert_equals('a', interpret("(car (cons 'a '(b c)))")) assert_equals('(b c)', interpret("(cdr (cons 'a '(b c)))"))
def test_evaluating_atoms(self): assert_equals('foo', interpret('a', [('a', 'foo')]))