def test_execution_integration(): """ Computing pi by integrating: \\frac{\\pi}{2} = \\int^1_{-1} \\sqrt{1 - x^2} dx """ code = """ let delta_x: real = 0.001 let x: real = -1 let y: real = sqrt(1 - x * x) let result: real while x + delta_x < 1 do let next_x: real = x + delta_x let next_y: real = sqrt(1 - next_x * next_x) result = result + (y + next_y) / 2 * delta_x y = next_y x = next_x end print(result * 2) """ stack = Stack() stack.add_global("print", Function(([Real], Void))) stack.add_global("sqrt", Function(([Real], Real))) expressions = parser.parse(code, stack) context = ExecutionContext(dict(print=MagicMock(), sqrt=math.sqrt)) context.compile(expressions) context.execute(MockTracebackWriter()) return_value = context.globals["print"].call_args[0][0] assert abs(return_value - math.pi) < 0.01
def test_library_init_stack(): lib = Library() @lib.function([Integer], Integer) def func1(): pass @lib.function([Real], Real) def func2(): pass stack = Stack() lib.initialize_stack(stack) assert stack.get_variable("func1").type == Function(([Integer], Integer)) assert stack.get_variable("func2").type == Function(([Real], Real))
def test_exception(): code = """ func f() throw() end f() """ stack = Stack() stack.add_global("throw", Function(([], Void))) expressions = parser.parse(code, stack) def throw_function(): raise ValueError("~~error~~") writer = MockTracebackWriter() writer.print_traceback = MagicMock() context = ExecutionContext({"throw": throw_function}) context.compile(expressions) context.execute(writer) error: RuntimeError = writer.print_traceback.call_args_list[0][0][0] assert str(error) == "~~error~~" assert tuple(error.stack_entries[0]) == ("f", 2) assert tuple(error.stack_entries[1]) == (None, 3) assert context.code_map[2] == 2 assert context.code_map[3] == 5
def test_invalid_argument_types(self): with pytest.raises(FunctionArgumentsError): stack = Stack() stack.add_variable("var", Set(Real)) stack.add_variable("func", Function((([Integer, List(Integer)]), Integer))) tree = tr("func_call", "func", tr("int_literal", "1"), tr("variable", "var")) parser.handle(tree, stack)
def test_invalid_arguments_count_many(self): with pytest.raises(FunctionArgumentsError): stack = Stack() stack.add_variable("func", Function(([Integer, Integer], Integer))) tree = tr("func_call", "func", tr("int_literal", "1"), tr("int_literal", "1"), tr("int_literal", "1")) parser.handle(tree, stack)
def test_flip_flops(): code = """ let count: int while top[1, 1] != top[2, 2] or count == 0 do RUR'U' count = count + 1 end out(count) """ out_fn = MagicMock() stack = Stack() finish_function = MagicMock() cube_runtime = CubeRuntime(Cube((3, 3, 3)), Orientation(), lambda action: None, finish_function) cube_runtime.functions.initialize_stack(stack) stdlib.initialize_stack(stack) stack.add_global("out", Function(([Integer], Void))) globals = {"out": out_fn, **stdlib.exec_globals, **cube_runtime.functions.exec_globals} executor = ExecutionContext(globals) executor.compile(parser.parse(code, stack)) executor.execute(MockTracebackWriter()) cube_runtime.finished() out_fn.assert_called_once_with(6) finish_function.assert_called_once()
def test_no_args(self): stack = Stack() stack.add_global("func", Function(([], Integer))) tree = tr("func_call", "func") expression = parser.handle(tree, stack) assert expression.type == Integer assert expression.expression == ["func", "()"]
def test_execution_simple(): code = """ let x: int = -15 let y: int = x * abs(x + a) print(x * y) """ stack = Stack() stack.add_global("a", Integer) stack.add_global("abs", Function(([Integer], Integer))) stack.add_global("print", Function(([Integer], Void))) expressions = parser.parse(code, stack) globals = {"a": 10, "abs": abs, "print": MagicMock()} context = ExecutionContext(globals) context.compile(expressions) context.execute(MockTracebackWriter()) assert tuple(globals["print"].call_args[0]) == (1125, )
def test_no_arguments_no_return(self): tree = tr("func_decl", "func_name", tr("clause")) stack = Stack() expression = parser.handle(tree, stack) assert isinstance(expression, FunctionDeclarationExpression) assert expression.name == "var_0" assert expression.symbol_name == "func_name" assert expression.arguments == [] assert expression.return_type == Void assert stack.get_variable("func_name").type == Function(([], Void))
def test_no_return(self): tree = tr("func_decl", "func_name", tr("argument", "a", tr("type_int")), tr("clause", tr("variable", "a"))) stack = Stack() expression = parser.handle(tree, stack) assert isinstance(expression, FunctionDeclarationExpression) assert expression.name == "var_0" assert expression.symbol_name == "func_name" assert expression.arguments == ["var_0"] assert expression.return_type == Void assert expression.clause[0].expression == ["var_0"] assert expression.clause[0].type == Integer assert stack.get_variable("func_name").type == Function(([Integer], Void))
def test_pascals_triangle(): """ Computes five lines of Pascal's triangle: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 Values are returned via `print` function line by line separated by `0`. """ code = """ let result: list of list of int let row_size: int = 1 repeat 5 times let row: list of int = new_list(row_size, 1) let i: int = 1 while i < row_size - 1 do row[i] = result[size(result) - 1][i] + result[size(result) - 1][i - 1] i = i + 1 end add_last(result, row) row_size = row_size + 1 end for row in result do for x in row do print(x) end print(0) end """ stack = Stack() stack.add_global("print", Function(([Integer], Void))) stdlib.initialize_stack(stack) expressions = parser.parse(code, stack) print_fn = MagicMock() context = ExecutionContext(dict(print=print_fn, **stdlib.exec_globals)) context.compile(expressions) context.execute(MockTracebackWriter()) return_value = [x[0][0] for x in print_fn.call_args_list] assert return_value == [ 1, 0, 1, 1, 0, 1, 2, 1, 0, 1, 3, 3, 1, 0, 1, 4, 6, 4, 1, 0 ]
def test_default(self): tree = tr("func_decl", "func_name", tr("argument", "a", tr("type_int")), tr("argument", "b", tr("type_real")), tr("type_bool"), tr("clause", tr("variable", "a"), tr("variable", "b"))) stack = Stack() expression = parser.handle(tree, stack) assert isinstance(expression, FunctionDeclarationExpression) assert expression.name == "var_0" assert expression.symbol_name == "func_name" assert expression.arguments == ["var_0", "var_1"] assert expression.return_type == Bool assert expression.clause[0].expression == ["var_0"] assert expression.clause[0].type == Integer assert expression.clause[1].expression == ["var_1"] assert expression.clause[1].type == Real assert stack.get_variable("func_name").type == Function(([Integer, Real], Bool))
def test_function_call(self, is_global): stack = Stack() stack.add_variable("array", List(Integer)) func = Function(([Integer, Real, List(Integer)], Void)) if is_global: stack.add_global("func", func) else: stack.add_variable("func", func) tree = tr("func_call", "func", tr("int_literal", "1"), tr("int_literal", "2"), tr("variable", "array")) expression = parser.handle(tree, stack) assert expression.type == Void func_name = "func" if is_global else "var_1" assert expression.expression == [func_name, "(", "1", ", ", "2", ", ", "var_0", ")"]
def test_execution_gcd(): code = """ let a: int = 15 let b: int = 6 while a != 0 and b != 0 do if a > b then a = a - b else b = b - a end end print (a + b) """ stack = Stack() stack.add_global("print", Function(([Integer], Void))) expressions = parser.parse(code, stack) context = ExecutionContext(dict(print=MagicMock())) context.compile(expressions) context.execute(MockTracebackWriter()) assert tuple(context.globals["print"].call_args[0]) == (3, )
def test_functions(): code = """ func compute() func r(x: int): int func g(x: int): int return x - 1 end let c: int while x != 0 do x = g(x) c = c + 1 end return c end let i: int = 1 while true do if i == 5 then return end print(r(i)) i = i + 1 end end compute() """ stack = Stack() stack.add_global("print", Function(([Integer], Void))) stdlib.initialize_stack(stack) expressions = parser.parse(code, stack) print_fn = MagicMock() context = ExecutionContext(dict(print=print_fn, **stdlib.exec_globals)) context.compile(expressions) context.execute(MockTracebackWriter()) return_value = [x[0][0] for x in print_fn.call_args_list] assert return_value == [1, 2, 3, 4]
def test_orient(): code = """ orient top: {G--/---/---}, bottom: {--Y/---/---} then out(red) else-orient top: {-W-/---/---}, right: {---/---/-O-} then out(top[1, 1]) end """ out_fn = MagicMock() stack = Stack() cube_runtime = CubeRuntime(Cube((3, 3, 3)), Orientation(), lambda action: None, lambda: None) cube_runtime.functions.initialize_stack(stack) stdlib.initialize_stack(stack) stack.add_global("out", Function(([Color], Void))) globals = {"out": out_fn, **stdlib.exec_globals, **cube_runtime.functions.exec_globals} executor = ExecutionContext(globals) executor.compile(parser.parse(code, stack)) executor.execute(MockTracebackWriter()) cube_runtime.finished() out_fn.assert_called_once_with(orientation.Color.WHITE)
import typing import pytest from cubelang.compiler.types import Type, Integer, Real, Bool, List, Set, Function, Void, type_annotation_to_type, T, \ Color, Side @pytest.mark.parametrize("type_object, representation", [(Integer, "Integer"), (Real, "Real"), (Bool, "Bool"), (Void, "Void"), (List(Set(Integer)), "List(Set(Integer))"), (Set(Bool), "Set(Bool)"), (Function(([Integer, Real, List(Bool)], Void)), "Function(([Integer, Real, List(Bool)], Void))")]) def test_repr(type_object: Type, representation: str): assert repr(type_object) == representation @pytest.mark.parametrize("type_object, string", [(Integer, "int"), (Real, "real"), (Bool, "bool"), (Void, "void"), (List(Set(Integer)), "list of set of int"), (Set(Bool), "set of bool")]) def test_repr(type_object: Type, string: str): assert str(type_object) == string @pytest.mark.parametrize("type1, type2, result", [(Integer, Integer, True), (Integer, Real, False), (Real, Integer, True), (Bool, Bool, True), (Bool, Integer, False),
def test_function_arguments_generic(args: typing.List[Type], return_type: Type): func = Function(([T, List(T)], Set(T)), ([Set(List(T))], Integer), ([Set(T), List(T)], T)) assert func.takes_arguments(args) == return_type
def test_function_arguments(args: typing.List[Type], return_type: Type): func = Function(([Integer, Integer], Integer), ([Integer, Real], Bool), ([Real, Real], Color), ([Real, List(Integer)], Real), ([Color, Real, ...], Side)) res = func.takes_arguments(args) assert res == return_type
def test_variadic_expansion(arguments, amount, expected): assert Function.expand_variadic(arguments, amount) == expected