From 439016154faa0aafeb5f7b6b14bd090b7c7d02df Mon Sep 17 00:00:00 2001
From: Frederik Hennig <frederik.hennig@fau.de>
Date: Wed, 15 Nov 2023 21:18:53 +0900
Subject: [PATCH] fixed nested namespaces

---
 pystencilssfg/context.py                           | 14 ++++++++++++++
 pystencilssfg/emitters/cpu/basic_cpu.py            |  9 +++++++--
 .../emitters/cpu/templates/BasicCpu.tmpl.cpp       | 12 ++++++++----
 .../emitters/cpu/templates/BasicCpu.tmpl.h         | 10 +++++++---
 pystencilssfg/kernel_namespace.py                  |  4 +++-
 pystencilssfg/tree/basic_nodes.py                  |  2 --
 pystencilssfg/tree/conditional.py                  |  2 +-
 7 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/pystencilssfg/context.py b/pystencilssfg/context.py
index 69ad66c..61cb60c 100644
--- a/pystencilssfg/context.py
+++ b/pystencilssfg/context.py
@@ -57,6 +57,8 @@ class SfgContext:
         self._config = config
         self._default_kernel_namespace = SfgKernelNamespace(self, "kernels")
 
+        self._code_namespace = None
+
         #   Source Components
         self._includes = set()
         self._kernel_namespaces = {self._default_kernel_namespace.name: self._default_kernel_namespace}
@@ -70,6 +72,18 @@ class SfgContext:
     def root_namespace(self) -> str:
         return self._config.base_namespace
 
+    @property
+    def inner_namespace(self) -> str:
+        return self._code_namespace
+
+    @property
+    def fully_qualified_namespace(self) -> str:
+        match (self.root_namespace, self.inner_namespace):
+            case None, None: return None
+            case outer, None: return outer
+            case None, inner: return inner
+            case outer, inner: return f"{outer}::{inner}"
+
     @property
     def codestyle(self) -> SfgCodeStyle:
         return self._config.codestyle
diff --git a/pystencilssfg/emitters/cpu/basic_cpu.py b/pystencilssfg/emitters/cpu/basic_cpu.py
index 69c7188..e6c3438 100644
--- a/pystencilssfg/emitters/cpu/basic_cpu.py
+++ b/pystencilssfg/emitters/cpu/basic_cpu.py
@@ -21,12 +21,14 @@ class BasicCpuEmitter:
         )
 
     def write_files(self, ctx: SfgContext):
+        fq_namespace = ctx.fully_qualified_namespace
+
         jinja_context = {
             'ctx': ctx,
             'header_filename': self._header_filename,
             'source_filename': self._source_filename,
             'basename': self._basename,
-            'root_namespace': ctx.root_namespace,
+            'fq_namespace': fq_namespace,
             'public_includes': list(incl.get_code() for incl in ctx.includes() if not incl.private),
             'private_includes': list(incl.get_code() for incl in ctx.includes() if incl.private),
             'kernel_namespaces': list(ctx.kernel_namespaces()),
@@ -35,7 +37,10 @@ class BasicCpuEmitter:
 
         template_name = "BasicCpu"
 
-        env = Environment(loader=PackageLoader('pystencilssfg.emitters.cpu'), undefined=StrictUndefined)
+        env = Environment(loader=PackageLoader('pystencilssfg.emitters.cpu'),
+                          undefined=StrictUndefined,
+                          trim_blocks=True,
+                          lstrip_blocks=True)
 
         from .jinja_filters import add_filters_to_jinja
         add_filters_to_jinja(env)
diff --git a/pystencilssfg/emitters/cpu/templates/BasicCpu.tmpl.cpp b/pystencilssfg/emitters/cpu/templates/BasicCpu.tmpl.cpp
index 1f2e614..dfb7a43 100644
--- a/pystencilssfg/emitters/cpu/templates/BasicCpu.tmpl.cpp
+++ b/pystencilssfg/emitters/cpu/templates/BasicCpu.tmpl.cpp
@@ -1,18 +1,20 @@
 #include "{{header_filename}}"
 
-{% for incl in private_includes -%}
+{% for incl in private_includes %}
 {{incl}}
 {% endfor %}
 
 #define FUNC_PREFIX inline
 
-namespace {{root_namespace}} {
+{% if fq_namespace is not none %}
+namespace {{fq_namespace}} {
+{% endif %}
 
 /*************************************************************************************
  *                                Kernels
 *************************************************************************************/
 
-{% for kns in kernel_namespaces -%}
+{% for kns in kernel_namespaces %}
 namespace {{ kns.name }} {
 
 {% for ast in kns.asts %}
@@ -32,4 +34,6 @@ void {{ function.name }} ( {{ function | generate_function_parameter_list }} ) {
 }
 {% endfor %}
 
-} // namespace {{root_namespace}}
+{% if fq_namespace is not none %}
+} // namespace {{fq_namespace}}
+{% endif %}
diff --git a/pystencilssfg/emitters/cpu/templates/BasicCpu.tmpl.h b/pystencilssfg/emitters/cpu/templates/BasicCpu.tmpl.h
index cf594e5..6cc4e5e 100644
--- a/pystencilssfg/emitters/cpu/templates/BasicCpu.tmpl.h
+++ b/pystencilssfg/emitters/cpu/templates/BasicCpu.tmpl.h
@@ -2,16 +2,20 @@
 
 #include <cstdint>
 
-{% for incl in public_includes -%}
+{% for incl in public_includes %}
 {{incl}}
 {% endfor %}
 
 #define RESTRICT __restrict__
 
-namespace {{root_namespace}} {
+{% if fq_namespace is not none %}
+namespace {{fq_namespace}} {
+{% endif %}
 
 {% for function in functions %}
 void {{ function.name }} ( {{ function | generate_function_parameter_list }} );
 {% endfor %}
 
-} // namespace {{root_namespace}}
+{% if fq_namespace is not none %}
+} // namespace {{fq_namespace}}
+{% endif %}
\ No newline at end of file
diff --git a/pystencilssfg/kernel_namespace.py b/pystencilssfg/kernel_namespace.py
index 1204e6c..ce5dde5 100644
--- a/pystencilssfg/kernel_namespace.py
+++ b/pystencilssfg/kernel_namespace.py
@@ -59,7 +59,9 @@ class SfgKernelHandle:
 
     @property
     def fully_qualified_name(self):
-        return f"{self._ctx.root_namespace}::{self.kernel_namespace.name}::{self.kernel_name}"
+        match self._ctx.fully_qualified_namespace:
+            case None: return f"{self.kernel_namespace.name}::{self.kernel_name}"
+            case fqn: return f"{fqn}::{self.kernel_namespace.name}::{self.kernel_name}"
 
     @property
     def parameters(self):
diff --git a/pystencilssfg/tree/basic_nodes.py b/pystencilssfg/tree/basic_nodes.py
index 3e0c03c..89d0edf 100644
--- a/pystencilssfg/tree/basic_nodes.py
+++ b/pystencilssfg/tree/basic_nodes.py
@@ -6,7 +6,6 @@ from itertools import chain
 
 from ..kernel_namespace import SfgKernelHandle
 from ..source_concepts.source_objects import SrcObject, TypedSymbolOrObject
-from ..exceptions import SfgException
 
 if TYPE_CHECKING:
     from ..context import SfgContext
@@ -43,7 +42,6 @@ class SfgCallTreeNode(ABC):
 
         By convention, the code block emitted by this function should not contain a trailing newline.
         """
-        pass
 
     @property
     def required_includes(self) -> Set[SfgHeaderInclude]:
diff --git a/pystencilssfg/tree/conditional.py b/pystencilssfg/tree/conditional.py
index c9c5eaf..45e91d8 100644
--- a/pystencilssfg/tree/conditional.py
+++ b/pystencilssfg/tree/conditional.py
@@ -1,5 +1,5 @@
 from __future__ import annotations
-from typing import TYPE_CHECKING, Sequence, Optional, Set
+from typing import TYPE_CHECKING, Optional, Set
 
 from .basic_nodes import SfgCallTreeNode, SfgCallTreeLeaf
 from ..source_concepts.source_objects import TypedSymbolOrObject
-- 
GitLab