Make product config handles into structs

This is clearer and allows us to more easily
add new fields to the struct. One usecase for
more fields is the artifact path requirements.

Bug: 221312707
Test: Verified starlark product config still works for aosp_arm64
Change-Id: I4c4307e916f3b3fc8ca303b10eac3c7c73b76ac6
diff --git a/core/product_config.rbc b/core/product_config.rbc
index 2820695..77cd604 100644
--- a/core/product_config.rbc
+++ b/core/product_config.rbc
@@ -165,10 +165,10 @@
         pcm(globals, handle)
 
         # Now we know everything about this PCM, record it in 'configs'.
-        children = __h_inherited_modules(handle)
+        children = handle.inherited_modules
         if _options.trace_modules:
             print("#   ", "    ".join(children.keys()))
-        configs[name] = (pcm, __h_cfg(handle), children.keys(), False)
+        configs[name] = (pcm, handle.cfg, children.keys(), False)
         pcm_count = pcm_count + 1
 
         if len(children) == 0:
@@ -235,7 +235,7 @@
     input_variables_init(globals_base, h_base)
     input_variables_init(globals, h)
     board_config_init(globals, h)
-    return (globals, _dictionary_difference(h[0], h_base[0]), globals_base)
+    return (globals, _dictionary_difference(h.cfg, h_base.cfg), globals_base)
 
 
 def _substitute_inherited(configs, pcm_name, cfg):
@@ -392,11 +392,11 @@
 #   default value list (initially empty, modified by inheriting)
 def __h_new():
     """Constructs a handle which is passed to PCM."""
-    return (dict(), dict(), list())
-
-def __h_inherited_modules(handle):
-    """Returns PCM's inherited modules dict."""
-    return handle[1]
+    return struct(
+        cfg = dict(),
+        inherited_modules = dict(),
+        default_list_value = list()
+    )
 
 def __h_cfg(handle):
     """Returns PCM's product configuration attributes dict.
@@ -404,7 +404,7 @@
     This function is also exported as rblf.cfg, and every PCM
     calls it at the beginning.
     """
-    return handle[0]
+    return handle.cfg
 
 def _setdefault(handle, attr):
     """If attribute has not been set, assigns default value to it.
@@ -413,9 +413,9 @@
     Only list attributes are initialized this way. The default
     value is kept in the PCM's handle. Calling inherit() updates it.
     """
-    cfg = handle[0]
+    cfg = handle.cfg
     if cfg.get(attr) == None:
-        cfg[attr] = list(handle[2])
+        cfg[attr] = list(handle.default_list_value)
     return cfg[attr]
 
 def _inherit(handle, pcm_name, pcm):
@@ -424,12 +424,11 @@
     This function is exported as rblf.inherit, PCM calls it when
     a module is inherited.
     """
-    cfg, inherited, default_lv = handle
-    inherited[pcm_name] = pcm
-    default_lv.append(_indirect(pcm_name))
+    handle.inherited_modules[pcm_name] = pcm
+    handle.default_list_value.append(_indirect(pcm_name))
 
     # Add inherited module reference to all configuration values
-    for attr, val in cfg.items():
+    for attr, val in handle.cfg.items():
         if type(val) == "list":
             val.append(_indirect(pcm_name))