def test_quasiquote(self): program = "(quasiquote (1 1))" self.assertEvaluatesTo(program, Cons.from_list([Integer(1), Integer(1)])) program = "(quasiquote (unquote 1))" self.assertEvaluatesTo(program, Integer(1)) program = "(quasiquote (1 (unquote (+ 2 2))))" self.assertEvaluatesTo(program, Cons(Integer(1), Cons(Integer(4)))) program = "(quasiquote (1 (unquote-splicing '(2 2))))" self.assertEvaluatesTo( program, Cons(Integer(1), Cons(Integer(2), Cons(Integer(2)))))
def test_cons(self): program = "(cons 1 (quote (2 3)))" self.assertEvaluatesTo( program, Cons.from_list([Integer(1), Integer(2), Integer(3)])) program = "(cons 1 2)" self.assertEvaluatesTo(program, Cons(Integer(1), Integer(2)))
def test_car_cdr_compositions(self): program = "(caar '((1 3) 2))" self.assertEvaluatesTo(program, Integer(1)) program = "(cadr '((1 3) 2))" self.assertEvaluatesTo(program, Integer(2)) program = "(cdar '((1 3) 2))" self.assertEvaluatesTo(program, Cons(Integer(3))) program = "(cddr '((1 3) 2))" self.assertEvaluatesTo(program, Nil())
def test_variadic_function_definition(self): # test that we can put nothing in the impure list parameter program = "(define (foo . args) 1) (foo)" self.assertEvaluatesTo(program, Integer(1)) # test that we can put multiple things in the impure list parameter program = "(define (f . everything) everything) (f 1 2 3)" self.assertEvaluatesTo( program, Cons.from_list([Integer(1), Integer(2), Integer(3)])) # test that the improper list parameter is evaluated program = "(define (g . everything) everything) (g (+ 2 3))" self.assertEvaluatesTo(program, Cons(Integer(5)))
def cons(arguments): # TODO: check type as well as arity check_argument_number('cons', arguments, 2, 2) return Cons(arguments[0], arguments[1])
def test_map(self): program = "(map (lambda (x) (+ x 1)) '(2 3))" self.assertEvaluatesTo(program, Cons(Integer(3), Cons(Integer(4))))
def test_set_cdr(self): program = "(define x (list 4 5 6)) (set-cdr! x 1) x" result = self.evaluate(program) self.assertEqual(result, Cons(Integer(4), Integer(1)))
def p_listarguments_one(p): "listarguments : sexpression listarguments" # a list is therefore a nested tuple: p[0] = Cons(p[1], p[2])
def p_list_unquotesplicingsugar(p): "list : UNQUOTESPLICINGSUGAR sexpression" # convert ,foo to (unquote foo) p[0] = Cons(Symbol("unquote-splicing"), Cons(p[2]))
def p_list_unquotesugar(p): "list : UNQUOTESUGAR sexpression" # convert ,foo to (unquote foo) p[0] = Cons(Symbol("unquote"), Cons(p[2]))
def p_list_quasiquotesugar(p): "list : QUASIQUOTESUGAR sexpression" # convert `foo to (quasiquote foo) p[0] = Cons(Symbol("quasiquote"), Cons(p[2]))
def p_program(p): "program : sexpression program" p[0] = Cons(p[1], p[2])