def test_var(self): env = types.Environment() expr = interop.read_str("a") result = compile(expr, env=env) self.assertEqual(result.code, bytes([OpCode.READ_VAR_1.value, 0, OpCode.RET.value])) self.assertEqual(result.variables, [expr])
def test_const(self): env = types.Environment() expr = interop.read_str("123456") result = compile(expr, env=env) self.assertEqual(result.code, bytes([OpCode.CONST_1.value, 0, OpCode.RET.value])) self.assertEqual(result.constants, [123456])
def test_if_non_tail(self): symbol_table = types.symbol_table() env = types.Environment(bindings={ symbol_table["if"]: Builtins.IF, symbol_table["+"]: base.plus, }) expr = interop.read_str("(+ (if #t 3 4) 5)", symbol_table=symbol_table) result = compile(expr, env=env) self.assertEqual( result.code, bytes([ OpCode.READ_VAR_1.value, 0, OpCode.CONST_1.value, 0, OpCode.JUMP_IF_NOT_3.value, 0, 0, 14, OpCode.CONST_1.value, 1, OpCode.JUMP_3.value, 0, 0, 16, OpCode.CONST_1.value, 2, OpCode.CONST_1.value, 3, OpCode.TAIL_CALL_1.value, 2, ])) self.assertEqual(result.variables, [symbol_table["+"]]) self.assertEqual(result.constants, [True, 3, 4, 5])
def test_quote(self): symbol_table = types.symbol_table() env = types.Environment( bindings={symbol_table["quote"]: Builtins.QUOTE}) expr = interop.read_str("'abc", symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, symbol_table["abc"])
def test_lambda(self): symbol_table = types.symbol_table() env = types.Environment( bindings={symbol_table["lambda"]: Builtins.LAMBDA}) expr = interop.read_str("((lambda () 1))", symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, 1)
def test_set_error(self): symbol_table = types.symbol_table() env = types.Environment(bindings={ symbol_table["set!"]: Builtins.SET, }) expr = interop.read_str("(set! x 8)", symbol_table=symbol_table) with self.assertRaises(exceptions.IdentifierNotBoundError): result = eval.eval(expr, env=env)
def test_recursive(self): n = 100 string = "(+ 1 " * n + ")" * n symbol_table = types.symbol_table() env = types.Environment(bindings={symbol_table["+"]: base.plus}) expr = interop.read_str(string, symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, n)
def test_quote(self): symbol_table = types.symbol_table() env = types.Environment( bindings={symbol_table["quote"]: Builtins.QUOTE}) expr = interop.read_str("'a", symbol_table=symbol_table) result = compile(expr, env=env) self.assertEqual(result.code, bytes([OpCode.CONST_1.value, 0, OpCode.RET.value])) self.assertEqual(result.variables, []) self.assertEqual(result.constants, [symbol_table["a"]])
def test_define(self): symbol_table = types.symbol_table() x = symbol_table['x'] env = types.Environment(bindings={ symbol_table["define"]: Builtins.DEFINE, }) expr = interop.read_str("(define x 5)", symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, False) self.assertEqual(env[x], 5)
def test_define_set(self): symbol_table = types.symbol_table() x = symbol_table['x'] env = types.Environment(bindings={ symbol_table["set!"]: Builtins.SET, x: 3, }) expr = interop.read_str("(set! x 8)", symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, False) self.assertEqual(env[x], 8)
def test_lambda_rest(self): symbol_table = types.symbol_table() env = types.Environment( bindings={ symbol_table["lambda"]: Builtins.LAMBDA, symbol_table["quote"]: Builtins.QUOTE, }) expr = interop.read_str("((lambda (x :rest y) y) 1 2 3)", symbol_table=symbol_table) result = eval.eval(expr, env=env) result_list = interop.from_scheme_list(result) self.assertEqual(result_list, [2, 3])
def test_set(self): symbol_table = types.symbol_table() env = types.Environment(bindings={symbol_table["set!"]: Builtins.SET}) x = symbol_table["x"] expr = interop.read_str("(set! x 3)", symbol_table=symbol_table) result = compile(expr, env=env) self.assertEqual( result.code, bytes([ OpCode.CONST_1.value, 0, OpCode.SET_VAR_1.value, 0, OpCode.PUSH_FALSE.value, OpCode.RET.value ])) self.assertEqual(result.variables, [x]) self.assertEqual(result.constants, [3])
def test_lexical_scope(self): symbol_table = types.symbol_table() lexical = symbol_table['lexical'] dynamic = symbol_table['dynamic'] env = types.Environment( bindings={ symbol_table["lambda"]: Builtins.LAMBDA, symbol_table["quote"]: Builtins.QUOTE, }) expr = interop.read_str(""" ((lambda (x) (((lambda (x) (lambda () x)) 'lexical))) 'dynamic) """, symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, lexical)
def test_set_local(self): symbol_table = types.symbol_table() x = symbol_table['x'] env = types.Environment( bindings={ symbol_table["lambda"]: Builtins.LAMBDA, symbol_table["set!"]: Builtins.SET, x: 3, }) expr = interop.read_str(""" ((lambda () (set! x 8) x)) """, symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, 8) self.assertEqual(env[x], 8)
def test_call(self): symbol_table = types.symbol_table() env = types.Environment(bindings={symbol_table["+"]: None}) expr = interop.read_str("(+ 10 20)", symbol_table=symbol_table) result = compile(expr, env=env) self.assertEqual( result.code, bytes([ OpCode.READ_VAR_1.value, 0, OpCode.CONST_1.value, 0, OpCode.CONST_1.value, 1, OpCode.TAIL_CALL_1.value, 2, ])) self.assertEqual(result.variables, [symbol_table["+"]]) self.assertEqual(result.constants, [10, 20])
def test_lambda_arg(self): symbol_table = types.symbol_table() env = types.Environment( bindings={symbol_table["lambda"]: Builtins.LAMBDA}) x = symbol_table["x"] expr = interop.read_str("(lambda (x) x)", symbol_table=symbol_table) result = compile(expr, env=env) self.assertEqual( result.code, bytes([ OpCode.CONST_1.value, 0, OpCode.MAKE_CLOSURE.value, OpCode.RET.value ])) self.assertEqual(result.variables, []) self.assertIsInstance(result.constants[0], Bytecode) self.assertEqual(result.constants[0].code, bytes([OpCode.READ_VAR_1.value, 0, OpCode.RET.value])) self.assertEqual(result.constants[0].constants, []) self.assertEqual(result.constants[0].variables, [x]) self.assertEqual(result.constants[0].formals, [x])
def test_if_tail(self): symbol_table = types.symbol_table() env = types.Environment(bindings={symbol_table["if"]: Builtins.IF}) expr = interop.read_str("(if #t 3 4)", symbol_table=symbol_table) result = compile(expr, env=env) self.assertEqual( result.code, bytes([ OpCode.CONST_1.value, 0, OpCode.JUMP_IF_NOT_3.value, 0, 0, 9, OpCode.CONST_1.value, 1, OpCode.RET.value, OpCode.CONST_1.value, 2, OpCode.RET.value, ])) self.assertEqual(result.variables, []) self.assertEqual(result.constants, [True, 3, 4])
def test_if_false(self): symbol_table = types.symbol_table() env = types.Environment(bindings={symbol_table["if"]: Builtins.IF}) expr = interop.read_str("(if #f 2 3)", symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, 3)
def test_fun_call_order(self): symbol_table = types.symbol_table() env = types.Environment(bindings={symbol_table["-"]: base.minus}) expr = interop.read_str("(- 1 2 3)", symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, -4)
def test_fun_call(self): symbol_table = types.symbol_table() env = types.Environment(bindings={symbol_table["+"]: base.plus}) expr = interop.read_str("(+ 1 2)", symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, 3)
def test_number(self): env = types.Environment() expr = interop.read_str("3") result = eval.eval(expr, env=env) self.assertEqual(result, 3)
def test_variable(self): symbol_table = types.symbol_table() env = types.Environment(bindings={symbol_table["a"]: 5}) expr = interop.read_str("a", symbol_table=symbol_table) result = eval.eval(expr, env=env) self.assertEqual(result, 5)