Set up a way of comparing the old scope/type/value analysis result with the new,...
authorNick Downing <nick@ndcode.org>
Wed, 27 Dec 2023 05:14:37 +0000 (16:14 +1100)
committerNick Downing <nick@ndcode.org>
Wed, 27 Dec 2023 13:35:41 +0000 (00:35 +1100)
ansi_c.py
ansi_c.t
ansi_c.y
base_type.py
calc_type.py
calc_value.py
declarator.py
pretty_print.t
scope_analysis.py
type_analysis.py

index 195837c..c593a90 100755 (executable)
--- a/ansi_c.py
+++ b/ansi_c.py
@@ -59,11 +59,15 @@ with open(in_file) as fin:
   )
 element.serialize(translation_unit, 'a.xml', 'utf-8')
 translation_unit = element.deserialize('a.xml', t_def.factory, 'utf-8')
+translation_unit.fix_type_sharing()
 element.serialize(translation_unit, 'b.xml', 'utf-8')
 translation_unit.strip_scope_analysis()
 element.serialize(translation_unit, 'c.xml', 'utf-8')
 translation_unit.scope = t_def.Scope()
 translation_unit.post_process(post_process.Context())
 element.serialize(translation_unit, 'd.xml', 'utf-8')
+translation_unit = element.deserialize('d.xml', t_def.factory, 'utf-8')
+translation_unit.fix_type_sharing()
+element.serialize(translation_unit, 'e.xml', 'utf-8')
 #translation_unit.strip_redundancy()
-#element.serialize(translation_unit, 'e.xml', 'utf-8')
+#element.serialize(translation_unit, 'f.xml', 'utf-8')
index efc084f..e0f1912 100644 (file)
--- a/ansi_c.t
+++ b/ansi_c.t
@@ -96,9 +96,9 @@ class Scope {
   int size;
   int align = 1;
   dict(str, ref) identifiers;
-  dict(str, ref) enum_tags;
   dict(str, ref) struct_tags;
   dict(str, ref) union_tags;
+  dict(str, ref) enum_tags;
 };
 
 /* type analysis */
@@ -108,6 +108,7 @@ class Type {
   int align = 1;
 };
 class TypeVoid: Type;
+class TypeBool: Type;
 class TypeInt: Type;
 class TypeIntSigned: TypeInt;
 class TypeEnum: TypeIntSigned {
@@ -119,10 +120,9 @@ class TypeEnum: TypeIntSigned {
 };
 class TypeIntUnsigned: TypeInt;
 class TypeFloat: Type;
-class TypeFloat: TypeFloat;
+class TypeFloatReal: TypeFloat;
 class TypeFloatImaginary: TypeFloat;
 class TypeFloatComplex: TypeFloat;
-class TypeBool: Type;
 class TypePointer: Type {
   ref target_type;
 };
@@ -431,6 +431,59 @@ class UnionSpecifier: Specifier {
 
 %%
 
+# primitive types
+type_void = TypeVoid(size = 0)
+type_bool = TypeBool(rank = 0, size = 1)
+type_signed_char = TypeIntSigned(rank = 1, size = 1)
+type_unsigned_char = TypeIntUnsigned(rank = 2, size = 1)
+type_signed_short = TypeIntSigned(rank = 3, size = 2, align = 2)
+type_unsigned_short = TypeIntUnsigned(rank = 4, size = 2, align = 2)
+type_signed_int = TypeIntSigned(rank = 5, size = 4, align = 4)
+type_unsigned_int = TypeIntUnsigned(rank = 6, size = 4, align = 4)
+type_signed_long = TypeIntSigned(rank = 7, size = 8, align = 8)
+type_unsigned_long = TypeIntUnsigned(rank = 8, size = 8, align = 8)
+type_signed_long_long = TypeIntSigned(rank = 9, size = 16, align = 16)
+type_unsigned_long_long = TypeIntUnsigned(rank = 10, size = 16, align = 16)
+type_float = TypeFloatReal(rank = 11, size = 4, align = 4)
+type_float_imaginary = TypeFloatImaginary(rank = 12, size = 4, align = 4)
+type_float_complex = TypeFloatComplex(rank = 13, size = 8, align = 4)
+type_double = TypeFloatReal(rank = 14, size = 8, align = 8)
+type_double_imaginary = TypeFloatImaginary(rank = 15, size = 8, align = 8)
+type_double_complex = TypeFloatComplex(rank = 16, size = 16, align = 8)
+type_long_double = TypeFloatReal(rank = 17, size = 16, align = 16)
+type_long_double_imaginary = TypeFloatImaginary(rank = 18, size = 16, align = 16)
+type_long_double_complex = TypeFloatComplex(rank = 19, size = 32, align = 16)
+
+type_ssize_t = type_signed_int
+assert type_ssize_t.size == POINTER_SIZE
+type_size_t = type_unsigned_int
+assert type_size_t.size == POINTER_SIZE
+
+rank_to_type = [
+  type_bool, # 0
+  type_signed_char, # 1
+  type_unsigned_char, # 2
+  type_signed_short, # 3
+  type_unsigned_short, # 4
+  type_signed_int, # 5
+  type_unsigned_int, # 6
+  type_signed_long, # 7
+  type_unsigned_long, # 8
+  type_signed_long_long, # 9
+  type_unsigned_long_long, # 10
+  type_float, # 11
+  type_float_imaginary, # 12
+  type_float_complex, # 13
+  type_double, # 14
+  type_double_imaginary, # 15
+  type_double_complex, # 16
+  type_long_double, # 17
+  type_long_double_imaginary, # 18
+  type_long_double_complex # 19
+]
+
+# note: ranks must also match calc_type.complex_promotions
+
 def factory(tag, *args, **kwargs):
   return tag_to_class[tag](*args, **kwargs)
 
@@ -493,15 +546,6 @@ def parameter_declaration_list_is_void(parameter_declaration_list):
     isinstance(parameter_declaration.children[1], DeclaratorAbstract)
   )
 
-@method(TypeStructOrUnion.Member)
-def __eq__(self, rhs):
-  return (
-    self.name == rhs.name and
-    self.type == rhs.type and
-    self.offset == rhs.offset
-  )
-del __eq__
-
 @method(Type)
 def __eq__(self, rhs):
   return (
@@ -549,6 +593,15 @@ def __eq__(self, rhs):
   )
 del __eq__
 
+@method(TypeStructOrUnion.Member)
+def __eq__(self, rhs):
+  return (
+    self.name == rhs.name and
+    self.type == rhs.type and
+    self.offset == rhs.offset
+  )
+del __eq__
+
 @method(Node)
 def strip_redundancy(self):
   self.text = [''] * (len(self.children) + 1)
@@ -616,49 +669,164 @@ def strip_redundancy(self):
 # temporary
 @method(Node)
 def strip_scope_analysis(self):
-  for i in self.children:
-    i.strip_scope_analysis()
+  for i in range(len(self.children)):
+    self.children[i] = self.children[i].strip_scope_analysis()
+  return self
 @method(ItemList)
 def strip_scope_analysis(self):
   self.scope = None
-  Node.strip_scope_analysis(self)
+  return Node.strip_scope_analysis(self)
 @method(EnumSpecifier)
 def strip_scope_analysis(self):
   self.scope_tag = None
-  Specifier.strip_scope_analysis(self)
+  return Specifier.strip_scope_analysis(self)
 @method(ExpressionIdentifier)
 def strip_scope_analysis(self):
   self.scope_identifier = None
-  Expression.strip_scope_analysis(self)
+  return Expression.strip_scope_analysis(self)
 @method(FunctionDefinition)
 def strip_scope_analysis(self):
   self.scope_identifier = None
-  Node.strip_scope_analysis(self)
+  return Node.strip_scope_analysis(self)
 @method(Identifier)
 def strip_scope_analysis(self):
   self.scope_identifier = None
-  Node.strip_scope_analysis(self)
+  return Node.strip_scope_analysis(self)
 @method(InitDeclarator)
 def strip_scope_analysis(self):
   self.scope_identifier = None
-  Node.strip_scope_analysis(self)
+  return Node.strip_scope_analysis(self)
 @method(ParameterDeclaration)
 def strip_scope_analysis(self):
   self.scope_identifier = None
-  Node.strip_scope_analysis(self)
+  return Node.strip_scope_analysis(self)
 @method(StructSpecifier)
 def strip_scope_analysis(self):
   self.scope_tag = None
-  Specifier.strip_scope_analysis(self)
+  return Specifier.strip_scope_analysis(self)
 @method(TagIdentifier)
 def strip_scope_analysis(self):
   self.scope_tag = None
-  Node.strip_scope_analysis(self)
+  return Node.strip_scope_analysis(self)
 @method(TypedefName)
 def strip_scope_analysis(self):
   self.scope_identifier = None
-  Specifier.strip_scope_analysis(self)
+  return Specifier.strip_scope_analysis(self)
 @method(UnionSpecifier)
 def strip_scope_analysis(self):
   self.scope_tag = None
-  Specifier.strip_scope_analysis(self)
+  return Specifier.strip_scope_analysis(self)
+@method(ExpressionCast)
+def strip_scope_analysis(self):
+  # not really scope analysis but strip casts that were not in the original
+  Expression.strip_scope_analysis(self)
+  if len(self.children[0].children) == 0:
+    return self.children[1]
+  return self
+del strip_scope_analysis
+
+# deserializing the tree creates new copies of primitive types
+# this can waste space if the tree is subsequently modified using
+# primitive types defined in this file -- fix deserialized tree
+@method(Type)
+def fix_type_sharing(self):
+  return self
+@method(TypeVoid)
+def fix_type_sharing(self):
+  return type_void
+@method(TypeBool)
+def fix_type_sharing(self):
+  return type_bool
+@method(TypeInt)
+def fix_type_sharing(self):
+  return rank_to_type[self.rank]
+@method(TypeFloat)
+def fix_type_sharing(self):
+  return rank_to_type[self.rank]
+@method(TypePointer)
+def fix_type_sharing(self):
+  self.target_type = self.target_type.fix_type_sharing()
+  return Type.fix_type_sharing(self)
+@method(TypeArray)
+def fix_type_sharing(self):
+  self.element_type = self.element_type.fix_type_sharing()
+  return Type.fix_type_sharing(self)
+@method(TypeFunction)
+def fix_type_sharing(self):
+  self.return_type = self.return_type.fix_type_sharing()
+  return Type.fix_type_sharing(self)
+@method(TypeFunctionANSI)
+def fix_type_sharing(self):
+  for i in range(len(self.formal_parameters)):
+    self.formal_parameters[i] = self.formal_parameters[i].fix_type_sharing()
+  return TypeFunction.fix_type_sharing(self)
+@method(TypeStructOrUnion)
+def fix_type_sharing(self):
+  for i in self.members:
+    i.fix_type_sharing()
+  return Type.fix_type_sharing(self)
+@method(TypeEnum)
+def fix_type_sharing(self):
+  # avoid calling TypeSignedInt.fix_type_sharing() which replaces us by rank
+  return self
+del fix_type_sharing
+
+@method(TypeStructOrUnion.Member)
+def fix_type_sharing(self):
+  self.type = self.type.fix_type_sharing()
+del fix_type_sharing
+
+@method(Scope)
+def fix_type_sharing(self):
+  for i in self.identifiers.values():
+    i.fix_type_sharing()
+  for i in self.struct_tags.values():
+    i.fix_type_sharing()
+  for i in self.union_tags.values():
+    i.fix_type_sharing()
+  for i in self.enum_tags.values():
+    i.fix_type_sharing()
+del fix_type_sharing
+
+@method(Scope.Identifier)
+def fix_type_sharing(self):
+  self.type = self.type.fix_type_sharing()
+del fix_type_sharing
+
+@method(Scope.Tag)
+def fix_type_sharing(self):
+  self.type = self.type.fix_type_sharing()
+del fix_type_sharing
+
+@method(Node)
+def fix_type_sharing(self):
+  for i in range(len(self.children)):
+    self.children[i].fix_type_sharing()
+@method(ItemList)
+def fix_type_sharing(self):
+  self.scope.fix_type_sharing()
+  Node.fix_type_sharing(self)
+@method(Expression)
+def fix_type_sharing(self):
+  self.type = self.type.fix_type_sharing()
+  Node.fix_type_sharing(self)
+@method(Initializer)
+def fix_type_sharing(self):
+  self.type = self.type.fix_type_sharing()
+  Node.fix_type_sharing(self)
+@method(DesignatorInitializer)
+def fix_type_sharing(self):
+  self.type = self.type.fix_type_sharing()
+  Node.fix_type_sharing(self)
+@method(MemberIdentifier)
+def fix_type_sharing(self):
+  self.type = self.type.fix_type_sharing()
+  Node.fix_type_sharing(self)
+@method(ParameterDeclaration)
+def fix_type_sharing(self):
+  self.type = self.type.fix_type_sharing()
+  Node.fix_type_sharing(self)
+@method(TypeName)
+def fix_type_sharing(self):
+  self.type = self.type.fix_type_sharing()
+  Node.fix_type_sharing(self)
index f201894..b532fa7 100644 (file)
--- a/ansi_c.y
+++ b/ansi_c.y
@@ -99,7 +99,7 @@ primary_expression
       assert False
 
     expression_identifier.calc_type()
-    #expression_identifier.calc_value()
+    expression_identifier.calc_value()
   }
   | constant
   | STRING_LITERAL
@@ -170,12 +170,12 @@ postfix_expression
       rank = actual_parameters.children[i].type.rank
       if rank >= 0 and rank < t_def.INT_RANK:
         actual_parameters.children[i] = t_def.add_cast(
-          base_type.type_signed_int,
+          t_def.type_signed_int,
           actual_parameters.children[i]
         )
       elif rank >= t_def.FLOAT_RANK and rank < t_def.DOUBLE_RANK:
         actual_parameters.children[i] = t_def.add_cast(
-          base_type.rank_to_type[rank + t_def.DOUBLE_RANK - t_def.FLOAT_RANK],
+          t_def.rank_to_type[rank + t_def.DOUBLE_RANK - t_def.FLOAT_RANK],
           actual_parameters.children[i]
         )
   }
@@ -312,14 +312,14 @@ conditional_expression
 
 /* occurs in array declarator */
 assignment_expression_or_asterisk_opt
-  : %space (?E{t_def.ExpressionEmpty})
+  : %space (?E{build, t_def.ExpressionEmpty})
   | %space (?E{t_def.ExpressionAsterisk}'*')
   | assignment_expression {
     container = yy_element_stack[-1]
     assert isinstance(container.children[0], t_def.Expression)
-    if container.children[0].type != base_type.type_size_t:
+    if container.children[0].type != t_def.type_size_t:
       container.children[0] = t_def.add_cast(
-        base_type.type_size_t,
+        t_def.type_size_t,
         container.children[0]
       )
   }
@@ -356,9 +356,9 @@ equals_constant_expression_opt
   | '=' constant_expression {
     container = yy_element_stack[-1]
     assert isinstance(container.children[0], t_def.Expression)
-    if container.children[0].type != base_type.type_signed_int:
+    if container.children[0].type != t_def.type_signed_int:
       container.children[0] = t_def.add_cast(
-        base_type.type_signed_int,
+        t_def.type_signed_int,
         container.children[0]
       )
   }
@@ -409,7 +409,7 @@ declaration_specifier_list1
 
     declaration_specifier_list = yy_element_stack[-1].children[0]
 
-    assert(not doing_typedef)
+    assert not doing_typedef
     for i in declaration_specifier_list.children:
       if (
         isinstance(i, t_def.StorageClassSpecifier) and
@@ -489,11 +489,15 @@ init_declarator
       ):
         storage_class1 = t_def.STORAGE_CLASS_AUTO
 
-      align_m1 = _type.align - 1
-      scope.size = (scope.size + align_m1) & ~align_m1
-      scope_identifier.offset = scope.size
-      if _type.size >= 0: # unknown size treated as 0 bytes (not correct!!)
-        scope.size += _type.size
+      # don't do this here -- we don't have size of indeterminate array yet
+      #align_m1 = _type.align - 1
+      #scope.size = (scope.size + align_m1) & ~align_m1
+      #scope_identifier.offset = scope.size
+      #if _type.size >= 0: # unknown size treated as 0 bytes (not correct!!)
+      #  scope.size += _type.size
+    elif storage_class1 == t_def.STORAGE_CLASS_TYPEDEF: # TEMPORARY
+      assert not scope_identifier.defined # TEMPORARY
+      scope_identifier.defined = True # TEMPORARY
 
     if storage_class1 == t_def.STORAGE_CLASS_NONE:
       pass
@@ -533,18 +537,23 @@ init_declarator
       t_def.STORAGE_CLASS_TYPEDEF
     }:
       assert len(init_declarator.children) < 2 # can t have initializer
-    elif (
-      isinstance(_type, t_def.TypeArray) and
-      _type.element_count == -1 and
-      len(init_declarator.children) >= 2
-    ):
-      # size of indeterminate sized array can be deduced from initializer
-      element_size = _type.element_type.size
-      assert element_size >= 0 # must be of determinate size
-      _type.size = max_index * element_size
-      _type.element_count = max_index
     else:
+      if (
+        isinstance(_type, t_def.TypeArray) and
+        _type.element_count == -1 and
+        len(init_declarator.children) >= 2
+      ):
+        # size of indeterminate sized array can be deduced from initializer
+        element_size = _type.element_type.size
+        assert element_size >= 0 # must be of determinate size
+        _type.size = max_index * element_size
+        _type.element_count = max_index
+
       assert _type.size >= 0 # must be of determinate size
+      align_m1 = _type.align - 1
+      scope.size = (scope.size + align_m1) & ~align_m1
+      scope_identifier.offset = scope.size
+      scope.size += _type.size
   }
   ;
 
@@ -592,7 +601,7 @@ struct_specifier
       _type = scope_tag.type
     else:
       _type = t_def.TypeStruct()
-      scope_tag = t_def.Scope.Tag(type = _type)
+      scope_tag = t_def.Scope.Tag(name = name, type = _type)
       scope.struct_tags[name] = scope_tag
     struct_specifier.scope_tag = scope_tag
 
@@ -624,6 +633,11 @@ struct_specifier
         )
         size += member_type.size
         align = max(align, member_type.align)
+
+    # make the size a multiple of the alignment
+    align_m1 = align - 1
+    size = (size + align_m1) & ~align_m1
+
     _type.size = size
     _type.align = align
     _type.members = members
@@ -642,7 +656,7 @@ struct_specifier
       i = i.enclosing_scope
     else:
       _type = t_def.TypeStruct()
-      scope_tag = t_def.Scope.Tag(type = _type)
+      scope_tag = t_def.Scope.Tag(name = name, type = _type)
       scope.struct_tags[name] = scope_tag
     struct_specifier.scope_tag = scope_tag
   }
@@ -663,7 +677,7 @@ union_specifier
       _type = scope_tag.type
     else:
       _type = t_def.TypeUnion()
-      scope_tag = t_def.Scope.Tag(type = _type)
+      scope_tag = t_def.Scope.Tag(name = name, type = _type)
       scope.union_tags[name] = scope_tag
     union_specifier.scope_tag = scope_tag
 
@@ -690,6 +704,11 @@ union_specifier
         )
         size = max(size, member_type.size)
         align = max(align, member_type.align)
+
+    # make the size a multiple of the alignment
+    align_m1 = align - 1
+    size = (size + align_m1) & ~align_m1
+
     _type.size = size
     _type.align = align
     _type.members = members
@@ -708,7 +727,7 @@ union_specifier
       i = i.enclosing_scope
     else:
       _type = t_def.TypeUnion()
-      scope_tag = t_def.Scope.Tag(type = _type)
+      scope_tag = t_def.Scope.Tag(name = name, type = _type)
       scope.union_tags[name] = scope_tag
     union_specifier.scope_tag = scope_tag
   }
@@ -752,9 +771,9 @@ struct_declarator_list
 struct_declarator
   : %space (?E{t_def.StructDeclarator}declarator_opt ':' constant_expression) {
     struct_declarator = yy_element_stack[-1].children[0]
-    if struct_declarator.children[1].type != base_type.type_signed_int:
+    if struct_declarator.children[1].type != t_def.type_signed_int:
       struct_declarator.children[1] = t_def.add_cast(
-        base_type.type_signed_int,
+        t_def.type_signed_int,
         struct_declarator.children[1]
       )
   }
@@ -780,7 +799,7 @@ enum_specifier
         size = t_def.INT_SIZE,
         align = t_def.INT_ALIGN
       )
-      scope_tag = t_def.Scope.Tag(type = _type)
+      scope_tag = t_def.Scope.Tag(name = name, type = _type)
       scope.enum_tags[name] = scope_tag
     enum_specifier.scope_tag = scope_tag
 
@@ -794,7 +813,7 @@ enum_specifier
       assert member_name not in members
       if len(i.children) >= 2:
         expression = i.children[1]
-        assert expression.type == base_type.type_signed_int
+        assert expression.type == t_def.type_signed_int
         assert isinstance(expression.value, t_def.ValueInt)
         value = expression.value.value
       members[member_name] = t_def.TypeEnum.Member(
@@ -830,7 +849,7 @@ enum_specifier
         size = t_def.INT_SIZE,
         align = t_def.INT_ALIGN
       )
-      scope_tag = t_def.Scope.Tag(type = _type)
+      scope_tag = t_def.Scope.Tag(name = name, type = _type)
       scope.enum_tags[name] = scope_tag
     enum_specifier.scope_tag = scope_tag
   }
@@ -886,9 +905,9 @@ alignment_specifier
   : %space (?E{t_def.AlignAsType}ALIGNAS '(' type_name ')')
   | %space (?E{t_def.AlignAsExpression}ALIGNAS '(' constant_expression ')') {
     align_as_expression = yy_element_stack[-1].children[0]
-    if align_as_expression.children[0].type != base_type.type_size_t:
+    if align_as_expression.children[0].type != t_def.type_size_t:
       align_as_expression.children[0] = t_def.add_cast(
-        base_type.type_size_t,
+        t_def.type_size_t,
         align_as_expression.children[0]
       )
   }
@@ -1008,7 +1027,7 @@ initializer
     initializer_array_or_struct = yy_element_stack[-1].children[0]
     initializer_array_or_struct.type = initializer_stack[-1][0]
   }
-  | (?E{t_def.InitializerExpression}assignment_expression) {
+  | %space (?E{t_def.InitializerExpression}assignment_expression) {
     initializer_expression = yy_element_stack[-1].children[0]
     if initializer_expression.children[0].type != initializer_stack[-1][0]:
       initializer_expression.children[0] = t_def.add_cast(
@@ -1047,7 +1066,7 @@ designator_initializer
 
           # get numeric index from designator
           expression = i.children[0]
-          assert expression.type == base_type.type_ssize_t
+          assert expression.type == t_def.type_ssize_t
           assert isinstance(expression.value, t_def.ValueInt)
           j = expression.value.value
 
@@ -1103,9 +1122,9 @@ designator_list
 designator
   : %space (?E{t_def.DesignatorIndex}'[' constant_expression ']') {
     designator_index = yy_element_stack[-1].children[0]
-    if designator_index.children[0].type != base_type.type_ssize_t:
+    if designator_index.children[0].type != t_def.type_ssize_t:
       designator_index.children[0] = t_def.add_cast(
-        base_type.type_ssize_t,
+        t_def.type_ssize_t,
         designator_index.children[0]
       )
   }
@@ -1115,9 +1134,9 @@ designator
 static_assert_declaration
   : %space (?E{t_def.StaticAssertDeclaration}STATIC_ASSERT '(' constant_expression ',' STRING_LITERAL ')' ';') {
     static_assert_declaration = yy_element_stack[-1].children[0]
-    if static_assert_declaration.children[0].type != base_type.type_bool:
+    if static_assert_declaration.children[0].type != t_def.type_bool:
       static_assert_declaration.children[0] = t_def.add_cast(
-        base_type.type_bool,
+        t_def.type_bool,
         static_assert_declaration.children[0]
       )
   }
@@ -1156,7 +1175,7 @@ statement
     statement_expression = yy_element_stack[-1].children[0]
     if not isinstance(statement_expression.children[0].type, t_def.TypeVoid):
       statement_expression.children[0] = t_def.add_cast(
-        base_type.type_void,
+        t_def.type_void,
         statement_expression.children[0]
       )
   }
@@ -1164,7 +1183,7 @@ statement
     statement_if_else = yy_element_stack[-1].children[0]
     if not isinstance(statement_if_else.children[0].type, t_def.TypeBool):
       statement_if_else.children[0] = t_def.add_cast(
-        base_type.type_bool,
+        t_def.type_bool,
         statement_if_else.children[0]
       )
   }
@@ -1172,7 +1191,7 @@ statement
     statement_if = yy_element_stack[-1].children[0]
     if not isinstance(statement_if.children[0].type, t_def.TypeBool):
       statement_if.children[0] = t_def.add_cast(
-        base_type.type_bool,
+        t_def.type_bool,
         statement_if.children[0]
       )
   }
@@ -1188,7 +1207,7 @@ statement
     statement_while = yy_element_stack[-1].children[0]
     if not isinstance(statement_while.children[0].type, t_def.TypeBool):
       statement_while.children[0] = t_def.add_cast(
-        base_type.type_bool,
+        t_def.type_bool,
         statement_while.children[0]
       )
   }
@@ -1196,7 +1215,7 @@ statement
     statement_do_while = yy_element_stack[-1].children[0]
     if not isinstance(statement_do_while.children[1].type, t_def.TypeBool):
       statement_do_while.children[1] = t_def.add_cast(
-        base_type.type_bool,
+        t_def.type_bool,
         statement_do_while.children[1]
       )
   }
@@ -1205,17 +1224,17 @@ statement
     statement_expression = statement_for.children[0]
     if not isinstance(statement_expression.children[0].type, t_def.TypeVoid):
       statement_expression.children[0] = t_def.add_cast(
-        base_type.type_void,
+        t_def.type_void,
         statement_expression.children[0]
       )
     if not isinstance(statement_for.children[1].type, t_def.TypeBool):
       statement_for.children[1] = t_def.add_cast(
-        base_type.type_bool,
+        t_def.type_bool,
         statement_for.children[1]
       )
     if not isinstance(statement_for.children[2].type, t_def.TypeVoid):
       statement_for.children[2] = t_def.add_cast(
-        base_type.type_void,
+        t_def.type_void,
         statement_for.children[2]
       )
   }
@@ -1223,12 +1242,12 @@ statement
     statement_for = yy_element_stack[-1].children[0]
     if not isinstance(statement_for.children[1].type, t_def.TypeBool):
       statement_for.children[1] = t_def.add_cast(
-        base_type.type_bool,
+        t_def.type_bool,
         statement_for.children[1]
       )
     if not isinstance(statement_for.children[2].type, t_def.TypeVoid):
       statement_for.children[2] = t_def.add_cast(
-        base_type.type_void,
+        t_def.type_void,
         statement_for.children[2]
       )
   }
index 892508f..a0b1db1 100644 (file)
 import t_def
 
-# primitive types
-type_void = t_def.TypeVoid(size = 0)
-type_bool = t_def.TypeBool(rank = 0, size = 1)
-type_signed_char = t_def.TypeIntSigned(rank = 1, size = 1)
-type_unsigned_char = t_def.TypeIntUnsigned(rank = 2, size = 1)
-type_signed_short = t_def.TypeIntSigned(rank = 3, size = 2, align = 2)
-type_unsigned_short = t_def.TypeIntUnsigned(rank = 4, size = 2, align = 2)
-type_signed_int = t_def.TypeIntSigned(rank = 5, size = 4, align = 4)
-type_unsigned_int = t_def.TypeIntUnsigned(rank = 6, size = 4, align = 4)
-type_signed_long = t_def.TypeIntSigned(rank = 7, size = 8, align = 8)
-type_unsigned_long = t_def.TypeIntUnsigned(rank = 8, size = 8, align = 8)
-type_signed_long_long = t_def.TypeIntSigned(rank = 9, size = 16, align = 16)
-type_unsigned_long_long = t_def.TypeIntUnsigned(rank = 10, size = 16, align = 16)
-type_float = t_def.TypeFloat(rank = 11, size = 4, align = 4)
-type_float_imaginary = t_def.TypeFloatImaginary(rank = 12, size = 4, align = 4)
-type_float_complex = t_def.TypeFloatComplex(rank = 13, size = 8, align = 4)
-type_double = t_def.TypeFloat(rank = 14, size = 8, align = 8)
-type_double_imaginary = t_def.TypeFloatImaginary(rank = 15, size = 8, align = 8)
-type_double_complex = t_def.TypeFloatComplex(rank = 16, size = 16, align = 8)
-type_long_double = t_def.TypeFloat(rank = 17, size = 16, align = 16)
-type_long_double_imaginary = t_def.TypeFloatImaginary(rank = 18, size = 16, align = 16)
-type_long_double_complex = t_def.TypeFloatComplex(rank = 19, size = 32, align = 16)
-
-type_ssize_t = type_signed_int
-assert type_ssize_t.size == t_def.POINTER_SIZE
-type_size_t = type_unsigned_int
-assert type_size_t.size == t_def.POINTER_SIZE
-
-rank_to_type = [
-  type_bool, # 0
-  type_signed_char, # 1
-  type_unsigned_char, # 2
-  type_signed_short, # 3
-  type_unsigned_short, # 4
-  type_signed_int, # 5
-  type_unsigned_int, # 6
-  type_signed_long, # 7
-  type_unsigned_long, # 8
-  type_signed_long_long, # 9
-  type_unsigned_long_long, # 10
-  type_float, # 11
-  type_float_imaginary, # 12
-  type_float_complex, # 13
-  type_double, # 14
-  type_double_imaginary, # 15
-  type_double_complex, # 16
-  type_long_double, # 17
-  type_long_double_imaginary, # 18
-  type_long_double_complex # 19
-]
-
-# this is not correct -- check standard
-# minimum rank, maximum rank, promoted rank
-complex_promotions = {
-  (11, 12): 13, # float, float imaginary -> float complex
-  (11, 15): 16, # float, double imaginary -> double complex
-  (11, 18): 19, # float, long double imaginary -> long double complex
-  (14, 15): 16, # double, double imaginary -> double complex
-  (14, 18): 19, # double, long double imaginary -> long double complex
-  (17, 18): 19 # long double, long double imaginary -> long double complex
-}
-
 # void char short int long float double signed unsigned bool imaginary complex
 type_specifiers_to_type = {
-  (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): type_void,
-  (0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_char,
-  (0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_char,
-  (0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_char,
-  (0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_short,
-  (0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_short,
-  (0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_short,
-  (0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_short,
-  (0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_short,
-  (0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_short,
-  (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_int,
-  (0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_int,
-  (0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_int,
-  (0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0): type_signed_int,
-  (0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0): type_signed_int,
-  (0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0): type_unsigned_int,
-  (0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0): type_signed_long,
-  (0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0): type_signed_long,
-  (0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0): type_unsigned_long,
-  (0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0): type_signed_long,
-  (0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0): type_signed_long,
-  (0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0): type_unsigned_long,
-  (0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0): type_signed_long_long,
-  (0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0): type_signed_long_long,
-  (0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0): type_unsigned_long_long,
-  (0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0): type_signed_long_long,
-  (0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0): type_signed_long_long,
-  (0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0): type_unsigned_long_long,
-  (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0): type_float,
-  (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0): type_float_imaginary,
-  (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1): type_float_complex,
-  (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0): type_double,
-  (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0): type_double_imaginary,
-  (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1): type_double_complex,
-  (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0): type_long_double,
-  (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0): type_long_double_imaginary,
-  (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1): type_long_double_complex,
-  (0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0): type_bool
+  (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_void,
+  (0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_char,
+  (0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_char,
+  (0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_char,
+  (0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_short,
+  (0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_short,
+  (0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_short,
+  (0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_short,
+  (0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_short,
+  (0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_short,
+  (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_int,
+  (0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_int,
+  (0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_int,
+  (0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_int,
+  (0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_int,
+  (0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_int,
+  (0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_long,
+  (0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_long,
+  (0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_long,
+  (0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_long,
+  (0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_long,
+  (0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_long,
+  (0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_long_long,
+  (0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_long_long,
+  (0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_long_long,
+  (0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0): t_def.type_signed_long_long,
+  (0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0): t_def.type_signed_long_long,
+  (0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0): t_def.type_unsigned_long_long,
+  (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0): t_def.type_float,
+  (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0): t_def.type_float_imaginary,
+  (0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1): t_def.type_float_complex,
+  (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0): t_def.type_double,
+  (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0): t_def.type_double_imaginary,
+  (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1): t_def.type_double_complex,
+  (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0): t_def.type_long_double,
+  (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0): t_def.type_long_double_imaginary,
+  (0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1): t_def.type_long_double_complex,
+  (0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0): t_def.type_bool
 }
 
 @t_def.method(t_def.SpecifierList)
index 1bbb216..c34df89 100644 (file)
@@ -1,21 +1,32 @@
 import base_type
 import t_def
 
+# this is not correct -- check standard
+# minimum rank, maximum rank, promoted rank
+complex_promotions = {
+  (11, 12): 13, # float, float imaginary -> float complex
+  (11, 15): 16, # float, double imaginary -> double complex
+  (11, 18): 19, # float, long double imaginary -> long double complex
+  (14, 15): 16, # double, double imaginary -> double complex
+  (14, 18): 19, # double, long double imaginary -> long double complex
+  (17, 18): 19 # long double, long double imaginary -> long double complex
+}
+
 # f l
 floating_suffix_to_type = {
-  (0, 0): base_type.type_double,
-  (1, 0): base_type.type_float,
-  (0, 1): base_type.type_long_double
+  (0, 0): t_def.type_double,
+  (1, 0): t_def.type_float,
+  (0, 1): t_def.type_long_double
 }
 
 # u l ll
 integer_suffix_to_type = {
-  (0, 0, 0): base_type.type_signed_int,
-  (1, 0, 0): base_type.type_unsigned_int,
-  (0, 1, 0): base_type.type_signed_long,
-  (1, 1, 0): base_type.type_unsigned_long,
-  (0, 0, 1): base_type.type_signed_long_long,
-  (1, 0, 1): base_type.type_unsigned_long_long
+  (0, 0, 0): t_def.type_signed_int,
+  (1, 0, 0): t_def.type_unsigned_int,
+  (0, 1, 0): t_def.type_signed_long,
+  (1, 1, 0): t_def.type_unsigned_long,
+  (0, 0, 1): t_def.type_signed_long_long,
+  (1, 0, 1): t_def.type_unsigned_long_long
 }
 
 def add_cast(_type, expression):
@@ -35,15 +46,15 @@ def calc_type(self):
   rank = self.children[0].type.rank
   assert rank >= 0 # pointers, etc are not handled yet
   promoted_rank = max(rank, t_def.INT_RANK)
-  promoted_type = base_type.rank_to_type[promoted_rank]
+  promoted_type = t_def.rank_to_type[promoted_rank]
   if rank < promoted_rank:
     self.children[0] = add_cast(promoted_type, self.children[0])
   self.type = promoted_type
 @t_def.method(t_def.ExpressionUnaryLogical)
 def calc_type(self):
-  if self.children[0].type != base_type.type_bool:
-    self.children[0] = add_cast(base_type.type_bool, self.children[0])
-  self.type = base_type.type_bool
+  if self.children[0].type != t_def.type_bool:
+    self.children[0] = add_cast(t_def.type_bool, self.children[0])
+  self.type = t_def.type_bool
 @t_def.method(t_def.ExpressionBinaryArithmeticOrCompareOrLogical)
 def calc_type(self):
   rank0 = self.children[0].type.rank
@@ -51,11 +62,11 @@ def calc_type(self):
   min_rank = min(rank0, rank1)
   assert min_rank >= 0 # pointers, etc are not handled yet
   max_rank = max(rank0, rank1)
-  promoted_rank = base_type.complex_promotions.get(
+  promoted_rank = complex_promotions.get(
     (min_rank, max_rank),
     max(max_rank, t_def.INT_RANK)
   )
-  promoted_type = base_type.rank_to_type[promoted_rank]
+  promoted_type = t_def.rank_to_type[promoted_rank]
   if rank0 < promoted_rank:
     self.children[0] = add_cast(promoted_type, self.children[0])
   if rank1 < promoted_rank:
@@ -66,12 +77,12 @@ def calc_type(self):
   type0 = self.children[0].type
   type1 = self.children[1].type
   if isinstance(type0, t_def.TypePointer) and isinstance(type1, t_def.TypeInt):
-    if type1 != base_type.type_ssize_t:
-      self.children[1] = add_cast(base_type.type_ssize_t, self.children[1])
+    if type1 != t_def.type_ssize_t:
+      self.children[1] = add_cast(t_def.type_ssize_t, self.children[1])
     self.type = type0
   elif isinstance(type0, t_def.TypeInt) and isinstance(type1, t_def.TypePointer):
-    if type0 != base_type.type_ssize_t:
-      self.children[0] = add_cast(base_type.type_ssize_t, self.children[0])
+    if type0 != t_def.type_ssize_t:
+      self.children[0] = add_cast(t_def.type_ssize_t, self.children[0])
     self.type = type1
   else:
     t_def.ExpressionBinaryArithmeticOrCompareOrLogical.calc_type(self)
@@ -80,11 +91,11 @@ def calc_type(self):
   type0 = self.children[0].type
   type1 = self.children[1].type
   if isinstance(type0, t_def.TypePointer) and isinstance(type1, t_def.TypeInt):
-    if type1 != base_type.type_ssize_t:
-      self.children[1] = add_cast(base_type.type_ssize_t, self.children[1])
+    if type1 != t_def.type_ssize_t:
+      self.children[1] = add_cast(t_def.type_ssize_t, self.children[1])
     self.type = type0
   elif isinstance(type0, t_def.TypePointer) and isinstance(type1, t_def.TypePointer):
-    self.type = base_type.type_ssize_t
+    self.type = t_def.type_ssize_t
   else:
     t_def.ExpressionBinaryArithmeticOrCompareOrLogical.calc_type(self)
 @t_def.method(t_def.ExpressionBinaryCompare)
@@ -95,14 +106,14 @@ def calc_type(self):
     pass
   else:
     t_def.ExpressionBinaryArithmeticOrCompareOrLogical.calc_type(self)
-  self.type = base_type.type_bool
+  self.type = t_def.type_bool
 @t_def.method(t_def.ExpressionBinaryLogical)
 def calc_type(self):
-  self.type = base_type.type_bool
-  if self.children[0].type != base_type.type_bool:
-    self.children[0] = add_cast(base_type.type_bool, self.children[0])
-  if self.children[1].type != base_type.type_bool:
-    self.children[1] = add_cast(base_type.type_bool, self.children[1])
+  self.type = t_def.type_bool
+  if self.children[0].type != t_def.type_bool:
+    self.children[0] = add_cast(t_def.type_bool, self.children[0])
+  if self.children[1].type != t_def.type_bool:
+    self.children[1] = add_cast(t_def.type_bool, self.children[1])
 @t_def.method(t_def.ExpressionArrayOrStruct)
 def calc_type(self):
   self.type = self.children[0].type
@@ -124,7 +135,7 @@ def calc_type(self):
   )
 @t_def.method(t_def.ExpressionAlignOfType)
 def calc_type(self):
-  self.type = base_type.type_size_t
+  self.type = t_def.type_size_t
 @t_def.method(t_def.ExpressionArrayOrStruct)
 def calc_type(self):
   self.type = t_def.array_decay(self.children[0].type)
@@ -141,25 +152,25 @@ def calc_type(self):
   self.type = self.children[0].type
 @t_def.method(t_def.ExpressionCharacterConstant)
 def calc_type(self):
-  self.type = base_type.type_signed_int
+  self.type = t_def.type_signed_int
 @t_def.method(t_def.ExpressionComma)
 def calc_type(self):
   if not isinstance(self.children[0].type, t_def.TypeVoid):
     self.children[0] = add_cast(
-      base_type.type_void,
+      t_def.type_void,
       self.children[0]
     )
   self.type = self.children[1].type
 @t_def.method(t_def.ExpressionConditional)
 def calc_type(self):
-  if self.children[0].type != base_type.type_bool:
-    self.children[0] = add_cast(base_type.type_bool, self.children[0])
+  if self.children[0].type != t_def.type_bool:
+    self.children[0] = add_cast(t_def.type_bool, self.children[0])
   rank1 = self.children[1].type.rank
   rank2 = self.children[2].type.rank
   min_rank = min(rank1, rank2)
   assert min_rank >= 0 # pointers, etc are not handled yet
   max_rank = max(rank1, rank2)
-  max_type = base_type.rank_to_type[max_rank]
+  max_type = t_def.rank_to_type[max_rank]
   if rank1 < max_rank:
     self.children[1] = add_cast(max_type, self.children[1])
   if rank2 < max_rank:
@@ -172,7 +183,7 @@ def calc_type(self):
   self.type = t_def.array_decay(pointer_type.target_type)
 @t_def.method(t_def.ExpressionEmpty)
 def calc_type(self):
-  self.type = base_type.type_void
+  self.type = t_def.type_void
 @t_def.method(t_def.ExpressionMember)
 def calc_type(self):
   struct_or_union_type = self.children[0].type
@@ -206,8 +217,8 @@ def calc_type(self):
 def calc_type(self):
   pointer_type = self.children[0].type
   assert isinstance(pointer_type, t_def.TypePointer)
-  if self.children[1].type != base_type.type_ssize_t:
-    self.children[1] = add_cast(base_type.type_ssize_t, self.children[1])
+  if self.children[1].type != t_def.type_ssize_t:
+    self.children[1] = add_cast(t_def.type_ssize_t, self.children[1])
   self.type = t_def.array_decay(pointer_type.target_type)
 @t_def.method(t_def.ExpressionIntegerConstant)
 def calc_type(self):
@@ -217,15 +228,15 @@ def calc_type(self):
   self.type = integer_suffix_to_type[tuple(integer_suffix)]
 @t_def.method(t_def.ExpressionSizeOfExpression)
 def calc_type(self):
-  self.type = base_type.type_size_t
+  self.type = t_def.type_size_t
 @t_def.method(t_def.ExpressionSizeOfType)
 def calc_type(self):
-  self.type = base_type.type_size_t
+  self.type = t_def.type_size_t
 @t_def.method(t_def.ExpressionStringLiteral)
 def calc_type(self):
   self.type = t_def.TypePointer(
     size = t_def.POINTER_SIZE,
     align = t_def.POINTER_ALIGN,
-    target_type = base_type.type_signed_char
+    target_type = t_def.type_signed_char
   )
 del calc_type
index 81f05bb..d3c5ada 100644 (file)
@@ -196,7 +196,7 @@ def calc_value(self):
         self.type.size * 8,
         isinstance(self.type, t_def.TypeIntUnsigned)
       )
-    elif isinstance(self.type, t_def.TypeFloat):
+    elif isinstance(self.type, t_def.TypeFloatReal):
       assert isinstance(value, t_def.ValueFloat)
       self.value = float_value(
         self.operate_float(value.value),
@@ -223,7 +223,7 @@ def calc_value(self):
         self.type.size * 8,
         isinstance(self.type, t_def.TypeIntUnsigned)
       )
-    elif isinstance(self.type, t_def.TypeFloat):
+    elif isinstance(self.type, t_def.TypeFloatReal):
       assert isinstance(value0, t_def.ValueFloat)
       assert isinstance(value1, t_def.ValueFloat)
       self.value = float_value(
@@ -265,7 +265,7 @@ def calc_value(self):
         self.value = bool_value(
           self.operate_relational_int(value0.value, value1.value)
         )
-      elif isinstance(type0, t_def.TypeFloat) and isinstance(type1, t_def.TypeFloat):
+      elif isinstance(type0, t_def.TypeFloatReal) and isinstance(type1, t_def.TypeFloatReal):
         assert isinstance(value0, t_def.ValueFloat)
         assert isinstance(value1, t_def.ValueFloat)
         self.value = bool_value(
@@ -317,13 +317,13 @@ def calc_value(self):
           self.type.size * 8,
           isinstance(self.type, t_def.TypeIntUnsigned)
         )
-      elif isinstance(self.type, t_def.TypeFloat):
+      elif isinstance(self.type, t_def.TypeFloatReal):
         self.value = float_value(
           gmpy2.mpfr(from_value.value),
           self.type.size * 8
         )
       # other from_type is not handled yet
-    elif isinstance(from_type, t_def.TypeFloat):
+    elif isinstance(from_type, t_def.TypeFloatReal):
       assert isinstance(from_value, t_def.ValueFloat)
       if isinstance(self.type, t_def.TypeBool):
         self.value = bool_value(int(bool(from_value.value)))
@@ -333,7 +333,7 @@ def calc_value(self):
           self.type.size * 8,
           isinstance(self.type, t_def.TypeIntUnsigned)
         )
-      elif isinstance(self.type, t_def.TypeFloat):
+      elif isinstance(self.type, t_def.TypeFloatReal):
         self.value = float_value(
           from_value.value,
           self.type.size * 8
index 91aae75..188328e 100644 (file)
@@ -15,7 +15,7 @@ def get_name_and_type(self, _base_type):
   if isinstance(expression, t_def.ExpressionEmpty):
     element_count = -1
   else:
-    assert expression.type == base_type.type_size_t
+    assert expression.type == t_def.type_size_t
     assert isinstance(expression.value, t_def.ValueInt)
     element_count = expression.value.value
   return self.children[0].get_name_and_type(
index 0cd4414..4a806d3 100644 (file)
@@ -112,6 +112,7 @@ class Type {
   int align = 1;
 };
 class TypeVoid: Type;
+class TypeBool: Type;
 class TypeInt: Type;
 class TypeIntSigned: TypeInt;
 class TypeEnum: TypeIntSigned {
@@ -123,10 +124,9 @@ class TypeEnum: TypeIntSigned {
 };
 class TypeIntUnsigned: TypeInt;
 class TypeFloat: Type;
-class TypeFloat: TypeFloat;
+class TypeFloatReal: TypeFloat;
 class TypeFloatImaginary: TypeFloat;
 class TypeFloatComplex: TypeFloat;
-class TypeBool: Type;
 class TypePointer: Type {
   ref target_type;
 };
@@ -520,7 +520,7 @@ unsigned_int_size_to_specifiers = {
   ]
 }
 
-float_size_to_specifiers = {
+float_real_size_to_specifiers = {
   4: [
     TYPE_SPECIFIER_FLOAT
   ],
@@ -595,11 +595,11 @@ def get_type_specifiers(self, scope):
     TypeSpecifier(n = i)
     for i in unsigned_int_size_to_specifiers[self.size]
   ]
-@method(TypeFloat)
+@method(TypeFloatReal)
 def get_type_specifiers(self, scope):
   return [
     TypeSpecifier(n = i)
-    for i in float_size_to_specifiers[self.size]
+    for i in float_real_size_to_specifiers[self.size]
   ]
 @method(TypeFloatImaginary)
 def get_type_specifiers(self, scope):
index 1c93c9b..74c8c18 100644 (file)
@@ -20,9 +20,13 @@ def scope_analysis(self, context):
     declarator = init_declarator.children[0]
 
     # if it's function, allow multiple definition
-    is_function = t_def.get_declarator_function(
+    declarator_function = t_def.get_declarator_function(
       declarator
-    ) is not None
+    )
+    is_function = (
+      declarator_function is not None and
+      isinstance(declarator_function.children[0], t_def.DeclaratorIdentifier)
+    )
 
     declarator_identifier = t_def.get_declarator_identifier(
       declarator
@@ -55,11 +59,8 @@ def scope_analysis(self, context):
     self.children[1]
   )
   assert declarator_function is not None
-
-  declarator_identifier = t_def.get_declarator_identifier(
-    declarator_function
-  )
-  assert declarator_identifier is not None
+  declarator_identifier = declarator_function.children[0]
+  assert isinstance(declarator_identifier, t_def.DeclaratorIdentifier)
 
   # add the function being defined to the enclosing scope
   name = declarator_identifier.text[0]
@@ -94,7 +95,10 @@ def scope_analysis(self, context):
         print('scope analysis: parameter:', parameter_name)
         assert parameter_name not in new_scope.identifiers
         parameter_declarator_identifier.scope_identifier = (
-          t_def.Scope.Identifier(name = parameter_name)
+          t_def.Scope.Identifier(
+            name = parameter_name,
+            defined = True
+          )
         )
         new_scope.identifiers[parameter_name] = (
           parameter_declarator_identifier.scope_identifier
@@ -104,7 +108,8 @@ def scope_analysis(self, context):
       parameter_name = parameter_identifier.text[0]
       assert parameter_name not in new_scope.identifiers
       parameter_identifier.scope_identifier = t_def.Scope.Identifier(
-        name = parameter_name
+        name = parameter_name,
+        defined = True
       )
       new_scope.identifiers[parameter_name] = (
         parameter_identifier.scope_identifier
index 5e36866..dfece35 100644 (file)
@@ -2,18 +2,6 @@ import base_type
 import calc_value
 import t_def
 
-def add_cast(_type, expression):
-  if expression.type != _type:
-    # wrapping a node hides the wrapped node from value analysis
-    # strictly speaking, the type analysis should not be mixed with
-    # the value analysis, but it is more pragmatic to cheat a little
-    expression.calc_value()
-
-    expression = ExpressionCast(
-      children = [TypeName(type = _type), expression]
-    )
-  return expression
-
 # in a few special cases (function header followed by body, declarator
 # followed by initializer) the ordinary post-order type analysis is not
 # sufficient and we need to intervene in the middle of the rule to do
@@ -62,25 +50,19 @@ def mid_type_analysis(self, context):
 
   # fill in the formal parameters in the inner scope
   new_scope = self.children[3].scope
-  new_scope.size = 0
   if isinstance(declarator_function, t_def.DeclaratorFunctionANSI):
     parameter_declaration_list = declarator_function.children[1]
     if not t_def.parameter_declaration_list_is_void(
       parameter_declaration_list
     ):
-      for parameter_declaration in parameter_declaration_list.children:
-        parameter_name, parameter_type = (
-          parameter_declaration.children[1].get_name_and_type(
-            parameter_declaration.children[0].get_base_type()
-          )
-        )
-        parameter_type = t_def.array_decay(parameter_type)
-        print('type analysis: parameter:', parameter_name)
-
+      for i in range(len(parameter_declaration_list.children)):
+        parameter_declaration = parameter_declaration_list.children[i]
         parameter_declarator_identifier = t_def.get_declarator_identifier(
           parameter_declaration.children[1]
         )
         assert parameter_declarator_identifier is not None
+        parameter_name = parameter_declarator_identifier.text[0]
+        parameter_type = _type.formal_parameters[i] # enforce sharing
 
         parameter_scope_identifier = (
           parameter_declarator_identifier.scope_identifier
@@ -97,6 +79,9 @@ def mid_type_analysis(self, context):
         # copy scope_identifier from the DeclaratorIdentifier to the
         # ParameterDeclaration, we don't need the declarator anymore
         parameter_declaration.scope_identifier = parameter_scope_identifier
+        parameter_declarator_identifier.scope_identifier = None # TEMPORARY
+        parameter_declaration.name = parameter_name # TEMPORARY
+        parameter_declaration.type = parameter_type # TEMPORARY
   elif isinstance(declarator_function, t_def.DeclaratorFunctionKAndR):
     # has no information about formal parameter types, ignore for now
     pass
@@ -106,6 +91,7 @@ def mid_type_analysis(self, context):
   # copy scope_identifier from the DeclaratorIdentifier to the
   # FunctionDefinition, we don't need the declarator anymore
   self.scope_identifier = scope_identifier
+  declarator_identifier.scope_identifier = None # TEMPORARY
 @t_def.method(t_def.InitDeclarator)
 def mid_type_analysis(self, context):
   # we use the base type and storage class from the context
@@ -126,27 +112,23 @@ def mid_type_analysis(self, context):
   else:
     assert scope_identifier.type == _type
 
+  # see if inside a function, for automatic auto storage class
+  _storage_class = context.storage_class
+  if (
+    context.scope.enclosing_scope is not None and
+    _storage_class == t_def.STORAGE_CLASS_NONE
+  ):
+    _storage_class = t_def.STORAGE_CLASS_AUTO
+
   if scope_identifier.storage_class == t_def.STORAGE_CLASS_NONE:
-    scope_identifier.storage_class = context.storage_class
-  elif context.storage_class != t_def.STORAGE_CLASS_NONE:
-    assert scope_identifier.storage_class == context.storage_class
+    scope_identifier.storage_class = _storage_class
+  elif _storage_class != t_def.STORAGE_CLASS_NONE:
+    assert scope_identifier.storage_class == _storage_class
 
   # copy scope_identifier from the DeclaratorIdentifier to the
   # InitDeclarator, we don't need the declarator anymore
   self.scope_identifier = scope_identifier
-
-  # see whether this InitDeclarator can have an initializer
-  if (
-    isinstance(scope_identifier.type, t_def.TypeFunction) or
-    scope_identifier.storage_class == t_def.STORAGE_CLASS_EXTERN or
-    scope_identifier.storage_class == t_def.STORAGE_CLASS_TYPEDEF
-  ):
-    assert len(self.children) < 2 # can't have initializer
-  elif (
-    not isinstance(scope_identifier.type, t_def.TypeArray) or
-    len(self.children) < 2
-  ):
-    assert scope_identifier.type.size >= 0 # must be of determinate size
+  declarator_identifier.scope_identifier = None # TEMPORARY
 
   # push entry on initializer stack to use while visiting initializer,
   # popped by the later call to InitDeclarator.type_analysis()
@@ -161,6 +143,7 @@ def mid_type_analysis(self, context):
 @t_def.method(t_def.DesignatorInitializer)
 def mid_type_analysis(self, context):
   _type, index, max_index = context.initializer_stack[-1]
+  self.type = _type # the starting point for applying the indices
   if len(self.children[0].children):
     # with designator, the designator says which element to fill
     # note: this resets index position, but only for the first designator
@@ -172,7 +155,7 @@ def mid_type_analysis(self, context):
 
         # get numeric index from designator
         expression = designator.children[0]
-        assert expression.type == base_type.type_ssize_t
+        assert expression.type == t_def.type_ssize_t
         assert isinstance(expression.value, t_def.ValueInt)
         i = expression.value.value
 
@@ -258,6 +241,11 @@ def type_analysis(self, context):
         )
         size += member_type.size
         align = max(align, member_type.align)
+
+    # make the size a multiple of the alignment
+    align_m1 = align - 1
+    size = (size + align_m1) & ~align_m1
+
     _type.size = size
     _type.align = align
     _type.members = members
@@ -266,6 +254,7 @@ def type_analysis(self, context):
   # copy scope_tag from the TagIdentifier to the
   # StructSpecifier, we don't need the identifier anymore
   self.scope_tag = scope_tag
+  self.children[0].scope_tag = None # TEMPORARY
 @t_def.method(t_def.UnionSpecifier)
 def type_analysis(self, context):
   # create a TypeUnion placeholder with no members initially
@@ -304,6 +293,11 @@ def type_analysis(self, context):
         )
         size = max(size, member_type.size)
         align = max(align, member_type.align)
+
+    # make the size a multiple of the alignment
+    align_m1 = align - 1
+    size = (size + align_m1) & ~align_m1
+
     _type.size = size
     _type.align = align
     _type.members = members
@@ -312,6 +306,7 @@ def type_analysis(self, context):
   # copy scope_tag from the TagIdentifier to the
   # UnionSpecifier, we don't need the identifier anymore
   self.scope_tag = scope_tag
+  self.children[0].scope_tag = None # TEMPORARY
 @t_def.method(t_def.EnumSpecifier)
 def type_analysis(self, context):
   # create a TypeEnum placeholder with no members initially
@@ -336,11 +331,11 @@ def type_analysis(self, context):
       member_name = identifier.text[0]
       assert member_name not in members
 
-      #if len(enumerator.children) >= 2:
-      #  expression = enumerator.children[1]
-      #  assert expression.type == base_type.type_signed_int
-      #  assert isinstance(expression.value, t_def.ValueInt)
-      #  value = expression.value.value
+      if len(enumerator.children) >= 2:
+        expression = enumerator.children[1]
+        assert expression.type == t_def.type_signed_int
+        assert isinstance(expression.value, t_def.ValueInt)
+        value = expression.value.value
 
       members[member_name] = t_def.TypeEnum.Member(
         name = member_name,
@@ -351,6 +346,7 @@ def type_analysis(self, context):
       identifier.scope_identifier.storage_class = (
         t_def.STORAGE_CLASS_ENUM_MEMBER
       )
+      identifier.scope_identifier = None # TEMPORARY
 
       value += 1
     _type.members = members
@@ -358,6 +354,7 @@ def type_analysis(self, context):
   # copy scope_tag from the TagIdentifier to the
   # EnumSpecifier, we don't need the identifier anymore
   self.scope_tag = scope_tag
+  self.children[0].scope_tag = None # TEMPORARY
 @t_def.method(t_def.InitDeclarator)
 def type_analysis(self, context):
   # pop entry from initializer stack used while visiting initializer,
@@ -365,6 +362,7 @@ def type_analysis(self, context):
   _, _, max_index = context.initializer_stack.pop()
   assert len(context.initializer_stack) == 0
 
+  # see if it is being defined here
   _type = self.scope_identifier.type
   _storage_class = self.scope_identifier.storage_class
   if (
@@ -372,19 +370,32 @@ def type_analysis(self, context):
     _storage_class == t_def.STORAGE_CLASS_EXTERN or
     _storage_class == t_def.STORAGE_CLASS_TYPEDEF
   ):
-    assert len(self.children) < 2 # can't have initializer
-  elif (
-    isinstance(_type, t_def.TypeArray) and
-    _type.element_count == -1 and
-    len(self.children) >= 2
-  ):
-    # size of indeterminate sized array can be deduced from initializer
-    element_size = _type.element_type.size
-    assert element_size >= 0 # must be of determinate size
-    _type.size = max_index * element_size
-    _type.element_count = max_index
+    # no, can't have initializer
+    assert len(self.children) < 2
   else:
+    # yes, can have initializer, allocate space
+    if (
+      isinstance(_type, t_def.TypeArray) and
+      _type.element_count == -1 and
+      len(self.children) >= 2
+    ):
+      # size of indeterminate sized array can be deduced from initializer
+      element_size = _type.element_type.size
+      assert element_size >= 0 # must be of determinate size
+      _type.size = max_index * element_size
+      _type.element_count = max_index
+
     assert _type.size >= 0 # must be of determinate size
+    align_m1 = _type.align - 1
+    context.scope.size = (context.scope.size + align_m1) & ~align_m1
+    self.scope_identifier.offset = context.scope.size
+    context.scope.size += _type.size
+@t_def.method(t_def.TypeName)
+def type_analysis(self, context):
+  name, self.type = self.children[1].get_name_and_type(
+    self.children[0].get_base_type()
+  )
+  assert len(name) == 0
 @t_def.method(t_def.Expression)
 def type_analysis(self, context):
   self.calc_type()
@@ -430,7 +441,7 @@ def type_analysis(self, context):
 
     # process typed parameters
     for i in range(n_formal_parameters):
-      actual_parameters.children[i] = add_cast(
+      actual_parameters.children[i] = t_def.add_cast(
         function_type.formal_parameters[i],
         actual_parameters.children[i]
       )
@@ -443,12 +454,12 @@ def type_analysis(self, context):
   for i in range(n_formal_parameters, len(actual_parameters.children)):
     rank = actual_parameters.children[i].type.rank
     if rank >= 0 and rank < t_def.INT_RANK:
-      actual_parameters.children[i] = add_cast(
-        base_type.type_signed_int,
+      actual_parameters.children[i] = t_def.add_cast(
+        t_def.type_signed_int,
         actual_parameters.children[i]
       )
     elif rank >= t_def.FLOAT_RANK and rank < t_def.DOUBLE_RANK:
-      actual_parameters.children[i] = add_cast(
+      actual_parameters.children[i] = t_def.add_cast(
         rank_to_type[rank + t_def.DOUBLE_RANK - t_def.FLOAT_RANK],
         actual_parameters.children[i]
       )
@@ -464,7 +475,7 @@ def type_analysis(self, context):
   self.type = context.initializer_stack[-1][0]
 @t_def.method(t_def.InitializerExpression)
 def type_analysis(self, context):
-  self.children[0] = add_cast(
+  self.children[0] = t_def.add_cast(
     context.initializer_stack[-1][0],
     self.children[0]
   )
@@ -475,86 +486,86 @@ def type_analysis(self, context):
     not isinstance(self.children[2], t_def.ExpressionEmpty) and
     not isinstance(self.children[2], t_def.ExpressionAsterisk)
   ):
-    self.children[2] = add_cast(
-      base_type.type_size_t,
+    self.children[2] = t_def.add_cast(
+      t_def.type_size_t,
       self.children[2]
     )
 @t_def.method(t_def.Enumerator)
 def type_analysis(self, context):
   if len(self.children) >= 2:
-    self.children[1] = add_cast(
-      base_type.type_signed_int,
+    self.children[1] = t_def.add_cast(
+      t_def.type_signed_int,
       self.children[1]
     )
 @t_def.method(t_def.StructDeclarator)
 def type_analysis(self, context):
-  self.children[1] = add_cast(
-    base_type.type_signed_int,
+  self.children[1] = t_def.add_cast(
+    t_def.type_signed_int,
     self.children[1],
   )
 @t_def.method(t_def.AlignAsExpression)
 def type_analysis(self, context):
-  self.children[0] = add_cast(
-    base_type.type_size_t,
+  self.children[0] = t_def.add_cast(
+    t_def.type_size_t,
     self.children[0],
   )
 @t_def.method(t_def.DesignatorIndex)
 def type_analysis(self, context):
-  self.children[0] = add_cast(
-    base_type.type_ssize_t,
+  self.children[0] = t_def.add_cast(
+    t_def.type_ssize_t,
     self.children[0],
   )
 @t_def.method(t_def.StaticAssertDeclaration)
 def type_analysis(self, context):
-  self.children[0] = add_cast(
-    base_type.type_bool,
+  self.children[0] = t_def.add_cast(
+    t_def.type_bool,
     self.children[0],
   )
 @t_def.method(t_def.StatementCase)
 def type_analysis(self, context):
-  self.children[0] = add_cast(
+  self.children[0] = t_def.add_cast(
     context.case_type,
     self.children[0],
   )
 @t_def.method(t_def.StatementExpression)
 def type_analysis(self, context):
-  self.children[0] = add_cast(
-    base_type.type_void,
+  self.children[0] = t_def.add_cast(
+    t_def.type_void,
     self.children[0],
   )
 @t_def.method(t_def.StatementIf)
 def type_analysis(self, context):
-  self.children[0] = add_cast(
-    base_type.type_bool,
+  self.children[0] = t_def.add_cast(
+    t_def.type_bool,
     self.children[0],
   )
 @t_def.method(t_def.StatementWhile)
 def type_analysis(self, context):
-  self.children[0] = add_cast(
-    base_type.type_bool,
+  self.children[0] = t_def.add_cast(
+    t_def.type_bool,
     self.children[0],
   )
 @t_def.method(t_def.StatementDoWhile)
 def type_analysis(self, context):
-  self.children[1] = add_cast(
-    base_type.type_bool,
+  self.children[1] = t_def.add_cast(
+    t_def.type_bool,
     self.children[1],
   )
 @t_def.method(t_def.StatementFor)
 def type_analysis(self, context):
   if not isinstance(self.children[1], t_def.ExpressionEmpty):
-    self.children[1] = add_cast(
-      base_type.type_bool,
+    self.children[1] = t_def.add_cast(
+      t_def.type_bool,
       self.children[1],
     )
   if not isinstance(self.children[2], t_def.ExpressionEmpty):
-    self.children[2] = add_cast(
-      base_type.type_void,
+    self.children[2] = t_def.add_cast(
+      t_def.type_void,
       self.children[2],
     )
 @t_def.method(t_def.StatementReturn)
 def type_analysis(self, context):
-  self.children[0] = add_cast(
+  self.children[0] = t_def.add_cast(
     context.return_type,
     self.children[0],
   )