Commits

rkruppe committed a1a3370

Refactor templates for component code generation

Comments (0)

Files changed (1)

 import ttgx.rawbuf
 
 #TODO
-# * merge this module with rawbuf
-# * add vector types, like 3 x I32 (preferably in a general manner)
-#   * make sure those are only accessed like ``pos[e, 1] = new_y``
-#     (to prevent lifetime issues)
-# * perhaps add an escape hatch for arbitrary Python types?
+# * merge this module with rawbuf?
+# * add an escape hatch for arbitrary Python types?
 
 log = logging.getLogger(__name__)
 _jinja_env = jinja2.Environment(
     undefined=jinja2.StrictUndefined,  # error on undefined variables
+    line_statement_prefix='$'
 )
 _jinja_env.filters['repr'] = repr
 _component_template = _jinja_env.from_string('''
 import ttgx.dodecs
 import ttgx.rawbuf
 
-{# Is actually completely independent and could live in dodecs.
-    Including it here only to permit better error messages. #}
-class _{{clsname}}AttributeView:
-    def __init__(self, comp, indices, values):
-        self._comp = comp
-        self._indices = indices
-        self._values = values
-
-    def __setitem__(self, e, val):
-        self._comp.universe.check_entity(e)
-        self._values[self._indices[e]] = val
-
-    def __getitem__(self, e):
-        self._comp.universe.check_entity(e)
-        return self._values[self._indices[e]]
-
-
 class {{clsname}}:
     identifier = {{identifier|repr}}
 
     def __init__(self):
         self.__indices = {}
         self.__entities = []
-{%- for name, t in attrs.items() %}
+$ for name, t in attrs.items():
         self._{{name}} = ttgx.rawbuf.array({{t|repr}})
-        self.{{name}} = _{{clsname}}AttributeView(
+        self.{{name}} = ttgx.dodecs._AttributeView(
             self, self.__indices, self._{{name}})
-{%- endfor %}
-
+$ endfor
+{# #}
     def insert(self, e, *, {{ attrs|join(', ') }}):
         self.universe.check_entity(e)
         if e in self.__indices:
             raise ValueError('Already have record for ' + repr(e))
-    {%- for name in attrs %}
+$ for name in attrs:
         self._{{name}}.append({{name}})
-    {%- endfor %}
+$ endfor
         self.__indices[e] = len(self.__indices)
         self.__entities.append(e)
-    {% for name in attrs %}
+$ for name in attrs:
         assert len(self._{{name}}) == len(self.__indices)
-    {%- endfor %}
-
+$ endfor
+{# #}
     def delete(self, e):
         self.universe.check_entity(e)
         i = self.__indices.pop(e)
         assert e is self.__entities[i]
-    {%- for name in attrs %}
+$ for name in attrs:
         self._{{name}}.pop_by_swap(i)
         assert len(self._{{name}}) == len(self.__indices)
-    {%- endfor %}
+$ endfor
         if i != len(self.__entities) - 1:
             self.__entities[i] = self.__entities.pop()
             self.__indices[self.__entities[i]] = i
 
 
 _scalar_component_template = _jinja_env.from_string('''
-import ttgx.dodecs
-
 class {{clsname}}:
     identifier = {{identifier|repr}}
 
     def __init__(self, *, {{ attrs|join(', ') }}):
-    {%- for name in attrs %}
-        self._{{name}} = {{name}}
-    {%- endfor %}
-{% for name in attrs %}
-    @property
-    def {{name}}(self):
-        return self._{{name}}
-    @{{name}}.setter
-    def {{name}}(self, value):
-        self._{{name}} = value
-{% endfor %}
-
-    def __error(self, *args, **kwds):
-        raise TypeError("A scalar component only holds ONE record")
-
-    insert = delete = __error
+$ for name in attrs
+        self.{{name}} = {{name}}
+$ endfor
+{# #}
+$ for method in ['insert', 'delete']:
+    def {{method}}(self, *args, **kwds):
+        raise TypeError("Scalar components hold exactly one record")
+$ endfor
 ''')
 
 
     src = _scalar_component_template.render(
         clsname=clsname, identifier=identifier, attrs=attrs
     )
+    print(src)
     code = compile(src, '<dodecs scalar component>', 'exec')
     namespace = {}
     exec(code, namespace, namespace)
     return addr
 
 
+class _AttributeView:
+    def __init__(self, comp, indices, values):
+        self._comp = comp
+        self._indices = indices
+        self._values = values
+
+    def __setitem__(self, e, val):
+        self._comp.universe.check_entity(e)
+        self._values[self._indices[e]] = val
+
+    def __getitem__(self, e):
+        self._comp.universe.check_entity(e)
+        return self._values[self._indices[e]]
+
+
 class InvalidEntityError(BaseException):
     pass