import pytest from phasm.exceptions import StaticError from phasm.type5.solver import Type5SolverException from ..helpers import Suite @pytest.mark.integration_test def test_struct_0(): code_py = """ class CheckedValue: value: i32 @exported def testEntry() -> i32: return helper(CheckedValue(23)) def helper(cv: CheckedValue) -> i32: return cv.value """ result = Suite(code_py).run_code() assert 23 == result.returned_value @pytest.mark.integration_test def test_struct_1(): code_py = """ class Rectangle: height: i32 width: i32 border: i32 @exported def testEntry() -> i32: return helper(Rectangle(100, 150, 2)) def helper(shape: Rectangle) -> i32: return shape.height + shape.width + shape.border """ result = Suite(code_py).run_code() assert 252 == result.returned_value @pytest.mark.integration_test def test_struct_2(): code_py = """ class Rectangle: height: i32 width: i32 border: i32 @exported def testEntry() -> i32: return helper(Rectangle(100, 150, 2), Rectangle(200, 90, 3)) def helper(shape1: Rectangle, shape2: Rectangle) -> i32: return shape1.height + shape1.width + shape1.border + shape2.height + shape2.width + shape2.border """ result = Suite(code_py).run_code() assert 545 == result.returned_value @pytest.mark.integration_test def test_type_mismatch_struct_call_root(): code_py = """ class CheckedValueBlue: value: i32 class CheckedValueRed: value: i32 CONST: CheckedValueBlue = CheckedValueRed(1) """ with pytest.raises(Type5SolverException, match='Must be right struct'): Suite(code_py).run_code() @pytest.mark.integration_test def test_type_mismatch_struct_call_nested(): code_py = """ class CheckedValueBlue: value: i32 class CheckedValueRed: value: i32 CONST: (CheckedValueBlue, u32, ) = (CheckedValueRed(1), 16, ) """ with pytest.raises(Type5SolverException, match='Must be right struct'): Suite(code_py).run_code() @pytest.mark.integration_test def test_type_mismatch_struct_call_arg_count(): code_py = """ class CheckedValue: value1: i32 value2: i32 CONST: CheckedValue = CheckedValue(1) """ with pytest.raises(Type5SolverException, match='Struct member count mismatch'): Suite(code_py).run_code() @pytest.mark.integration_test @pytest.mark.parametrize('type_', ['i32', 'i64', 'f32', 'f64']) def test_type_mismatch_struct_member(type_): code_py = f""" class Struct: param: {type_} def testEntry(arg: Struct) -> (i32, i32, ): return arg.param """ match = rf'.param :: Struct -> {type_} ~ Struct -> \(i32, i32, \)' with pytest.raises(Type5SolverException, match=match): Suite(code_py).run_code() @pytest.mark.integration_test def test_name_already_use_struct(): code_py = """ class Struct: param: i32 class Struct: param: i64 """ with pytest.raises(StaticError, match='Struct already defined as type'): Suite(code_py).run_code() @pytest.mark.integration_test def test_name_already_use_type(): code_py = """ class f32: param: i32 """ with pytest.raises(StaticError, match='f32 already defined as type'): Suite(code_py).run_code() @pytest.mark.integration_test def test_struct_not_accessible(): code_py = """ @exported def testEntry(x: u8) -> u8: return x.y """ with pytest.raises(Type5SolverException, match='Must be a struct'): Suite(code_py).run_code() @pytest.mark.integration_test def test_struct_does_not_have_field(): code_py = """ class CheckedValue: value: i32 @exported def testEntry(x: CheckedValue) -> u8: return x.y """ with pytest.raises(Type5SolverException, match='Must have a field with this name'): Suite(code_py).run_code() @pytest.mark.integration_test def test_struct_literal_does_not_fit(): code_py = """ class CheckedValue: value: i32 @exported def testEntry() -> CheckedValue: return 14 """ with pytest.raises(Type5SolverException, match='Must be struct'): Suite(code_py).run_code() @pytest.mark.integration_test def test_struct_wrong_struct(): code_py = """ class CheckedValue: value: i32 class MessedValue: value: i32 @exported def testEntry() -> CheckedValue: return MessedValue(14) """ with pytest.raises(Type5SolverException, match='Not the same type'): Suite(code_py).run_code() @pytest.mark.integration_test def test_struct_wrong_arg_count(): code_py = """ class CheckedValue: value1: i32 value2: i32 @exported def testEntry() -> CheckedValue: return CheckedValue(14) """ with pytest.raises(Type5SolverException, match='Not the same type'): Suite(code_py).run_code() @pytest.mark.integration_test def test_struct_export_constant(): code_py = """ class CheckedValue: value: i32 CONSTANT: CheckedValue = CheckedValue(32) @exported def testEntry() -> CheckedValue: return CONSTANT """ result = Suite(code_py).run_code() assert {"value": 32} == result.returned_value @pytest.mark.integration_test def test_struct_export_instantiation(): code_py = """ class CheckedValue: value: i32 @exported def testEntry() -> CheckedValue: return CheckedValue(32) """ result = Suite(code_py).run_code() assert {"value": 32} == result.returned_value