コード例 #1
0
 def test_return_value_requires_different_signedness_from_arguments(self):
   ir = _make_ir_from_emb(
       '[$default byte_order: "LittleEndian"]\n'
       "struct Foo:\n"
       "  0 [+1]    UInt  x\n"
       # Both arguments require uint64; result fits in int64.
       "  if (x + 0x7fff_ffff_ffff_ffff) - 0x8000_0000_0000_0000 < 10:\n"
       "    1 [+1]  UInt  y\n")
   condition = ir.module[0].type[0].structure.field[1].existence_condition
   error_expression = condition.function.args[0]
   error_location = error_expression.source_location
   arg0_location = error_expression.function.args[0].source_location
   arg1_location = error_expression.function.args[1].source_location
   self.assertEqual([
       [error.error(
           "m.emb", error_location,
           "Either all arguments to '-' and its result must fit in a 64-bit "
           "unsigned integer, or all must fit in a 64-bit signed integer."),
        error.note("m.emb", arg0_location,
                   "Requires unsigned 64-bit integer."),
        error.note("m.emb", arg1_location,
                   "Requires unsigned 64-bit integer."),
        error.note("m.emb", error_location,
                   "Requires signed 64-bit integer.")]
   ], error.filter_errors(constraints.check_constraints(ir)))
コード例 #2
0
 def test_error_on_triple_field_cycle(self):
     ir = _parse_snippet("struct Foo:\n"
                         "  0 [+field2]  UInt  field1\n"
                         "  0 [+field3]  UInt  field2\n"
                         "  0 [+field1]  UInt  field3\n")
     struct = ir.module[0].type[0].structure
     self.assertEqual([[
         error.error("m.emb", struct.field[0].source_location,
                     "Dependency cycle\nfield1"),
         error.note("m.emb", struct.field[1].source_location, "field2"),
         error.note("m.emb", struct.field[2].source_location, "field3"),
     ]], dependency_checker.find_dependency_cycles(ir))
コード例 #3
0
ファイル: type_check.py プロジェクト: reventlov/emboss
def _type_check_passed_parameters(atomic_type, ir, source_file_name, errors):
    """Checks the types of parameters to a parameterized physical type."""
    referenced_type = ir_util.find_object(atomic_type.reference.canonical_name,
                                          ir)
    if (len(referenced_type.runtime_parameter) != len(
            atomic_type.runtime_parameter)):
        errors.append([
            error.error(
                source_file_name, atomic_type.source_location,
                "Type {} requires {} parameter{}; {} parameter{} given.".
                format(
                    referenced_type.name.name.text,
                    len(referenced_type.runtime_parameter),
                    "" if len(referenced_type.runtime_parameter) == 1 else "s",
                    len(atomic_type.runtime_parameter),
                    "" if len(atomic_type.runtime_parameter) == 1 else "s")),
            error.note(
                atomic_type.reference.canonical_name.module_file,
                referenced_type.source_location,
                "Definition of type {}.".format(
                    referenced_type.name.name.text))
        ])
        return
    for i in range(len(referenced_type.runtime_parameter)):
        if referenced_type.runtime_parameter[i].type.WhichOneof(
                "type") not in ("integer", "boolean", "enumeration"):
            # _type_check_parameter will catch invalid parameter types at the
            # definition site; no need for another, probably-confusing error at any
            # usage sites.
            continue
        if (atomic_type.runtime_parameter[i].type.WhichOneof("type") !=
                referenced_type.runtime_parameter[i].type.WhichOneof("type")):
            errors.append([
                error.error(
                    source_file_name,
                    atomic_type.runtime_parameter[i].source_location,
                    "Parameter {} of type {} must be {}, not {}.".format(
                        i, referenced_type.name.name.text,
                        _type_name_for_error_messages(
                            referenced_type.runtime_parameter[i].type),
                        _type_name_for_error_messages(
                            atomic_type.runtime_parameter[i].type))),
                error.note(
                    atomic_type.reference.canonical_name.module_file,
                    referenced_type.runtime_parameter[i].source_location,
                    "Parameter {} of {}.".format(
                        i, referenced_type.name.name.text))
            ])
コード例 #4
0
ファイル: type_check.py プロジェクト: reventlov/emboss
def _type_check_constant_reference(expression, source_file_name, ir, errors):
    """Annotates the type of a constant reference."""
    referred_name = expression.constant_reference.canonical_name
    referred_object = ir_util.find_object(referred_name, ir)
    if isinstance(referred_object, ir_pb2.EnumValue):
        expression.type.enumeration.name.CopyFrom(
            expression.constant_reference)
        del expression.type.enumeration.name.canonical_name.object_path[-1]
    elif isinstance(referred_object, ir_pb2.Field):
        if not ir_util.field_is_virtual(referred_object):
            errors.append([
                error.error(
                    source_file_name, expression.source_location,
                    "Static references to physical fields are not allowed."),
                error.note(
                    referred_name.module_file, referred_object.source_location,
                    "{} is a physical field.".format(
                        referred_name.object_path[-1])),
            ])
            return
        _type_check_expression(referred_object.read_transform,
                               referred_name.module_file, ir, errors)
        expression.type.CopyFrom(referred_object.read_transform.type)
    else:
        assert False, "Unexpected constant reference type."
コード例 #5
0
def _verify_requires_attribute_on_field(field, source_file_name, ir, errors):
  """Verifies that [requires] is valid on the given field."""
  requires_attr = ir_util.get_attribute(field.attribute, attributes.REQUIRES)
  if not requires_attr:
    return
  if ir_util.field_is_virtual(field):
    field_expression_type = field.read_transform.type
  else:
    if not field.type.HasField("atomic_type"):
      errors.append([
          error.error(source_file_name, requires_attr.source_location,
                      "Attribute 'requires' is only allowed on integer, "
                      "enumeration, or boolean fields, not arrays."),
          error.note(source_file_name, field.type.source_location,
                     "Field type."),
      ])
      return
    field_type = ir_util.find_object(field.type.atomic_type.reference, ir)
    assert field_type, "Field type should be non-None after name resolution."
    field_expression_type = (
        type_check.unbounded_expression_type_for_physical_type(field_type))
  if field_expression_type.WhichOneof("type") not in (
      "integer", "enumeration", "boolean"):
    errors.append([error.error(
        source_file_name, requires_attr.source_location,
        "Attribute 'requires' is only allowed on integer, enumeration, or "
        "boolean fields.")])
コード例 #6
0
ファイル: glue.py プロジェクト: max19931/emboss
def parse_module(file_name, file_reader):
    """Parses a module, returning a module-level IR.

  Arguments:
    file_name: The name of the module's source file.
    file_reader: A callable that returns either:
        (file_contents, None) or
        (None, list_of_error_detail_strings)

  Returns:
    (ir, debug_info, errors), where ir is a module-level intermediate
    representation (IR), debug_info is a ModuleDebugInfo containing the
    tokenization, parse tree, and original source text of all modules, and
    errors is a list of tokenization or parse errors.  If errors is not an empty
    list, ir will be None.

  Raises:
    FrontEndFailure: An error occurred while reading or parsing the module.
        str(error) will give a human-readable error message.
  """
    source_code, errors = file_reader(file_name)
    if errors:
        location = parser_types.make_location((1, 1), (1, 1))
        return None, None, [
            [error.error(file_name, location, "Unable to read file.")] +
            [error.note(file_name, location, e) for e in errors]
        ]
    return parse_module_text(source_code, file_name)
コード例 #7
0
ファイル: symbol_resolver.py プロジェクト: reventlov/emboss
def duplicate_name_error(file_name, location, name, original_location):
    """A name is defined two or more times."""
    return [
        error.error(file_name, location, "Duplicate name '{}'".format(name)),
        error.note(original_location.file, original_location.location,
                   "Original definition")
    ]
コード例 #8
0
def _find_object_dependency_cycles(ir):
    """Finds dependency cycles in types in the ir."""
    dependencies, find_dependency_errors = _find_dependencies(ir)
    if find_dependency_errors:
        return find_dependency_errors
    errors = []
    cycles = _find_cycles(dict(dependencies))
    for cycle in cycles:
        # TODO(bolms): This lists the entire strongly-connected component in a
        # fairly arbitrary order.  This is simple, and handles components that
        # aren't simple cycles, but may not be the most user-friendly way to
        # present this information.
        cycle_list = sorted(list(cycle))
        node_object = ir_util.find_object(cycle_list[0], ir)
        error_group = [
            error.error(cycle_list[0][0], node_object.source_location,
                        "Dependency cycle\n" + node_object.name.name.text)
        ]
        for node in cycle_list[1:]:
            node_object = ir_util.find_object(node, ir)
            error_group.append(
                error.note(node[0], node_object.source_location,
                           node_object.name.name.text))
        errors.append(error_group)
    return errors
コード例 #9
0
 def test_error_on_simple_enum_value_cycle(self):
     ir = _parse_snippet("enum Foo:\n" "  XX = YY\n" "  YY = XX\n")
     enum = ir.module[0].type[0].enumeration
     self.assertEqual([[
         error.error("m.emb", enum.value[0].source_location,
                     "Dependency cycle\nXX"),
         error.note("m.emb", enum.value[1].source_location, "YY")
     ]], dependency_checker.find_dependency_cycles(ir))
コード例 #10
0
 def test_error_on_virtual_field_cycle(self):
     ir = _parse_snippet("struct Foo:\n" "  let x = y\n" "  let y = x\n")
     struct = ir.module[0].type[0].structure
     self.assertEqual([[
         error.error("m.emb", struct.field[0].source_location,
                     "Dependency cycle\nx"),
         error.note("m.emb", struct.field[1].source_location, "y")
     ]], dependency_checker.find_dependency_cycles(ir))
コード例 #11
0
 def test_rejects_duplicate_default_attribute(self):
     ir = _make_ir_from_emb('[$default byte_order: "LittleEndian"]\n'
                            '[$default byte_order: "LittleEndian"]\n')
     self.assertEqual([[
         error.error("m.emb", ir.module[0].attribute[1].source_location,
                     "Duplicate attribute 'byte_order'."),
         error.note("m.emb", ir.module[0].attribute[0].source_location,
                    "Original attribute"),
     ]], attribute_checker.normalize_and_verify(ir))
コード例 #12
0
ファイル: symbol_resolver.py プロジェクト: reventlov/emboss
def ambiguous_name_error(file_name, location, name, candidate_locations):
    """A name cannot be resolved because there are two or more candidates."""
    result = [
        error.error(file_name, location, "Ambiguous name '{}'".format(name))
    ]
    for location in sorted(candidate_locations):
        result.append(
            error.note(location.file, location.location,
                       "Possible resolution"))
    return result
コード例 #13
0
def _check_attributes(attribute_list, attribute_specs, context_name,
                      module_source_file):
  """Performs basic checks on the given list of attributes.

  Checks the given attribute_list for duplicates, unknown attributes, attributes
  with incorrect type, and attributes whose values are not constant.

  Arguments:
    attribute_list: An iterable of ir_pb2.Attribute.
    attribute_specs: A dict of attribute names to _Attribute structures
      specifying the allowed attributes.
    context_name: A name for the context of these attributes, such as "struct
      'Foo'" or "module 'm.emb'".  Used in error messages.
    module_source_file: The value of module.source_file_name from the module
      containing 'attribute_list'.  Used in error messages.

  Returns:
    A list of lists of error.Errors.  An empty list indicates no errors were
    found.
  """
  errors = []
  already_seen_attributes = {}
  for attr in attribute_list:
    if attr.back_end.text:
      attribute_name = "({}) {}".format(attr.back_end.text, attr.name.text)
    else:
      attribute_name = attr.name.text
    if (attr.name.text, attr.is_default) in already_seen_attributes:
      original_attr = already_seen_attributes[attr.name.text, attr.is_default]
      errors.append([
          error.error(module_source_file,
                      attr.source_location,
                      "Duplicate attribute '{}'.".format(attribute_name)),
          error.note(module_source_file,
                     original_attr.source_location,
                     "Original attribute")])
      continue
    already_seen_attributes[attr.name.text, attr.is_default] = attr

    if ((attr.back_end.text, attr.name.text, attr.is_default) not in
        attribute_specs):
      if attr.is_default:
        error_message = "Attribute '{}' may not be defaulted on {}.".format(
            attribute_name, context_name)
      else:
        error_message = "Unknown attribute '{}' on {}.".format(attribute_name,
                                                               context_name)
      errors.append([error.error(module_source_file,
                                 attr.name.source_location,
                                 error_message)])
    else:
      attribute_check = _ATTRIBUTE_TYPES[attr.back_end.text, attr.name.text]
      errors.extend(attribute_check(attr, module_source_file))
  return errors
コード例 #14
0
ファイル: glue_test.py プロジェクト: reventlov/emboss
 def test_parse_module_no_such_file(self):
   file_name = "nonexistent.emb"
   ir, debug_info, errors = glue.parse_emboss_file(
       file_name, test_util.dict_file_reader({}))
   self.assertEqual([[
       error.error("nonexistent.emb", _location((1, 1), (1, 1)),
                   "Unable to read file."),
       error.note("nonexistent.emb", _location((1, 1), (1, 1)),
                  "File 'nonexistent.emb' not found."),
   ]], errors)
   self.assertFalse(file_name in debug_info.modules)
   self.assertFalse(ir)
コード例 #15
0
 def test_error_on_cycle_involving_subfield(self):
     ir = _parse_snippet("struct Bar:\n"
                         "  foo_b.x [+4]  Foo  foo_a\n"
                         "  foo_a.x [+4]  Foo  foo_b\n"
                         "struct Foo:\n"
                         "  0 [+4]  UInt  x\n")
     struct = ir.module[0].type[0].structure
     self.assertEqual([[
         error.error("m.emb", struct.field[0].source_location,
                     "Dependency cycle\nfoo_a"),
         error.note("m.emb", struct.field[1].source_location, "foo_b")
     ]], dependency_checker.find_dependency_cycles(ir))
コード例 #16
0
 def test_error_on_field_existence_cycle(self):
     ir = _parse_snippet("struct Foo:\n"
                         "  if y == 1:\n"
                         "    0 [+1]  UInt  x\n"
                         "  if x == 0:\n"
                         "    1 [+1]  UInt  y\n")
     struct = ir.module[0].type[0].structure
     self.assertEqual([[
         error.error("m.emb", struct.field[0].source_location,
                     "Dependency cycle\nx"),
         error.note("m.emb", struct.field[1].source_location, "y")
     ]], dependency_checker.find_dependency_cycles(ir))
コード例 #17
0
 def test_rejects_requires_on_array(self):
     ir = _make_ir_from_emb("struct Foo:\n"
                            "  0 [+4]  UInt:8[]  array\n"
                            "    [requires: false]\n")
     field_ir = ir.module[0].type[0].structure.field[0]
     self.assertEqual([[
         error.error(
             "m.emb", field_ir.attribute[0].value.source_location,
             "Attribute 'requires' is only allowed on integer, "
             "enumeration, or boolean fields, not arrays."),
         error.note("m.emb", field_ir.type.source_location, "Field type."),
     ]], error.filter_errors(attribute_checker.normalize_and_verify(ir)))
コード例 #18
0
ファイル: type_check_test.py プロジェクト: reventlov/emboss
 def test_error_on_passing_unneeded_parameter(self):
     ir = self._make_ir("struct Foo:\n"
                        "  0 [+1]  Bar(1)  b\n"
                        "struct Bar:\n"
                        "  0 [+1]       UInt:8[]  x\n")
     type_ir = ir.module[0].type[0].structure.field[0].type
     bar = ir.module[0].type[1]
     self.assertEqual([[
         error.error("m.emb", type_ir.source_location,
                     "Type Bar requires 0 parameters; 1 parameter given."),
         error.note("m.emb", bar.source_location, "Definition of type Bar.")
     ]], type_check.check_types(ir))
コード例 #19
0
 def test_rejects_duplicate_attribute(self):
     ir = _make_ir_from_emb("external Foo:\n"
                            "  [is_integer: true]\n"
                            "  [is_integer: true]\n")
     self.assertEqual([[
         error.error("m.emb",
                     ir.module[0].type[0].attribute[1].source_location,
                     "Duplicate attribute 'is_integer'."),
         error.note("m.emb",
                    ir.module[0].type[0].attribute[0].source_location,
                    "Original attribute"),
     ]], attribute_checker.normalize_and_verify(ir))
コード例 #20
0
ファイル: error_test.py プロジェクト: reventlov/emboss
 def test_split_errors(self):
     user_error = [
         error.error("foo.emb", parser_types.make_location((1, 2), (3, 4)),
                     "Bad thing"),
         error.note("foo.emb", parser_types.make_location((3, 4), (5, 6)),
                    "Note: bad thing referrent")
     ]
     user_error_2 = [
         error.error("foo.emb", parser_types.make_location(
             (8, 9), (10, 11)), "Bad thing"),
         error.note("foo.emb", parser_types.make_location(
             (10, 11), (12, 13)), "Note: bad thing referrent")
     ]
     synthetic_error = [
         error.error("foo.emb", parser_types.make_location((1, 2), (3, 4)),
                     "Bad thing"),
         error.note("foo.emb",
                    parser_types.make_location((3, 4), (5, 6), True),
                    "Note: bad thing referrent")
     ]
     synthetic_error_2 = [
         error.error("foo.emb",
                     parser_types.make_location((8, 9), (10, 11), True),
                     "Bad thing"),
         error.note("foo.emb", parser_types.make_location(
             (10, 11), (12, 13)), "Note: bad thing referrent")
     ]
     user_errors, synthetic_errors = error.split_errors(
         [user_error, synthetic_error])
     self.assertEqual([user_error], user_errors)
     self.assertEqual([synthetic_error], synthetic_errors)
     user_errors, synthetic_errors = error.split_errors(
         [synthetic_error, user_error])
     self.assertEqual([user_error], user_errors)
     self.assertEqual([synthetic_error], synthetic_errors)
     user_errors, synthetic_errors = error.split_errors(
         [synthetic_error, user_error, synthetic_error_2, user_error_2])
     self.assertEqual([user_error, user_error_2], user_errors)
     self.assertEqual([synthetic_error, synthetic_error_2],
                      synthetic_errors)
コード例 #21
0
 def test_explicit_size_too_small(self):
   ir = _make_ir_from_emb("bits Foo:\n"
                          "  0 [+0]  UInt:0  zero_bit\n")
   error_field = ir.module[0].type[0].structure.field[0]
   uint_type = ir_util.find_object(error_field.type.atomic_type.reference, ir)
   uint_requirements = ir_util.get_attribute(uint_type.attribute,
                                             attributes.STATIC_REQUIREMENTS)
   self.assertEqual([[
       error.error("m.emb", error_field.source_location,
                   "Requirements of UInt not met."),
       error.note("", uint_requirements.source_location,
                  "Requirements specified here."),
   ]], error.filter_errors(constraints.check_constraints(ir)))
コード例 #22
0
ファイル: type_check_test.py プロジェクト: reventlov/emboss
 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))
コード例 #23
0
 def test_error_on_import_cycle(self):
     ir, unused_debug_info, errors = glue.parse_emboss_file(
         "m.emb",
         test_util.dict_file_reader({
             "m.emb": 'import "n.emb" as n\n',
             "n.emb": 'import "m.emb" as m\n'
         }),
         stop_before_step="find_dependency_cycles")
     assert not errors
     self.assertEqual([[
         error.error("m.emb", ir.module[0].source_location,
                     "Import dependency cycle\nm.emb"),
         error.note("n.emb", ir.module[2].source_location, "n.emb")
     ]], dependency_checker.find_dependency_cycles(ir))
コード例 #24
0
 def test_checks_constancy_of_constant_references(self):
   ir = _make_ir_from_emb("struct Foo:\n"
                          "  0 [+1]  UInt  x\n"
                          "  let y = x\n"
                          "  let z = Foo.y\n")
   error_expression = ir.module[0].type[0].structure.field[2].read_transform
   error_location = error_expression.source_location
   note_field = ir.module[0].type[0].structure.field[1]
   note_location = note_field.source_location
   self.assertEqual([
       [error.error("m.emb", error_location,
                    "Static references must refer to constants."),
        error.note("m.emb", note_location, "y is not constant.")]
   ], error.filter_errors(constraints.check_constraints(ir)))
コード例 #25
0
 def test_explicit_size_too_small_on_fixed_size_type(self):
   ir = _make_ir_from_emb("struct Foo:\n"
                          "  0 [+0]  Byte:0  null_byte\n"
                          "struct Byte:\n"
                          "  0 [+1]  UInt  b\n")
   error_type = ir.module[0].type[0].structure.field[0].type
   self.assertEqual([[
       error.error(
           "m.emb", error_type.size_in_bits.source_location,
           "Explicit size of 0 bits does not match fixed size (8 bits) of "
           "type 'Byte'."),
       error.note("m.emb", ir.module[0].type[1].source_location,
                  "Size specified here."),
   ]], error.filter_errors(constraints.check_constraints(ir)))
コード例 #26
0
 def test_explicit_size_too_big(self):
   ir = _make_ir_from_emb("struct Foo:\n"
                          "  0 [+16]  UInt:128  one_twenty_eight_bit\n"
                          '    [byte_order: "LittleEndian"]\n')
   error_field = ir.module[0].type[0].structure.field[0]
   uint_type = ir_util.find_object(error_field.type.atomic_type.reference, ir)
   uint_requirements = ir_util.get_attribute(uint_type.attribute,
                                             attributes.STATIC_REQUIREMENTS)
   self.assertEqual([[
       error.error("m.emb", error_field.source_location,
                   "Requirements of UInt not met."),
       error.note("", uint_requirements.source_location,
                  "Requirements specified here."),
   ]], error.filter_errors(constraints.check_constraints(ir)))
コード例 #27
0
def _integer_bounds_errors_for_expression(expression, source_file_name):
    """Checks that `expression` is in range for int64_t or uint64_t."""
    # Only check non-constant subexpressions.
    if (expression.WhichOneof("expression") == "function"
            and not ir_util.is_constant_type(expression.type)):
        errors = []
        for arg in expression.function.args:
            errors += _integer_bounds_errors_for_expression(
                arg, source_file_name)
        if errors:
            # Don't cascade bounds errors: report them at the lowest level they
            # appear.
            return errors
    if expression.type.WhichOneof("type") == "integer":
        errors = _integer_bounds_errors(expression.type.integer, "expression",
                                        source_file_name,
                                        expression.source_location)
        if errors:
            return errors
    if (expression.WhichOneof("expression") == "function"
            and not ir_util.is_constant_type(expression.type)):
        int64_only_clauses = []
        uint64_only_clauses = []
        for clause in [expression] + list(expression.function.args):
            if clause.type.WhichOneof("type") == "integer":
                arg_minimum = int(clause.type.integer.minimum_value)
                arg_maximum = int(clause.type.integer.maximum_value)
                if not _bounds_can_fit_64_bit_signed(arg_minimum, arg_maximum):
                    uint64_only_clauses.append(clause)
                elif not _bounds_can_fit_64_bit_unsigned(
                        arg_minimum, arg_maximum):
                    int64_only_clauses.append(clause)
        if int64_only_clauses and uint64_only_clauses:
            error_set = [
                error.error(
                    source_file_name, expression.source_location,
                    "Either all arguments to '{}' and its result must fit in a "
                    "64-bit unsigned integer, or all must fit in a 64-bit signed "
                    "integer.".format(expression.function.function_name.text))
            ]
            for signedness, clause_list in (("unsigned", uint64_only_clauses),
                                            ("signed", int64_only_clauses)):
                for clause in clause_list:
                    error_set.append(
                        error.note(
                            source_file_name, clause.source_location,
                            "Requires {} 64-bit integer.".format(signedness)))
            return [error_set]
    return []
コード例 #28
0
def _check_physical_type_requirements(type_ir, usage_source_location, size, ir,
                                      source_file_name):
    """Checks that the given atomic `type_ir` is allowed to be `size` bits."""
    referenced_type_definition = ir_util.find_object(
        type_ir.atomic_type.reference, ir)
    # TODO(bolms): replace this with a check against an automatically-generated
    # `static_requirements` attribute on enum types.  (The main problem is that
    # the generated attribute would have no source text, so there would be a crash
    # when trying to display the error.)
    if referenced_type_definition.HasField("enumeration"):
        if size is None:
            return [[
                error.error(
                    source_file_name, type_ir.source_location,
                    "Enumeration {} cannot be placed in a dynamically-sized "
                    "field.".format(_render_type(type_ir, ir)))
            ]]
        elif size < 1 or size > 64:
            return [[
                error.error(
                    source_file_name, type_ir.source_location,
                    "Enumeration {} cannot be {} bits; enumerations must be between "
                    "1 and 64 bits, inclusive.".format(
                        _render_atomic_type_name(type_ir, ir), size))
            ]]

    if size is None:
        bindings = {"$is_statically_sized": False}
    else:
        bindings = {"$is_statically_sized": True, "$static_size_in_bits": size}
    requires_attr = ir_util.get_attribute(referenced_type_definition.attribute,
                                          attributes.STATIC_REQUIREMENTS)
    if requires_attr and not ir_util.constant_value(requires_attr.expression,
                                                    bindings):
        # TODO(bolms): Figure out a better way to build this error message.
        # The "Requirements specified here." message should print out the actual
        # source text of the requires attribute, so that should help, but it's still
        # a bit generic and unfriendly.
        return [[
            error.error(
                source_file_name, usage_source_location,
                "Requirements of {} not met.".format(
                    type_ir.atomic_type.reference.canonical_name.
                    object_path[-1])),
            error.note(
                type_ir.atomic_type.reference.canonical_name.module_file,
                requires_attr.source_location, "Requirements specified here.")
        ]]
    return []
コード例 #29
0
ファイル: error_test.py プロジェクト: reventlov/emboss
 def test_equality(self):
     note_message = error.note("foo.emb",
                               parser_types.make_location((3, 4), (3, 6)),
                               "thing")
     self.assertEqual(
         note_message,
         error.note("foo.emb", parser_types.make_location((3, 4), (3, 6)),
                    "thing"))
     self.assertNotEqual(
         note_message,
         error.warn("foo.emb", parser_types.make_location((3, 4), (3, 6)),
                    "thing"))
     self.assertNotEqual(
         note_message,
         error.note("foo2.emb", parser_types.make_location((3, 4), (3, 6)),
                    "thing"))
     self.assertNotEqual(
         note_message,
         error.note("foo.emb", parser_types.make_location((2, 4), (3, 6)),
                    "thing"))
     self.assertNotEqual(
         note_message,
         error.note("foo.emb", parser_types.make_location((3, 4), (3, 6)),
                    "thing2"))
コード例 #30
0
ファイル: type_check_test.py プロジェクト: reventlov/emboss
 def test_error_on_passing_wrong_parameter_type(self):
     ir = self._make_ir("struct Foo:\n"
                        "  0 [+1]  Bar(1)  b\n"
                        "enum Baz:\n"
                        "  QUX = 1\n"
                        "struct Bar(n: Baz):\n"
                        "  0 [+1]       UInt:8[]  x\n")
     type_ir = ir.module[0].type[0].structure.field[0].type
     usage_parameter_ir = type_ir.atomic_type.runtime_parameter[0]
     source_parameter_ir = ir.module[0].type[2].runtime_parameter[0]
     self.assertEqual([[
         error.error("m.emb", usage_parameter_ir.source_location,
                     "Parameter 0 of type Bar must be Baz, not integer."),
         error.note("m.emb", source_parameter_ir.source_location,
                    "Parameter 0 of Bar.")
     ]], type_check.check_types(ir))