tp: rework handling of implicit and parent columns

Mutability of Table leads to very subtle bugs which are hard to track
down. Instead, have wrappers for Table and Column which are themselves
immutable and handle implicit and parent columns there.

Change-Id: I8363974af63acece9734e422e8364d1b3ce23f82
diff --git a/python/generators/trace_processor_table/serialize.py b/python/generators/trace_processor_table/serialize.py
index 0401703..589544a 100644
--- a/python/generators/trace_processor_table/serialize.py
+++ b/python/generators/trace_processor_table/serialize.py
@@ -16,24 +16,27 @@
 from typing import Optional
 
 from python.generators.trace_processor_table.public import Alias
-from python.generators.trace_processor_table.public import Column
 from python.generators.trace_processor_table.public import ColumnFlag
-from python.generators.trace_processor_table.public import Table
-from python.generators.trace_processor_table.util import parse_type
-from python.generators.trace_processor_table.util import typed_column_type
+from python.generators.trace_processor_table.util import ParsedTable
+from python.generators.trace_processor_table.util import ParsedColumn
 from python.generators.trace_processor_table.util import to_cpp_flags
 
 
 class ColumnSerializer:
   """Functions for serializing a single Column in a table into C++."""
 
-  def __init__(self, table: Table, col_index: int):
+  def __init__(self, table: ParsedTable, column: ParsedColumn, col_index: int):
     self.col_index = col_index
-    self.col = table.columns[col_index]
+    self.parsed_col = column
+    self.col = self.parsed_col.column
     self.name = self.col.name
     self.flags = self.col.flags
-    self.typed_column_type = typed_column_type(table, self.col)
-    self.cpp_type = parse_type(table, self.col.type).cpp_type_with_optionality()
+    self.typed_column_type = table.typed_column_type(self.parsed_col)
+    self.cpp_type = table.parse_type(self.col.type).cpp_type_with_optionality()
+
+    self.is_implicit_id = self.parsed_col.is_implicit_id
+    self.is_implicit_type = self.parsed_col.is_implicit_type
+    self.is_ancestor = self.parsed_col.is_ancestor
 
   def colindex(self) -> str:
     return f'    static constexpr uint32_t {self.name} = {self.col_index};'
@@ -42,28 +45,28 @@
     return f'    using {self.name} = {self.typed_column_type};'
 
   def row_field(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
-    if not self.col._is_self_column:
+    if self.is_ancestor:
       return None
     return f'    {self.cpp_type} {self.name};'
 
   def row_param(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
     return f'{self.cpp_type} in_{self.name} = {{}}'
 
   def parent_row_initializer(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
-    if self.col._is_self_column:
+    if not self.is_ancestor:
       return None
     return f'std::move(in_{self.name})'
 
   def row_initializer(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
-    if not self.col._is_self_column:
+    if self.is_ancestor:
       return None
     return f'{self.name}(std::move(in_{self.name}))'
 
@@ -73,7 +76,7 @@
     }}'''
 
   def row_ref_getter(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
     return f'''void set_{self.name}(
         ColumnType::{self.name}::non_optional_type v) {{
@@ -81,9 +84,9 @@
     }}'''
 
   def flag(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
-    if not self.col._is_self_column:
+    if self.is_ancestor:
       return None
     default = f'ColumnType::{self.name}::default_flags()'
     if self.flags == ColumnFlag.NONE:
@@ -95,9 +98,9 @@
     '''
 
   def storage_init(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
-    if not self.col._is_self_column:
+    if self.is_ancestor:
       return None
 
     storage = f'ColumnStorage<ColumnType::{self.name}::stored_type>'
@@ -105,9 +108,9 @@
     return f'''{self.name}_({storage}::Create<false>())'''
 
   def column_init(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
-    if not self.col._is_self_column:
+    if self.is_ancestor:
       return None
     return f'''
     columns_.emplace_back("{self.name}", &{self.name}_, ColumnFlag::{self.name},
@@ -116,16 +119,16 @@
     '''
 
   def shrink_to_fit(self) -> Optional[str]:
-    if self.col._is_auto_added_id:
+    if self.is_implicit_id:
       return None
-    if not self.col._is_self_column:
+    if self.is_ancestor:
       return None
     return f'    {self.name}_.ShrinkToFit();'
 
   def append(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
-    if not self.col._is_self_column:
+    if self.is_ancestor:
       return None
     return f'    mutable_{self.name}()->Append(std::move(row.{self.name}));'
 
@@ -138,7 +141,7 @@
   '''
 
   def mutable_accessor(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
     return f'''
   {self.typed_column_type}* mutable_{self.name}() {{
@@ -148,9 +151,9 @@
   '''
 
   def storage(self) -> Optional[str]:
-    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+    if self.is_implicit_id or self.is_implicit_type:
       return None
-    if not self.col._is_self_column:
+    if self.is_ancestor:
       return None
     name = self.name
     return f'  ColumnStorage<ColumnType::{name}::stored_type> {name}_;'
@@ -159,19 +162,23 @@
 class TableSerializer(object):
   """Functions for seralizing a single Table into C++."""
 
-  def __init__(self, table: Table):
-    self.table = table
-    self.table_name = table.class_name
+  def __init__(self, parsed: ParsedTable):
+    self.table = parsed.table
+    self.table_name = parsed.table.class_name
     self.column_serializers = []
 
-    if table.parent:
-      self.parent_class_name = table.parent.class_name
+    if parsed.table.parent:
+      self.parent_class_name = parsed.table.parent.class_name
     else:
       self.parent_class_name = 'macros_internal::RootParentTable'
 
-    self.column_serializers = [
-        ColumnSerializer(table, i) for i in range(len(table.columns))
-    ]
+    self.column_serializers = []
+    for c in parsed.columns:
+      # Aliases should be ignored as they are handled in SQL currently.
+      if isinstance(c.column.type, Alias):
+        continue
+      self.column_serializers.append(
+          ColumnSerializer(parsed, c, len(self.column_serializers)))
 
   def foreach_col(self, serialize_fn, delimiter='\n') -> str:
     lines = []
@@ -363,7 +370,7 @@
   '''.strip('\n')
 
 
-def serialize_header(ifdef_guard: str, tables: List[Table],
+def serialize_header(ifdef_guard: str, tables: List[ParsedTable],
                      include_paths: List[str]) -> str:
   """Serializes a table header file containing the given set of tables."""
   include_paths_str = '\n'.join([f'#include "{i}"' for i in include_paths])