Skip to content
Snippets Groups Projects
Commit 833d1f29 authored by Frederik Hennig's avatar Frederik Hennig
Browse files

Refactored namespaces

parent 03d9cd29
No related branches found
No related tags found
No related merge requests found
Pipeline #57743 failed
## Namespaces
Conceptually, there exist two different kinds of namespaces: *kernel namespaces* for the generated kernels,
and a single *code namespace* for all the generated code.
Both get mapped to standard C++ namespaces, in the end, but they fulfill different purposes in the code generator.
*Kernel namespaces* are used for grouping generated kernels together, e.g. to avoid name collisions.
If, for example, a code generation script combines kernels and functions produced by different components, each
component may create its own kernel namespace to isolate its kernels.
The *code namespace*, in contrast, envelops all the generated code. Its fully qualified name is built from two parts:
- The *outer namespace* is defined in the [generator configuration][pystencilssfg.SfgConfiguration], typically by
the global project configuration;
- The *inner namespace* is defined by the code generation script, e.g. via [`SfgComposer.namespace`][pystencilssfg.SfgComposer.namespace].
These namespaces will finally occur in the generated implementation file as:
```C++
namespace outer_namespace::inner_namespace {
namespace kernels {
/* kernel definitions */
} // namespace kernels
/* function definitions */
} // namespace outer_namespace::inner_namespace
```
...@@ -11,6 +11,6 @@ def sfg_config(): ...@@ -11,6 +11,6 @@ def sfg_config():
return SfgConfiguration( return SfgConfiguration(
header_extension='hpp', header_extension='hpp',
source_extension='cpp', source_extension='cpp',
base_namespace='cmake_demo', outer_namespace='cmake_demo',
project_info=project_info project_info=project_info
) )
# type: ignore
import sympy as sp import sympy as sp
from pystencils import fields, kernel from pystencils import fields, kernel
from pystencilssfg import SourceFileGenerator from pystencilssfg import SourceFileGenerator, SfgConfiguration
from pystencilssfg.source_concepts.cpp import mdspan_ref from pystencilssfg.source_concepts.cpp import mdspan_ref
with SourceFileGenerator() as sfg: sfg_config = SfgConfiguration(
outer_namespace="make_demo"
)
with SourceFileGenerator(sfg_config) as sfg:
sfg.namespace("jacobi")
u_src, u_dst, f = fields("u_src, u_dst, f(1) : double[2D]", layout="fzyx") u_src, u_dst, f = fields("u_src, u_dst, f(1) : double[2D]", layout="fzyx")
h = sp.Symbol("h") h = sp.Symbol("h")
......
...@@ -39,7 +39,7 @@ int main(int argc, char ** argv){ ...@@ -39,7 +39,7 @@ int main(int argc, char ** argv){
} }
for(uint32_t i = 0; i < n_iters; ++i){ for(uint32_t i = 0; i < n_iters; ++i){
jacobi_smooth(f, h, dst, src); make_demo::jacobi::jacobi_smooth(f, h, dst, src);
std::swap(src, dst); std::swap(src, dst);
} }
......
...@@ -24,6 +24,10 @@ class SfgComposer: ...@@ -24,6 +24,10 @@ class SfgComposer:
@property @property
def context(self): def context(self):
return self._ctx return self._ctx
def namespace(self, namespace: str):
"""Set the inner code namespace. Throws an exception if a namespace was already set."""
self._ctx.set_namespace(namespace)
@property @property
def kernels(self) -> SfgKernelNamespace: def kernels(self) -> SfgKernelNamespace:
......
...@@ -55,7 +55,7 @@ class SfgConfiguration: ...@@ -55,7 +55,7 @@ class SfgConfiguration:
header_only: bool | None = None header_only: bool | None = None
"""If set to `True`, generate only a header file without accompaning source file.""" """If set to `True`, generate only a header file without accompaning source file."""
base_namespace: str | None = None outer_namespace: str | None = None
"""The outermost namespace in the generated file. May be a valid C++ nested namespace qualifier """The outermost namespace in the generated file. May be a valid C++ nested namespace qualifier
(like `a::b::c`) or `None` if no outer namespace should be generated.""" (like `a::b::c`) or `None` if no outer namespace should be generated."""
...@@ -88,7 +88,7 @@ DEFAULT_CONFIG = SfgConfiguration( ...@@ -88,7 +88,7 @@ DEFAULT_CONFIG = SfgConfiguration(
header_extension='h', header_extension='h',
source_extension='cpp', source_extension='cpp',
header_only=False, header_only=False,
base_namespace=None, outer_namespace=None,
codestyle=SfgCodeStyle(), codestyle=SfgCodeStyle(),
output_directory="" output_directory=""
) )
......
...@@ -15,7 +15,9 @@ class SfgContext: ...@@ -15,7 +15,9 @@ class SfgContext:
self._code_namespace = None self._code_namespace = None
# Source Components # Source Components
self._prelude: list[str] = []
self._includes: set[SfgHeaderInclude] = set() self._includes: set[SfgHeaderInclude] = set()
self._definitions: list[str] = []
self._kernel_namespaces = {self._default_kernel_namespace.name: self._default_kernel_namespace} self._kernel_namespaces = {self._default_kernel_namespace.name: self._default_kernel_namespace}
self._functions: dict[str, SfgFunction] = dict() self._functions: dict[str, SfgFunction] = dict()
...@@ -31,8 +33,8 @@ class SfgContext: ...@@ -31,8 +33,8 @@ class SfgContext:
return self._argv return self._argv
@property @property
def root_namespace(self) -> str | None: def outer_namespace(self) -> str | None:
return self._config.base_namespace return self._config.outer_namespace
@property @property
def inner_namespace(self) -> str | None: def inner_namespace(self) -> str | None:
...@@ -40,7 +42,7 @@ class SfgContext: ...@@ -40,7 +42,7 @@ class SfgContext:
@property @property
def fully_qualified_namespace(self) -> str | None: def fully_qualified_namespace(self) -> str | None:
match (self.root_namespace, self.inner_namespace): match (self.outer_namespace, self.inner_namespace):
case None, None: return None case None, None: return None
case outer, None: return outer case outer, None: return outer
case None, inner: return inner case None, inner: return inner
...@@ -53,15 +55,37 @@ class SfgContext: ...@@ -53,15 +55,37 @@ class SfgContext:
return self._config.codestyle return self._config.codestyle
# ---------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------
# Kernel Namespaces # Prelude, Includes, Definitions, Namespace
# ---------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------
def prelude_comments(self) -> Generator[str, None, None]:
"""The prelude is a comment block printed at the top of both generated files."""
yield from self._prelude
def append_to_prelude(self, code_str: str):
self._prelude.append(code_str)
def includes(self) -> Generator[SfgHeaderInclude, None, None]: def includes(self) -> Generator[SfgHeaderInclude, None, None]:
"""Includes of headers. Public includes are added to the header file, private includes
are added to the implementation file."""
yield from self._includes yield from self._includes
def add_include(self, include: SfgHeaderInclude): def add_include(self, include: SfgHeaderInclude):
self._includes.add(include) self._includes.add(include)
def definitions(self) -> Generator[str, None, None]:
"""Definitions are code lines printed at the top of the header file, after the includes."""
yield from self._definitions
def add_definition(self, definition: str):
self._definitions.append(definition)
def set_namespace(self, namespace: str):
if self._code_namespace is not None:
raise SfgException("The code namespace was already set.")
self._code_namespace = namespace
# ---------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------
# Kernel Namespaces # Kernel Namespaces
# ---------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment