def test_adds_integer_constant_type(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt x\n" " 1 [+1] UInt:8[] y\n") self.assertEqual([], type_check.annotate_types(ir)) expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual(expression.type.WhichOneof("type"), "integer")
def test_choice_of_integers(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt:8[] x\n" " 1 [+true ? 0 : 100] UInt:8[] y\n") expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual([], type_check.annotate_types(ir)) self.assertEqual("integer", expression.type.WhichOneof("type"))
def test_error_on_no_max_argument(self): ir = self._make_ir("struct Foo:\n" " $max() [+1] UInt:8[] x\n") expression = ir.module[0].type[0].structure.field[0].location.start self.assertEqual([[ error.error("m.emb", expression.source_location, "Function '$max' requires at least 1 argument.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_choice_of_bools(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt:8[] x\n" " 1 [+true ? true : false] UInt:8[] y\n") expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual([], error.filter_errors(type_check.annotate_types(ir))) self.assertEqual("boolean", expression.type.WhichOneof("type"))
def test_checks_that_parameters_are_atomic_types(self): ir = self._make_ir("struct Foo(y: UInt:8[1]):\n" " 0 [+1] UInt x\n") error_parameter = ir.module[0].type[0].runtime_parameter[0] error_location = error_parameter.physical_type_alias.source_location self.assertEqual([[ error.error("m.emb", error_location, "Parameters cannot be arrays.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_adds_opaque_field_type_for_array(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt:8[] x\n" " 1 [+x] UInt:8[] y\n") self.assertEqual([], error.filter_errors(type_check.annotate_types(ir))) expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual(expression.type.WhichOneof("type"), "opaque")
def test_adds_boolean_constant_type(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt x\n" " 1 [+true] UInt:8[] y\n") self.assertEqual([], error.filter_errors(type_check.annotate_types(ir)), ir.to_json(indent=2)) expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual(expression.type.WhichOneof("type"), "boolean")
def test_lower_bound_too_many_arguments(self): ir = self._make_ir("struct Foo:\n" " $lower_bound(1, 2) [+1] UInt:8[] x\n") expression = ir.module[0].type[0].structure.field[0].location.start self.assertEqual([[ error.error( "m.emb", expression.source_location, "Function '$lower_bound' requires exactly 1 argument.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_error_on_bad_boolean_operand_type(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt x\n" " 1 [+1&&true] UInt:8[] y\n") expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual([[ error.error("m.emb", expression.function.args[0].source_location, "Left argument of operator '&&' must be a boolean.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_error_on_bad_choice_condition_operand(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt:8[] x\n" " 1 [+5 ? 0 : 1] UInt:8[] y\n") expression = ir.module[0].type[0].structure.field[1].location.size condition_arg = expression.function.args[0] self.assertEqual([[ error.error("m.emb", condition_arg.source_location, "Condition of operator '?:' must be a boolean.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_error_on_bad_max_argument(self): ir = self._make_ir("struct Foo:\n" " $max(Bar.XX) [+1] UInt:8[] x\n" "enum Bar:\n" " XX = 0\n") expression = ir.module[0].type[0].structure.field[0].location.start self.assertEqual([[ error.error("m.emb", expression.function.args[0].source_location, "Argument 0 of function '$max' must be an integer.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_error_on_non_field_argument_to_has(self): ir = self._make_ir("struct Foo:\n" " if $present(0):\n" " 0 [+1] UInt x\n") expression = ir.module[0].type[0].structure.field[ 0].existence_condition self.assertEqual([[ error.error("m.emb", expression.function.args[0].source_location, "Argument 0 of function '$present' must be a field.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_error_on_no_argument_has(self): ir = self._make_ir("struct Foo:\n" " if $present():\n" " 0 [+1] UInt x\n") expression = ir.module[0].type[0].structure.field[ 0].existence_condition self.assertEqual([[ error.error("m.emb", expression.source_location, "Function '$present' requires exactly 1 argument.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_error_on_equality_mismatched_operands_bool_int(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt x\n" " 1 [+true==1] UInt:8[] y\n") expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual([[ error.error( "m.emb", expression.source_location, "Both arguments of operator '==' must have the same " "type.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_error_on_bad_choice_mismatched_operands(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt:8[] x\n" " 1 [+true ? 0 : true] UInt:8[] y\n") expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual([[ error.error( "m.emb", expression.source_location, "The if-true and if-false clauses of operator '?:' must " "have the same type.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_error_on_bad_equality_left_operand(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt:8[] x\n" " 1 [+x==x] UInt:8[] y\n") expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual([[ error.error( "m.emb", expression.function.args[0].source_location, "Left argument of operator '==' must be an integer, " "boolean, or enum.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_adds_enum_constant_type(self): ir = self._make_ir("struct Foo:\n" " 0 [+Enum.VALUE] UInt x\n" "enum Enum:\n" " VALUE = 1\n") self.assertEqual([], error.filter_errors(type_check.annotate_types(ir))) expression = ir.module[0].type[0].structure.field[0].location.size self.assertEqual(expression.type.WhichOneof("type"), "enumeration") enum_type_name = expression.type.enumeration.name.canonical_name self.assertEqual(enum_type_name.module_file, "m.emb") self.assertEqual(enum_type_name.object_path[0], "Enum")
def test_error_on_bad_choice_if_true_operand(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt:8[] x\n" " 1 [+true ? x : x] UInt:8[] y\n") expression = ir.module[0].type[0].structure.field[1].location.size if_true_arg = expression.function.args[1] self.assertEqual([[ error.error( "m.emb", if_true_arg.source_location, "If-true clause of operator '?:' must be an integer, " "boolean, or enum.") ]], error.filter_errors(type_check.annotate_types(ir)))
def test_error_static_reference_to_physical_field(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt x\n" " let y = Foo.x\n") static_ref = ir.module[0].type[0].structure.field[1].read_transform physical_field = ir.module[0].type[0].structure.field[0] self.assertEqual([[ error.error( "m.emb", static_ref.source_location, "Static references to physical fields are not allowed."), error.note("m.emb", physical_field.source_location, "x is a physical field.") ]], type_check.annotate_types(ir))
def test_adds_enum_operation_type(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] UInt x\n" " 1 [+Enum.VAL==Enum.VAL] UInt:8[] y\n" "enum Enum:\n" " VAL = 1\n") self.assertEqual([], error.filter_errors(type_check.annotate_types(ir))) expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual(expression.type.WhichOneof("type"), "boolean") self.assertEqual(expression.function.args[0].type.WhichOneof("type"), "enumeration") self.assertEqual(expression.function.args[1].type.WhichOneof("type"), "enumeration")
def test_choice_of_enums(self): ir = self._make_ir("struct Foo:\n" " 0 [+1] enum xx:\n" " XX = 1\n" " YY = 1\n" " 1 [+true ? Xx.XX : Xx.YY] UInt:8[] y\n") expression = ir.module[0].type[0].structure.field[1].location.size self.assertEqual([], error.filter_errors(type_check.annotate_types(ir))) self.assertEqual("enumeration", expression.type.WhichOneof("type")) self.assertFalse(expression.type.enumeration.HasField("value")) self.assertEqual( "m.emb", expression.type.enumeration.name.canonical_name.module_file) self.assertEqual( "Foo", expression.type.enumeration.name.canonical_name.object_path[0]) self.assertEqual( "Xx", expression.type.enumeration.name.canonical_name.object_path[1])
def test_lower_bound_return_type(self): ir = self._make_ir("struct Foo:\n" " $lower_bound(3) [+1] UInt:8[] x\n") expression = ir.module[0].type[0].structure.field[0].location.start self.assertEqual([], type_check.annotate_types(ir)) self.assertEqual("integer", expression.type.WhichOneof("type"))