예제 #1
0
    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)))
예제 #2
0
    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)))
예제 #3
0
    def test_cdr(self):
        program = "(cdr (quote (1 2 3)))"
        self.assertEvaluatesTo(program, Cons.from_list([Integer(2), Integer(3)]))

        program = "(cdr (quote (1 2 3)) 1)"
        with self.assertRaises(SchemeArityError):
            self.evaluate(program)
예제 #4
0
    def test_list(self):
        program = "(list)"
        self.assertEvaluatesTo(program, Nil())

        program = "(list 1 (+ 2 3))"
        self.assertEvaluatesTo(program,
                               Cons.from_list([Integer(1),
                                               Integer(5)]))
예제 #5
0
    def test_quasiquote_sugar(self):
        program = "`,1"
        self.assertEvaluatesTo(program, Integer(1))

        program = "`(1 ,@'(2 2))"
        self.assertEvaluatesTo(
            program, Cons.from_list([Integer(1),
                                     Integer(2),
                                     Integer(2)]))
예제 #6
0
    def test_cdr(self):
        program = "(cdr (quote (1 2 3)))"
        self.assertEvaluatesTo(program,
                               Cons.from_list([Integer(2),
                                               Integer(3)]))

        program = "(cdr (quote (1 2 3)) 1)"
        with self.assertRaises(SchemeArityError):
            self.evaluate(program)
예제 #7
0
    def test_quote(self):
        program = "(quote (1 2 3))"
        self.assertEvaluatesTo(
            program, Cons.from_list([Integer(1),
                                     Integer(2),
                                     Integer(3)]))

        program = "(quote ())"
        self.assertEvaluatesTo(program, Nil())
예제 #8
0
    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)))
예제 #9
0
    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())
예제 #10
0
    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)))))
예제 #11
0
    def recursive_eval_unquote(s_expression, _environment):
        """Return a copy of s_expression, with all occurrences of
        unquoted s-expressions replaced by their evaluated values.

        Note that we can only have unquote-splicing in a sublist,
        since we can only return one value, e.g `,@(1 2 3).

        """
        if isinstance(s_expression, Atom):
            return (s_expression, _environment)

        elif isinstance(s_expression, Nil):
            return (s_expression, _environment)

        elif s_expression[0] == Symbol("unquote"):
            check_argument_number('unquote', arguments, 1, 1)
            return eval_s_expression(s_expression[1], _environment)

        else:
            # return a list of s_expressions that have been
            # recursively checked for unquote
            list_elements = []

            for element in s_expression:
                if isinstance(element, Cons) and \
                        element[0] == Symbol('unquote-splicing'):
                    check_argument_number('unquote-splicing', element.tail, 1,
                                          1)

                    (result,
                     _environment) = eval_s_expression(element[1],
                                                       _environment)

                    if not isinstance(result, Cons) and not isinstance(
                            result, Nil):
                        raise SchemeArityError(
                            "unquote-splicing requires a list.")

                    for item in result:
                        list_elements.append(item)

                else:
                    (result, _environment) = recursive_eval_unquote(
                        element, _environment)
                    list_elements.append(result)

            return (Cons.from_list(list_elements), _environment)
예제 #12
0
    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)))))
예제 #13
0
    def expand_then_eval(arguments, _environment):
        """Expand this macro once, then continue evaluation."""
        if is_variadic:
            if len(arguments) < len(macro_arguments):
                raise SchemeArityError(
                    "Macro %s takes at least %d arguments, but got %d." %
                    (macro_name, len(macro_arguments), len(arguments)))

        else:
            if len(arguments) != len(macro_arguments):
                raise SchemeArityError(
                    "Macro %s takes %d arguments, but got %d." %
                    (macro_name, len(macro_arguments), len(arguments)))

        new_environment = dict(_environment)
        for (variable_name, variable_value) in zip(macro_arguments, arguments):
            new_environment[variable_name] = variable_value

        if is_variadic:
            remaining_arguments = []
            for index, arg in enumerate(arguments):
                if index >= len(macro_arguments):
                    remaining_arguments.append(arg)

            new_environment[variadic_argument_name] = Cons.from_list(
                remaining_arguments)

        (s_expression_after_expansion,
         new_environment) = eval_s_expression(replacement_body,
                                              new_environment)

        # restore old environment, ignoring variables hidden by scope
        for variable_name in _environment:
            if variable_name not in macro_arguments:
                _environment[variable_name] = new_environment[variable_name]

        # continue evaluation where we left off
        return eval_s_expression(s_expression_after_expansion, _environment)
예제 #14
0
 def test_vector_to_list(self):
     program = "(vector->list (vector 1 2))"
     self.assertEvaluatesTo(program,
                            Cons.from_list([Integer(1),
                                            Integer(2)]))
예제 #15
0
def p_list_unquotesplicingsugar(p):
    "list : UNQUOTESPLICINGSUGAR sexpression"
    # convert ,foo to (unquote foo)
    p[0] = Cons(Symbol("unquote-splicing"), Cons(p[2]))
예제 #16
0
 def test_set_car(self):
     program = "(define x (list 4 5 6)) (set-car! x 1) x"
     self.assertEvaluatesTo(program, Cons.from_list([Integer(1), Integer(5), Integer(6)]))
예제 #17
0
    def test_quasiquote_sugar(self):
        program = "`,1"
        self.assertEvaluatesTo(program, Integer(1))

        program = "`(1 ,@'(2 2))"
        self.assertEvaluatesTo(program, Cons.from_list([Integer(1), Integer(2), Integer(2)]))
예제 #18
0
 def test_quote_sugar(self):
     program = "'(1 2 3)"
     self.assertEvaluatesTo(program, Cons.from_list([Integer(1), Integer(2), Integer(3)]))
예제 #19
0
 def test_quote_sugar(self):
     program = "'(1 2 3)"
     self.assertEvaluatesTo(
         program, Cons.from_list([Integer(1),
                                  Integer(2),
                                  Integer(3)]))
예제 #20
0
def cons(arguments):
    # TODO: check type as well as arity
    check_argument_number('cons', arguments, 2, 2)

    return Cons(arguments[0], arguments[1])
예제 #21
0
 def test_set_car(self):
     program = "(define x (list 4 5 6)) (set-car! x 1) x"
     self.assertEvaluatesTo(
         program, Cons.from_list([Integer(1),
                                  Integer(5),
                                  Integer(6)]))
예제 #22
0
    def test_quote(self):
        program = "(quote (1 2 3))"
        self.assertEvaluatesTo(program, Cons.from_list([Integer(1), Integer(2), Integer(3)]))

        program = "(quote ())"
        self.assertEvaluatesTo(program, Nil())
예제 #23
0
 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)))
예제 #24
0
    def test_list(self):
        program = "(list)"
        self.assertEvaluatesTo(program, Nil())

        program = "(list 1 (+ 2 3))"
        self.assertEvaluatesTo(program, Cons.from_list([Integer(1), Integer(5)]))
예제 #25
0
def p_list_quasiquotesugar(p):
    "list : QUASIQUOTESUGAR sexpression"
    # convert `foo to (quasiquote foo)
    p[0] = Cons(Symbol("quasiquote"), Cons(p[2]))
예제 #26
0
def p_list_unquotesugar(p):
    "list : UNQUOTESUGAR sexpression"
    # convert ,foo to (unquote foo)
    p[0] = Cons(Symbol("unquote"), Cons(p[2]))
예제 #27
0
 def test_map(self):
     program = "(map (lambda (x) (+ x 1)) '(2 3))"
     self.assertEvaluatesTo(program, Cons(Integer(3), Cons(Integer(4))))
예제 #28
0
    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)))
예제 #29
0
def p_listarguments_one(p):
    "listarguments : sexpression listarguments"
    # a list is therefore a nested tuple:
    p[0] = Cons(p[1], p[2])
예제 #30
0
 def test_vector_to_list(self):
     program = "(vector->list (vector 1 2))"
     self.assertEvaluatesTo(program, Cons.from_list([Integer(1), Integer(2)]))
예제 #31
0
def p_program(p):
    "program : sexpression program"
    p[0] = Cons(p[1], p[2])