def test_global_variable_exist(): tree = tr("variable", "a") stack = Stack() stack.add_global("a", Real) expression: Expression = parser.handle(tree, stack) assert expression.type == Real assert expression.expression == ["a"]
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_comparision_incorrect(self, arg1, arg2): tree = tr("op_3_0", tr("variable", "a"), tr("variable", "b")) stack = Stack() stack.add_global("a", arg1) stack.add_global("b", arg2) with pytest.raises(CompileTimeError): parser.handle(tree, stack)
def test_if_wrong_type(): tree = tr("if_expression", tr("int_literal", "1"), tr("float_literal", "2"), tr("float_literal", "3")) with pytest.raises(ValueTypeError): 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_operators(self, op1_type: str, op2_type: str, op_name: str, res_type: Type, res_expr: str): tree = tr(op_name, tr(op1_type, "1"), tr(op2_type, "2")) expr: Expression = parser.handle(tree, Stack()) assert expr.type == res_type assert expr.intermediates == [] assert "".join(expr.expression) == res_expr
def test_indices_right(self): tree = tr("cube_turn_range", tr("cube_left"), tr("range_open_right", tr("int_literal", "1"))) expr = parser.handle(tree, Stack()) assert isinstance(expr, CubeTurningExpression) assert len(expr.indices) == 2 assert expr.indices[0].expression == ["1"] assert expr.indices[1].expression == ["..."]
def test_indices_single(self): tree = tr("cube_turn_range", tr("cube_left"), tr("range_value", tr("int_literal", "1"))) expr = parser.handle(tree, Stack()) assert isinstance(expr, CubeTurningExpression) assert expr.side == "left" assert len(expr.indices) == 1 assert expr.indices[0].expression == ["1"]
def test_literal(name: str, value: str, exp_type: Type, exp_value: str): tree = tr(name, value) expr = parser.handle(tree, Stack()) assert isinstance(expr, Expression) assert expr.type == exp_type assert expr.expression == [exp_value] assert expr.intermediates == []
def test_variable_exist(): tree = tr("variable", "a") stack = Stack() stack.add_variable("a", Integer) expression: Expression = parser.handle(tree, stack) assert expression.type == Integer assert expression.expression == ["var_0"]
def test_negation_correct_type(self, type): tree = tr("negation", tr("variable", "a")) stack = Stack() stack.add_global("a", type) expression = parser.handle(tree, stack) assert expression.expression == ["-(", "a", ")"] assert expression.type == type
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_comparision_correct(self, arg1, arg2): tree = tr("op_3_0", tr("variable", "a"), tr("variable", "b")) stack = Stack() stack.add_global("a", arg1) stack.add_global("b", arg2) expr: Expression = parser.handle(tree, stack) assert expr.type == Bool
def test_return(self): tree = tr("return_statement", tr("int_literal", "1")) stack = Stack() stack.context_return_type = Real expression = parser.handle(tree, stack) assert expression.type == Void assert expression.expression == ["return ", "1"]
def test_for_loop_wrong_range(): with pytest.raises(ValueTypeError): tree = tr("for_expression", "var", tr("int_literal", "1"), tr("int_literal", "1")) parser.handle(tree, Stack())
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_list_type_error(self): stack = Stack() stack.add_global("a", List(Bool)) tree = tr("var_assignment", tr("collection_item", tr("variable", "a"), tr("int_literal", "2")), tr("int_literal", "42")) with pytest.raises(ValueTypeError): parser.handle(tree, stack)
def test_list(self): stack = Stack() stack.add_global("a", List(Real)) tree = tr("var_assignment", tr("collection_item", tr("variable", "a"), tr("int_literal", "2")), tr("int_literal", "42")) expression = parser.handle(tree, stack) assert expression.expression == ["(", "a", ")[", "2", "]", " = ", "42"]
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_repeat(): tree = tr("repeat_expression", tr("int_literal", "2"), tr("bool_literal_true")) expression = parser.handle(tree, Stack()) assert isinstance(expression, RepeatLoopExpression) assert expression.type == Void assert expression.times.expression == ["2"] assert expression.actions[0].expression == ["True"]
def test_do_while(): tree = tr("do_expression", tr("int_literal", "2"), tr("bool_literal_true")) expression = parser.handle(tree, Stack()) assert isinstance(expression, DoWhileLoopExpression) assert expression.type == Void assert expression.condition.expression == ["True"] assert expression.actions[0].expression == ["2"]
def test_list_reference(): stack = Stack() stack.add_global("a", List(Bool)) tree = tr("collection_item", tr("variable", "a"), tr("int_literal", "12")) expression = parser.handle(tree, stack) assert expression.expression == ["(", "a", ")[", "12", "]"] assert expression.type == Bool
def test_for_loop_wrong_iterator_type(): with pytest.raises(ValueTypeError): stack = Stack() stack.add_variable("var", Bool) stack.add_variable("range", List(Integer)) tree = tr("for_expression", "var", tr("variable", "range"), tr("int_literal", "1")) parser.handle(tree, stack)
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_var_declaration(self): tree = tr("var_decl", "a", "b", "c", tr("type_int")) stack = Stack() expressions = parser.handle(tree, stack) for i, value in enumerate(expressions): assert value.type == Void assert value.expression == ["var_" + str(i), " = ", "0"] assert stack.get_variable("a").type == Integer assert stack.get_variable("b").type == Integer assert stack.get_variable("c").type == Integer
def test_value(self): tree = tr("var_decl", "a", "b", "c", tr("type_int"), tr("int_literal", "1")) stack = Stack() values: typing.List[Expression] = parser.handle(tree, stack) for i, value in enumerate(values): assert value.type == Void assert value.expression == ["var_" + str(i), " = ", "1"] assert stack.get_variable("a").type == Integer assert stack.get_variable("b").type == Integer assert stack.get_variable("c").type == Integer
def test_for_loop_existing_var(): stack = Stack() stack.add_variable("var", Real) stack.add_variable("range", List(Integer)) tree = tr("for_expression", "var", tr("variable", "range"), tr("int_literal", "1")) expression = parser.handle(tree, stack) assert isinstance(expression, ForLoopExpression) assert expression.iterator == "var_0" assert expression.range.expression == ["var_1"] assert expression.actions[0].expression == ["1"]
def test_globals(): stack = Stack() stack.add_global("a", List(Integer)) stack.add_variable("b", Real) g = stack.get_variable("a") assert g.type == List(Integer) assert g.number == -1 stack.add_variable("a", Bool) g = stack.get_variable("a") assert g.type == Bool assert g.number == 1
def test_frames(): stack = Stack() assert stack.add_variable("a", Integer) == 0 assert stack.add_variable("b", Real) == 1 stack.add_frame() assert stack.add_variable("b", List(Integer)) == 2 assert stack.add_variable("c", Bool) == 3 assert stack.get_variable("b").type == List(Integer) stack.pop_frame() assert stack.get_variable("b").type == Real assert stack.get_variable("c") is None assert stack.add_variable("c", List(Integer)) == 2
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))