Make serialization nested with proper virtual functions to handle compound type
authorNick Downing <nick@ndcode.org>
Sun, 27 Jan 2019 11:31:13 +0000 (22:31 +1100)
committerNick Downing <nick@ndcode.org>
Sun, 27 Jan 2019 11:31:13 +0000 (22:31 +1100)
ast.py
generate_py.py

diff --git a/ast.py b/ast.py
index 839db34..5ba683c 100644 (file)
--- a/ast.py
+++ b/ast.py
@@ -19,14 +19,21 @@ default_value_str = {
   'bool': 'false',
   'int': '-1',
   'ref': '-1',
-  'str': ''
+  'str': '',
+  'list(bool)': '',
+  'list(int)': '',
+  'list(ref)': '',
+  'list(str)': '',
+  'set(bool)': '',
+  'set(int)': '',
+  'set(ref)': '',
+  'set(str)': ''
 }
 
 class Context:
   def __init__(
     self,
     fout = sys.stdout,
-    package_name = 't_ast.',
     indent = '',
     stack = [],
     classes = [],
@@ -35,7 +42,6 @@ class Context:
     field_name = ''
   ):
     self.fout = fout
-    self.package_name = package_name
     self.indent = indent
     self.stack = stack
     self.classes = classes
@@ -128,46 +134,15 @@ class AST(element.Element):
       self.repr_serialize(params)
       return 'ast.AST.Type({0:s})'.format(', '.join(params))
     # GENERATE END
-    def generate_serialize(self, context):
-      type = element.to_text(self)
-      context.fout.write(
-        '''{0:s}  self.set('{1:s}', element.serialize_{2:s}(self.{3:s}))
-'''.format(
-          context.indent,
-          context.field_name,
-          type,
-          context.field_name
-        )
+    def generate_serialize(self, context, expr):
+      return 'element.serialize_{0:s}({1:s})'.format(
+        element.to_text(self),
+        expr
       )
-    def generate_deserialize(self, context): 
-      type = element.to_text(self)
-      context.fout.write(
-        '''{0:s}  self.{1:s} = element.deserialize_{2:s}(self.get('{3:s}', '{4:s}'))
-'''.format(
-          context.indent,
-          context.field_name,
-          type,
-          context.field_name,
-          default_value_str[type]
-        )
-      )
-    def generate_repr_serialize(self, context):
-      type = element.to_text(self)
-      context.fout.write(
-        '''{0:s}  if self.{1:s} != {2:s}:
-{3:s}    params.append(
-{4:s}      '{5:s} = {{0:s}}'.format(repr(self.{6:s}))
-{7:s}    )
-'''.format(
-          context.indent,
-          context.field_name,
-          default_value[type],
-          context.indent,
-          context.indent,
-          context.field_name,
-          context.field_name,
-          context.indent
-        )
+    def generate_deserialize(self, context, expr): 
+      return 'element.deserialize_{0:s}({1:s})'.format(
+        element.to_text(self),
+        expr
       )
 
   # syntax classes:
@@ -668,63 +643,40 @@ class AST(element.Element):
       self.repr_serialize(params)
       return 'ast.AST.TypeList({0:s})'.format(', '.join(params))
     # GENERATE END
-    def generate_serialize(self, context):
-      subtype = element.to_text(self[0])
-      context.fout.write(
-        '''{0:s}  self.set(
-{1:s}    '{2:s}',
-{3:s}    ' '.join([element.serialize_{4:s}(i{5:s}) for i in self.{6:s}])
-{7:s}  )
-'''.format(
-          context.indent,
-          context.indent,
-          context.field_name,
-          context.indent,
-          subtype,
-          ', ref_list' if subtype == 'ref' else '',
-          context.field_name,
-          context.indent
-        )
-      )
-    def generate_deserialize(self, context): 
-      subtype = element.to_text(self[0])
-      context.fout.write(
-        '''{0:s}  self.{1:s} = [
-{2:s}    element.deserialize_{3:s}(i{4:s})
-{5:s}    for i in self.get('{6:s}', '').split()
-{7:s}  ]
-'''.format(
-          context.indent,
-          context.field_name,
-          context.indent,
-          subtype,
-          ', ref_list' if subtype == 'ref' else '',
-          context.indent,
-          context.field_name,
-          context.indent
-        )
+    def generate_serialize(self, context, expr):
+      indent_save = context.indent
+      context.indent += '    '
+      result = '''' '.join(
+{0:s}  [
+{1:s}    {2:s}
+{3:s}    for i in {4:s}
+{5:s}  ]
+{6:s})'''.format(
+        indent_save,
+        indent_save,
+        self[0].generate_serialize(context, 'i'),
+        indent_save,
+        expr,
+        indent_save,
+        indent_save
       )
-    def generate_repr_serialize(self, context):
-      subtype = element.to_text(self[0])
-      context.fout.write(
-        '''{0:s}  if len(self.{1:s}):
-{2:s}    params.append(
-{3:s}      '{4:s} = [{{0:s}}]'.format(
-{5:s}        ', '.join([repr(i) for i in self.{6:s}])
-{7:s}      )
-{8:s}    )
-'''.format(
-          context.indent,
-          context.field_name,
-          context.indent,
-          context.indent,
-          context.field_name,
-          context.indent,
-          context.field_name,
-          context.indent,
-          context.indent
-        )
+      context.indent = indent_save
+      return result
+    def generate_deserialize(self, context, expr):
+      indent_save = context.indent
+      context.indent += '  '
+      result = '''[
+{0:s}  {1:s}
+{2:s}  for i in {3:s}.split()
+{4:s}]'''.format(
+        indent_save,
+        self[0].generate_deserialize(context, 'i'),
+        indent_save,
+        expr,
+        indent_save
       )
+      context.indent = indent_save
+      return result
   class TypeRef(Type):
     # GENERATE ELEMENT() BEGIN
     def __init__(
@@ -752,24 +704,10 @@ class AST(element.Element):
       self.repr_serialize(params)
       return 'ast.AST.TypeRef({0:s})'.format(', '.join(params))
     # GENERATE END
-    def generate_serialize(self, context):
-      context.fout.write(
-        '''{0:s}  self.set('{1:s}', element.serialize_ref(self.{2:s}, ref_list))
-'''.format(
-          context.indent,
-          context.field_name,
-          context.field_name
-        )
-      )
-    def generate_deserialize(self, context): 
-      context.fout.write(
-        '''{0:s}  self.{1:s} = element.deserialize_ref(self.get('{2:s}', '-1'), ref_list)
-'''.format(
-          context.indent,
-          context.field_name,
-          context.field_name
-        )
-      )
+    def generate_serialize(self, context, expr):
+      return 'element.serialize_ref({0:s}, ref_list)'.format(expr)
+    def generate_deserialize(self, context, expr): 
+      return 'element.deserialize_ref({0:s}, ref_list)'.format(expr)
   class TypeSet(Type):
     # GENERATE ELEMENT() BEGIN
     def __init__(
@@ -797,67 +735,44 @@ class AST(element.Element):
       self.repr_serialize(params)
       return 'ast.AST.TypeSet({0:s})'.format(', '.join(params))
     # GENERATE END
-    def generate_serialize(self, context):
-      subtype = element.to_text(self[0])
-      context.fout.write(
-        '''{0:s}  self.set(
-{1:s}    '{2:s}',
-{3:s}    ' '.join([element.serialize_{4:s}(i{5:s}) for i in sorted(self.{6:s})])
-{7:s}  )
-'''.format(
-          context.indent,
-          context.indent,
-          context.field_name,
-          context.indent,
-          subtype,
-          ', ref_list' if subtype == 'ref' else '',
-          context.field_name,
-          context.indent
-        )
+    def generate_serialize(self, context, expr):
+      indent_save = context.indent
+      context.indent += '    '
+      result = '''' '.join(
+{0:s}  [
+{1:s}    {2:s}
+{3:s}    for i in sorted({4:s})
+{5:s}  ]
+{6:s})'''.format(
+        indent_save,
+        indent_save,
+        self[0].generate_serialize(context, 'i'),
+        indent_save,
+        expr,
+        indent_save,
+        indent_save
       )
-    def generate_deserialize(self, context): 
-      subtype = element.to_text(self[0])
-      context.fout.write(
-        '''{0:s}  self.{1:s} = set(
-{2:s}    [
-{3:s}      element.deserialize_{4:s}(i{5:s})
-{6:s}      for i in self.get('{7:s}', '').split()
-{8:s}    ]
-{9:s}  )
-'''.format(
-          context.indent,
-          context.field_name,
-          context.indent,
-          context.indent,
-          subtype,
-          ', ref_list' if subtype == 'ref' else '',
-          context.indent,
-          context.field_name,
-          context.indent,
-          context.indent
-        )
-      )
-    def generate_repr_serialize(self, context):
-      subtype = element.to_text(self[0])
-      context.fout.write(
-        '''{0:s}  if len(self.{1:s}):
-{2:s}    params.append(
-{3:s}      '{4:s} = set([{{0:s}}])'.format(
-{5:s}        ', '.join([repr(i) for i in sorted(self.{6:s})])
-{7:s}      )
-{8:s}    )
-'''.format(
-          context.indent,
-          context.field_name,
-          context.indent,
-          context.indent,
-          context.field_name,
-          context.indent,
-          context.field_name,
-          context.indent,
-          context.indent
-        )
+      context.indent = indent_save
+      return result
+    def generate_deserialize(self, context, expr):
+      indent_save = context.indent
+      context.indent += '    '
+      result = '''set(
+{0:s}  [
+{1:s}    {2:s}
+{3:s}    for i in {4:s}.split()
+{5:s}  ]
+{6:s})'''.format(
+        indent_save,
+        indent_save,
+        self[0].generate_deserialize(context, 'i'),
+        indent_save,
+        expr,
+        indent_save,
+        indent_save
       )
+      context.indent = indent_save
+      return result
   class TypeStr(Type):
     # GENERATE ELEMENT() BEGIN
     def __init__(
@@ -1066,19 +981,62 @@ class AST(element.Element):
           context.fout.write(
             '''{0:s}def serialize(self, ref_list):
 {1:s}  {2:s}.serialize(self, ref_list)
-'''.format(context.indent, context.indent, full_base_class)
+'''.format(
+              context.indent,
+              context.indent,
+              full_base_class
+            )
           )
+          indent_save2 = context.indent
+          context.indent += '    '
           for i in context.fields[n_base_fields:]:
             context.field_name = i[1].get_text()
-            i[0].generate_serialize(context)
+            context.fout.write(
+              '''{0:s}  self.set(
+{1:s}    '{2:s}',
+{3:s}    {4:s}
+{5:s}  )
+'''.format(
+                indent_save2,
+                indent_save2,
+                context.field_name,
+                indent_save2,
+                i[0].generate_serialize(
+                  context,
+                  'self.{0:s}'.format(context.field_name)
+                ),
+                indent_save2
+              )
+            )
+          context.indent = indent_save2
           context.fout.write(
             '''{0:s}def deserialize(self, ref_list):
 {1:s}  {2:s}.deserialize(self, ref_list)
-'''.format(context.indent, context.indent, full_base_class)
+'''.format(
+              context.indent,
+              context.indent,
+              full_base_class
+            )
           )
+          #indent_save2 = context.indent
+          context.indent += '  '
           for i in context.fields[n_base_fields:]:
             context.field_name = i[1].get_text()
-            i[0].generate_deserialize(context)
+            context.fout.write(
+              '''{0:s}  self.{1:s} = {2:s}
+'''.format(
+                indent_save2,
+                context.field_name,
+                i[0].generate_deserialize(
+                  context,
+                  'self.get(\'{0:s}\', \'{1:s}\')'.format(
+                    context.field_name,
+                    default_value_str[element.to_text(i[0])]
+                  )
+                )
+              )
+            )
+          context.indent = indent_save2
         context.fout.write(
           '''{0:s}def copy(self, factory = None):
 {1:s}  result = {2:s}.copy(
@@ -1107,33 +1065,6 @@ class AST(element.Element):
             context.indent
           )
         )
-        if len(context.fields) > n_base_fields:
-          context.fout.write(
-            '''{0:s}def repr_serialize(self, params):
-{1:s}  {2:s}.repr_serialize(self, params)
-'''.format(
-              context.indent,
-              context.indent,
-              full_base_class
-            )
-          )
-          for i in context.fields[n_base_fields:]:
-            context.field_name = i[1].get_text()
-            i[0].generate_repr_serialize(context)
-        context.fout.write(
-          '''{0:s}def __repr__(self):
-{1:s}  params = []
-{2:s}  self.repr_serialize(params)
-{3:s}  return '{4:s}{5:s}({{0:s}})'.format(', '.join(params))
-'''.format(
-            context.indent,
-            context.indent,
-            context.indent,
-            context.indent,
-            context.package_name,
-            '.'.join(context.stack),
-          )
-        )
 
         context.indent = indent_save
         del context.stack[-1]
index c8bfab1..6f37472 100644 (file)
@@ -54,10 +54,7 @@ def generate_py(_ast, home_dir, skel_file, out_file):
           )
         elif line == '# GENERATE SECTION2\n':
           fout.write('# GENERATE SECTION2 BEGIN\n')
-          #package_name = os.path.basename(out_file)
-          #if package_name[-3:] == '.py':
-          #  package_name = package_name[:-3]
-          context = ast.Context(fout, 'ast.') #, package_name + '.')
+          context = ast.Context(fout)
           for i in _ast[1]:
             assert isinstance(i, ast.AST.Section2.ClassDef)
             i.generate_class_or_field_def(context)