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

Refactored namespaces

parent 03d9cd29
Branches
Tags
No related merge requests found
Pipeline #57743 failed with stages
in 16 seconds
## 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% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment