Example #1
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)]))
Example #2
0
    def test_modulo(self):
        program = "(modulo 4 2)"
        self.assertEvaluatesTo(program, Integer(0))

        program = "(modulo 5 2)"
        self.assertEvaluatesTo(program, Integer(1))

        program = "(modulo -13 4)"
        self.assertEvaluatesTo(program, Integer(3))
Example #3
0
    def test_quotient(self):
        program = "(quotient 3 2)"
        self.assertEvaluatesTo(program, Integer(1))

        program = "(quotient 4 2)"
        self.assertEvaluatesTo(program, Integer(2))

        program = "(quotient -13 4)"
        self.assertEvaluatesTo(program, Integer(-3))
Example #4
0
    def test_multiplication(self):
        program = "(* 2 2 3)"
        self.assertEvaluatesTo(program, Integer(12))

        program = "(*)"
        self.assertEvaluatesTo(program, Integer(1))

        program = "(* 3 0.5)"
        self.assertEvaluatesTo(program, FloatingPoint(1.5))
Example #5
0
    def test_addition(self):
        program = "(+ 1 2 3)"
        self.assertEvaluatesTo(program, Integer(6))

        program = "(+)"
        self.assertEvaluatesTo(program, Integer(0))

        program = "(+ 1 2.5)"
        self.assertEvaluatesTo(program, FloatingPoint(3.5))
Example #6
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)))
Example #7
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)
Example #8
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)]))
Example #9
0
    def test_cond(self):
        program = "(cond ((else 1)))"
        self.assertEvaluatesTo(program, Integer(1))

        program = "(define x 1) (cond (((> x 0) 3) (else 1)))"
        self.assertEvaluatesTo(program, Integer(3))

        program = "(define y 1) (cond (((< y 0) 3) (else 1)))"
        self.assertEvaluatesTo(program, Integer(1))
Example #10
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())
Example #11
0
    def test_subtraction(self):
        program = "(- 1 2 3)"
        self.assertEvaluatesTo(program, Integer(-4))

        program = "(- 2)"
        self.assertEvaluatesTo(program, Integer(-2))

        program = "(- 0.1)"
        self.assertEvaluatesTo(program, FloatingPoint(-0.1))

        program = "(- 10.0 0.5)"
        self.assertEvaluatesTo(program, FloatingPoint(9.5))
Example #12
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())
Example #13
0
    def test_remainder(self):
        program = "(remainder 4 2)"
        self.assertEvaluatesTo(program, Integer(0))

        program = "(remainder 5 2)"
        self.assertEvaluatesTo(program, Integer(1))

        program = "(remainder -13 4)"
        self.assertEvaluatesTo(program, Integer(-1))

        program = "(remainder 13 -4)"
        self.assertEvaluatesTo(program, Integer(1))
Example #14
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)))
Example #15
0
 def test_for_each(self):
     program = """(let ((total 0))
  (for-each
     (lambda (x) (set! total (+ total x)))
     '(1 2 3))
  total)"""
     self.assertEvaluatesTo(program, Integer(6))
Example #16
0
def subtract(arguments):
    check_argument_number('-', arguments, 1)

    if len(arguments) == 1:
        # we just negate a single argument
        if isinstance(arguments[0], Integer):
            return Integer(-1 * arguments[0].value)
        elif isinstance(arguments[0], FloatingPoint):
            return FloatingPoint(-1 * arguments[0].value)
        else:
            raise SchemeTypeError("Subtraction is only defined for integers and "
                                  "floating point, you gave me %s." % arguments[0].__class__)

    total = copy(arguments[0])

    for argument in arguments.tail:
        if not isinstance(argument, Number):
            raise SchemeTypeError("Subtraction is only defined for numbers, "
                                  "you gave me %s." % argument.__class__)

        # subtracting a float from an integer gives us a float
        if isinstance(total, Integer) and isinstance(argument, FloatingPoint):
            total = FloatingPoint(float(total.value))

        total.value -= argument.value

    return total
Example #17
0
def vector_length(arguments):
    check_argument_number('vector-length', arguments, 1, 1)

    # todo: check type
    vector = arguments[0]

    return Integer(len(vector))
Example #18
0
def modulo(arguments):
    check_argument_number('modulo', arguments, 2, 2)

    if not isinstance(arguments[0], Integer) or not isinstance(arguments[1], Integer):
        raise SchemeTypeError("modulo is only defined for integers, "
                              "got %s and %s." % (arguments[0].__class__,
                                                  arguments[1].__class__))

    return Integer(arguments[0].value % arguments[1].value)
Example #19
0
def string_length(arguments):
    check_argument_number('string-length', arguments, 1, 1)

    string_atom = arguments[0]
    if not isinstance(string_atom, String):
        raise SchemeTypeError("string-length takes a string as its argument, "
                              "not a %s." % string_atom.__class__)

    string_length = len(string_atom.value)
    return Integer(string_length)
Example #20
0
def add(arguments):
    if not arguments:
        return Integer(0)

    if isinstance(arguments[0], Integer):
        total = Integer(0)
    elif isinstance(arguments[0], FloatingPoint):
        total = FloatingPoint(0.0)

    for argument in arguments:
        if not isinstance(argument, Number):
            raise SchemeTypeError("Addition is only defined for numbers, "
                                  "you gave me %s." % argument.__class__)

        # adding a float to an integer gives us a float
        if isinstance(total, Integer) and isinstance(argument, FloatingPoint):
            total = FloatingPoint(float(total.value))

        total.value += argument.value
    return total
Example #21
0
def multiply(arguments):
    if not arguments:
        return Integer(1)

    if isinstance(arguments[0], Integer):
        product = Integer(1)

    elif isinstance(arguments[0], FloatingPoint):
        product = FloatingPoint(1.0)

    for argument in arguments:
        if not isinstance(argument, Number):
            raise SchemeTypeError("Multiplication is only defined for numbers, "
                                  "you gave me %s." % argument.__class__)

        if isinstance(product, Integer) and isinstance(argument, FloatingPoint):
            product = FloatingPoint(float(product.value))

        product.value *= argument.value

    return product
Example #22
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)))))
Example #23
0
def remainder(arguments):
    check_argument_number('remainder', arguments, 2, 2)

    if not isinstance(arguments[0], Integer) or not isinstance(arguments[1], Integer):
        raise SchemeTypeError("remainder is only defined for integers, "
                              "got %s and %s." % (arguments[0].__class__,
                                                  arguments[1].__class__))

    # as with quotient, we can't use Python's integer division here because it floors rather than truncates
    x1 = arguments[0].value
    x2 = arguments[1].value
    value = x1 - (math.trunc(x1 / x2) * x2)

    return Integer(value)
Example #24
0
def quotient(arguments):
    # integer division
    check_argument_number('quotient', arguments, 2, 2)

    if not isinstance(arguments[0], Integer) or not isinstance(arguments[1], Integer):
        raise SchemeTypeError("quotient is only defined for integers, "
                              "got %s and %s." % (arguments[0].__class__,
                                                  arguments[1].__class__))

    # Python's integer division floors, whereas Scheme rounds towards zero
    x1 = arguments[0].value
    x2 = arguments[1].value
    result = math.trunc(x1 / x2)

    return Integer(result)
Example #25
0
 def test_if_two_arguments(self):
     program = "(if #t 1)"
     self.assertEvaluatesTo(program, Integer(1))
Example #26
0
 def test_procedure_call(self):
     program = "((if #f + *) 3 4)"
     self.assertEvaluatesTo(program, Integer(12))
Example #27
0
 def test_variable_evaluation(self):
     program = "(define x 28) x"
     self.assertEvaluatesTo(program, Integer(28))
Example #28
0
 def test_let_last_argument(self):
     program = "(let ((x 1)) 2 x)"
     self.assertEvaluatesTo(program, Integer(1))
Example #29
0
 def test_let(self):
     program = "(let ((x 1)) x)"
     self.assertEvaluatesTo(program, Integer(1))
Example #30
0
 def test_defmacro(self):
     program = '(defmacro inc (argument) `(+ 1 ,argument)) (inc 5)'
     self.assertEvaluatesTo(program, Integer(6))