From dd07cdfb2c48466bf1c9f99336ba44a9a1c7dca9 Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Tue, 19 Jan 2016 17:45:50 +0100
Subject: [PATCH] Add support for initializer lists

---
 python/dune/perftool/cgen/clazz.py           | 24 ++++++++----
 python/dune/perftool/pdelab/localoperator.py | 39 +++++++++++++++-----
 2 files changed, 47 insertions(+), 16 deletions(-)

diff --git a/python/dune/perftool/cgen/clazz.py b/python/dune/perftool/cgen/clazz.py
index 03f4290f..0fed3054 100644
--- a/python/dune/perftool/cgen/clazz.py
+++ b/python/dune/perftool/cgen/clazz.py
@@ -41,11 +41,12 @@ class ClassMember(Generable):
             yield line + '\n'
 
 class Constructor(Generable):
-    def __init__(self, block=Block([]), arg_decls=[], clsname=None, access=AccessModifier.PUBLIC):
+    def __init__(self, block=Block([]), arg_decls=[], clsname=None, initializer_list=[], access=AccessModifier.PUBLIC):
         self.clsname = clsname
         self.arg_decls = arg_decls
         self.access = access
         self.block = block
+        self.il = initializer_list
 
     def generate(self):
         assert self.clsname
@@ -56,9 +57,16 @@ class Constructor(Generable):
         for ad in self.arg_decls:
             for content in ad.generate(with_semicolon=False):
                 yield content
-        yield ")"
+        yield ")\n"
 
-        # TODO Add initializer lists here as soon as they are needed
+        # add the initializer list
+        if self.il:
+            yield "    : {}".format(self.il[0])
+
+            for i in self.il[1:]:
+                yield ",\n"
+                yield "      {}".format(i)
+            yield '\n'
 
         for line in self.block.generate():
             yield line
@@ -99,10 +107,12 @@ class Class(Generable):
         yield '\n'
 
         # add base class inheritance
-        for i, bc in enumerate(self.base_classes):
-            yield "    : {} {}".format(access_modifier_string(bc.inheritance), bc.name)
-            if i+1 != len(self.base_classes):
-                yield ','
+        if self.base_classes:
+            yield "    : {} {}".format(access_modifier_string(self.base_classes[0].inheritance), self.base_classes[0].name)
+
+            for bc in self.base_classes[1:]:
+                yield ",\n"
+                yield "      {} {}".format(access_modifier_string(bc.inheritance), bc.name)
             yield '\n'
 
         # Now yield the entire block
diff --git a/python/dune/perftool/pdelab/localoperator.py b/python/dune/perftool/pdelab/localoperator.py
index 6c0240f1..a0d6a9b5 100644
--- a/python/dune/perftool/pdelab/localoperator.py
+++ b/python/dune/perftool/pdelab/localoperator.py
@@ -12,7 +12,17 @@ from pytools import memoize
 operator_include = generator_factory(item_tags=("include", "operator"), on_store=lambda i: Include(i), no_deco=True)
 from dune.perftool.cgen.clazz import BaseClass
 public_base_class = generator_factory(item_tags=("baseclass", "operator"), on_store=lambda n: BaseClass(n), counted=True, no_deco=True)
-initializer_list = generator_factory(item_tags=("pdelab", "initializer", "operator"), counted=True, no_deco=True)
+
+
+@generator_factory(item_tags=("initializer", "operator"), counted=True, cache_key_generator=lambda *a: a[0])
+def initializer_list(obj, params):
+    return "{}({})".format(obj, ", ".join(params))
+
+@generator_factory(item_tags=("operator", "member"), counted=True, cache_key_generator=lambda t,n : n)
+def define_private_member(_type, name):
+    from cgen import Value
+    from dune.perftool.cgen.clazz import ClassMember, AccessModifier
+    return ClassMember(Value(_type, name), access=AccessModifier.PRIVATE) 
 
 @generator_factory(item_tags=("operator", "constructor_param"), counted=True)
 def constructor_parameter(_type, name):
@@ -25,6 +35,14 @@ def name_initree_constructor():
     constructor_parameter("const Dune::ParameterTree&", "iniParams")
     return "iniParams"
 
+@dune_symbol
+def name_initree_member():
+    operator_include('dune/common/parametertree.hh')
+    define_private_member("const Dune::ParameterTree&", "_iniParams")
+    in_constructor = name_initree_constructor()
+    initializer_list("_iniParams", [in_constructor])
+    return "_iniParams"
+
 @dune_symbol
 def localoperator_type():
     #TODO use something from the form here to make it unique
@@ -43,9 +61,9 @@ def measure_specific_details(measure):
             public_base_class("Dune::PDELab::NumericalJacobian{}<{}>".format(which, loptype))
 
             # Add the initializer list for that base class
-            ini = name_initree_constructor()
-            initializer_list("Dune::PDELab::NumericalJacobian{}<{}>({}.get(\"numerical_epsilon.{}\", 1e-9))".format(which, loptype, ini, which.lower()))
-
+            ini = name_initree_member()
+            initializer_list("Dune::PDELab::NumericalJacobian{}<{}>".format(which, loptype),
+                             ["{}.get(\"numerical_epsilon.{}\", 1e-9)".format(ini, which.lower())])
 
     if measure == "cell":
         public_base_class('Dune::PDELab::FullVolumePattern')
@@ -80,9 +98,6 @@ def measure_specific_details(measure):
 def generate_kernel(integrand=None, measure=None):
     assert integrand and measure
 
-    from dune.perftool.generation import delete_cache
-    delete_cache()
-
     # Get the measure specifics
     specifics = measure_specific_details(measure)
 
@@ -111,6 +126,10 @@ def generate_kernel(integrand=None, measure=None):
     kernel = make_kernel(domains, instructions, arguments, temporary_variables=temporaries, target=DuneTarget())
     kernel = preprocess_kernel(kernel)
 
+    # All items with the kernel tags can be destroyed once a kernel has been generated
+    from dune.perftool.generation import delete_cache_items
+    delete_cache_items("kernel")
+
     # Return the actual code (might instead return kernels...)
     return kernel
 
@@ -129,12 +148,14 @@ def cgen_class_from_cache(tag, members=[]):
 
     base_classes = [bc for bc in retrieve_cache_items(tags=(tag, "baseclass"), union=False)]
     constructor_params = [bc for bc in retrieve_cache_items(tags=(tag, "constructor_param"), union=False)]
+    il = [i for i in retrieve_cache_items(tags=(tag, "initializer"), union=False)]
+    pm = [m for m in retrieve_cache_items(tags=(tag, "member"), union=False)]
 
     from dune.perftool.cgen.clazz import Constructor
-    constructor = Constructor(arg_decls=constructor_params, clsname=localoperator_type())
+    constructor = Constructor(arg_decls=constructor_params, clsname=localoperator_type(), initializer_list=il)
 
     from dune.perftool.cgen import Class
-    return Class(localoperator_type, base_classes=base_classes, members=members, constructors=[constructor])
+    return Class(localoperator_type, base_classes=base_classes, members=members + pm, constructors=[constructor])
 
 
 def generate_localoperator(form):
-- 
GitLab