Implement storage classes
authorNick Downing <nick.downing@lifx.co>
Sun, 19 Jan 2020 06:49:23 +0000 (17:49 +1100)
committerNick Downing <nick.downing@lifx.co>
Sun, 19 Jan 2020 06:49:23 +0000 (17:49 +1100)
ansi_c.l
ansi_c.t

index e037240..c394660 100644 (file)
--- a/ansi_c.l
+++ b/ansi_c.l
@@ -80,7 +80,7 @@ WS  [ \t\v\n\f]
 "_Thread_local"                                return y_tab.THREAD_LOCAL
 "__func__"                             return y_tab.FUNC_NAME
 
-FILE|GRAM_STYPE|YYLTYPE|assoc|bool|boundary|code_props|code_props_type|location|muscle_kind|named_ref|param_type|scanflags_t|size_t|symbol|symbol_class|symbol_list|uniqstr|variant|warnings|u?int(8|16|32|64)_t {
+FILE|GRAM_STYPE|YYLTYPE|assoc|bool|boundary|code_props|code_props_type|location|muscle_kind|named_ref|param_type|scanflags_t|size_t|symbol|symbol_class|symbol_list|uniqstr|variant|warnings|u?int(8|16|32|64)_t|BaseType_t {
   # THIS IS A HACK FOR NOW
   return y_tab.TYPEDEF_NAME
 }
index f7d1811..2eae663 100644 (file)
--- a/ansi_c.t
+++ b/ansi_c.t
@@ -41,6 +41,7 @@ class AST {
     bool right_to_left = False;
   };
   class Specifier;
+  class SpecifierList;
   /* type analysis */
   class Type;
   class TypeVoid: Type;
@@ -77,6 +78,10 @@ class AST {
   };
   class TypeStruct: TypeStructOrUnion;
   class TypeUnion: TypeStructOrUnion;
+  /* storage class analysis */
+  class StorageClass;
+  class StorageClassExtern: StorageClass;
+  class StorageClassStatic: StorageClass;
   /* syntax classes */
   class AlignAsExpression;
   class AlignAsType;
@@ -84,7 +89,7 @@ class AST {
   class BlockItemList;
   class Declaration: DeclarationOrStatement;
   class DeclarationList;
-  class DeclarationSpecifierList;
+  class DeclarationSpecifierList: SpecifierList;
   class DeclaratorAbstract: Declarator;
   class DeclaratorArray: Declarator;
   class DeclaratorEmpty: Declarator;
@@ -177,7 +182,7 @@ class AST {
   class InitDeclaratorList;
   class ParameterDeclaration;
   class ParameterDeclarationList;
-  class SpecifierQualifierList;
+  class SpecifierQualifierList: SpecifierList;
   class StatementBlock: Statement;
   class StatementBreak: Statement;
   class StatementCase: Statement;
@@ -280,6 +285,12 @@ type_specifiers_to_type = {
   (0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1): AST.TypeFloat(complex = 2, bits = 64),
   (0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0): AST.TypeBool()
 }
+# typedef extern static thread_local auto register
+storage_class_specifiers_to_storage_class = {
+  (0, 0, 0, 0, 0): AST.StorageClass(),
+  (0, 1, 0, 0, 0): AST.StorageClassExtern(),
+  (0, 0, 1, 0, 0): AST.StorageClassStatic()
+}
 octal_prefix = set(
   ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09']
 )
@@ -333,20 +344,22 @@ def translate_declaration_or_statement(self, context):
         )
       )
     )
-  for i in self.children[1].children:
-    type, name = i.children[0].get_type_and_name(base_type)
-    if not isinstance(type, AST.TypeFunction):
-      context.lines.append(
-        '{0:s}{1:s} = {2:s}\n'.format(
-          context.indent,
-          name,
-          (
-            type.translate_zero(context)
-          if isinstance(i.children[1], AST.EqualsInitializerEmpty) else
-            i.children[1].translate_initializer_or_expression(context)
+  storage_class = self.children[0].get_storage_class()
+  if not isinstance(storage_class, AST.StorageClassExtern):
+    for i in self.children[1].children:
+      type, name = i.children[0].get_type_and_name(base_type)
+      if not isinstance(type, AST.TypeFunction):
+        context.lines.append(
+          '{0:s}{1:s} = {2:s}\n'.format(
+            context.indent,
+            name,
+            (
+              type.translate_zero(context)
+            if isinstance(i.children[1], AST.EqualsInitializerEmpty) else
+              i.children[1].translate_initializer_or_expression(context)
+            )
           )
         )
-      )
 @method(AST.FunctionDefinition)
 def translate_declaration_or_statement(self, context):
   type, name = self.children[1].get_type_and_name(self.children[0].get_type())
@@ -803,9 +816,11 @@ def translate_expression(self, context, precedence):
   text = self.text[0]
   if text[:2] in octal_prefix:
     text = '0o' + text[1:]
-  if text[-2:] == 'LL':
-    text = text[:-2]
-  elif text[-1:] == 'L':
+  if text[-1:] == 'L':
+    text = text[:-1]
+  if text[-1:] == 'L':
+    text = text[:-1]
+  if text[-1:] == 'U':
     text = text[:-1]
   return text
 @method(AST.ExpressionSizeOfType)
@@ -1038,24 +1053,28 @@ def specifier_get_type(self):
   )
 del specifier_get_type
 
-@method(AST.DeclarationSpecifierList)
+@method(AST.SpecifierList)
 def get_type(self):
   type_specifiers = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
   for i in self.children:
-    if not isinstance(i, AST.TypeSpecifier):
-      return i.specifier_get_type()
-    type_specifiers[i.n] += 1
-  return type_specifiers_to_type[tuple(type_specifiers)]
-@method(AST.SpecifierQualifierList)
-def get_type(self):
-  type_specifiers = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-  for i in self.children:
-    if not isinstance(i, AST.TypeSpecifier):
+    if isinstance(i, AST.TypeSpecifier):
+      type_specifiers[i.n] += 1
+    elif isinstance(i, AST.StorageClassSpecifier):
+      pass
+    else:
       return i.specifier_get_type()
-    type_specifiers[i.n] += 1
   return type_specifiers_to_type[tuple(type_specifiers)]
 del get_type
 
+@method(AST.SpecifierList)
+def get_storage_class(self):
+  storage_class_specifiers = [0, 0, 0, 0, 0]
+  for i in self.children:
+    if isinstance(i, AST.StorageClassSpecifier):
+      storage_class_specifiers[i.n] += 1
+  return storage_class_specifiers_to_storage_class[tuple(storage_class_specifiers)]
+del get_storage_class
+
 @method(AST.Identifier)
 def translate_identifier(self, context):
   text = self.text[0]