Skip to content
Snippets Groups Projects
Select Git revision
  • fcbdf0f5a6faa2df4313e38d5b47e9a7cc08e659
  • master default protected
  • v2.0-dev protected
  • zikeliml/Task-96-dotExporterForAST
  • zikeliml/124-rework-tutorials
  • fma
  • fhennig/v2.0-deprecations
  • holzer-master-patch-46757
  • 66-absolute-access-is-probably-not-copied-correctly-after-_eval_subs
  • gpu_bufferfield_fix
  • hyteg
  • vectorization_sqrt_fix
  • target_dh_refactoring
  • const_fix
  • improved_comm
  • gpu_liveness_opts
  • release/1.3.7 protected
  • release/1.3.6 protected
  • release/2.0.dev0 protected
  • release/1.3.5 protected
  • release/1.3.4 protected
  • release/1.3.3 protected
  • release/1.3.2 protected
  • release/1.3.1 protected
  • release/1.3 protected
  • release/1.2 protected
  • release/1.1.1 protected
  • release/1.1 protected
  • release/1.0.1 protected
  • release/1.0 protected
  • release/0.4.4 protected
  • last/Kerncraft
  • last/OpenCL
  • last/LLVM
  • release/0.4.3 protected
  • release/0.4.2 protected
36 results

test_vectorization.py

Blame
  • class_composer.py 7.69 KiB
    from __future__ import annotations
    from typing import Sequence
    
    from pystencils.types import PsCustomType, UserTypeSpec
    
    from ..lang import (
        _VarLike,
        VarLike,
        ExprLike,
        asvar,
        SfgVar,
    )
    
    from ..ir.source_components import (
        SfgClass,
        SfgClassMember,
        SfgInClassDefinition,
        SfgConstructor,
        SfgMethod,
        SfgMemberVariable,
        SfgClassKeyword,
        SfgVisibility,
        SfgVisibilityBlock,
    )
    from ..exceptions import SfgException
    
    from .mixin import SfgComposerMixIn
    from .basic_composer import (
        make_sequence,
        SequencerArg,
    )
    
    
    class SfgClassComposer(SfgComposerMixIn):
        """Composer for classes and structs.
    
    
        This class cannot be instantiated on its own but must be mixed in with
        :class:`SfgBasicComposer`.
        Its interface is exposed by :class:`SfgComposer`.
        """
    
        class VisibilityContext:
            """Represent a visibility block in the composer syntax.
    
            Returned by `private`, `public`, and `protected`.
            """
    
            def __init__(self, visibility: SfgVisibility):
                self._vis_block = SfgVisibilityBlock(visibility)
    
            def members(self):
                yield from self._vis_block.members()
    
            def __call__(
                self,
                *args: (
                    SfgClassMember | SfgClassComposer.ConstructorBuilder | VarLike | str
                ),
            ):
                for arg in args:
                    self._vis_block.append_member(SfgClassComposer._resolve_member(arg))
    
                return self
    
            def resolve(self, cls: SfgClass) -> None:
                cls.append_visibility_block(self._vis_block)
    
        class ConstructorBuilder:
            """Composer syntax for constructor building.
    
            Returned by `constructor`.
            """
    
            def __init__(self, *params: VarLike):
                self._params = list(asvar(p) for p in params)
                self._initializers: list[str] = []
                self._body: str | None = None
    
            def add_param(self, param: VarLike, at: int | None = None):
                if at is None:
                    self._params.append(asvar(param))
                else:
                    self._params.insert(at, asvar(param))
    
            @property
            def parameters(self) -> list[SfgVar]:
                return self._params
    
            def init(self, var: VarLike | str):
                """Add an initialization expression to the constructor's initializer list."""
    
                member = var if isinstance(var, str) else asvar(var)
    
                def init_sequencer(*args: ExprLike):
                    expr = ", ".join(str(arg) for arg in args)
                    initializer = f"{member}{{ {expr} }}"
                    self._initializers.append(initializer)
                    return self
    
                return init_sequencer
    
            def body(self, body: str):
                """Define the constructor body"""
                if self._body is not None:
                    raise SfgException("Multiple definitions of constructor body.")
                self._body = body
                return self
    
            def resolve(self) -> SfgConstructor:
                return SfgConstructor(
                    parameters=self._params,
                    initializers=self._initializers,
                    body=self._body if self._body is not None else "",
                )
    
        def klass(self, class_name: str, bases: Sequence[str] = ()):
            """Create a class and add it to the underlying context.
    
            Args:
                class_name: Name of the class
                bases: List of base classes
            """
            return self._class(class_name, SfgClassKeyword.CLASS, bases)
    
        def struct(self, class_name: str, bases: Sequence[str] = ()):
            """Create a struct and add it to the underlying context.
    
            Args:
                class_name: Name of the struct
                bases: List of base classes
            """
            return self._class(class_name, SfgClassKeyword.STRUCT, bases)
    
        @property
        def public(self) -> SfgClassComposer.VisibilityContext:
            """Create a `public` visibility block in a class body"""
            return SfgClassComposer.VisibilityContext(SfgVisibility.PUBLIC)
    
        @property
        def protected(self) -> SfgClassComposer.VisibilityContext:
            """Create a `protected` visibility block in a class or struct body"""
            return SfgClassComposer.VisibilityContext(SfgVisibility.PROTECTED)
    
        @property
        def private(self) -> SfgClassComposer.VisibilityContext:
            """Create a `private` visibility block in a class or struct body"""
            return SfgClassComposer.VisibilityContext(SfgVisibility.PRIVATE)
    
        def constructor(self, *params: VarLike):
            """In a class or struct body or visibility block, add a constructor.
    
            Args:
                params: List of constructor parameters
            """
            return SfgClassComposer.ConstructorBuilder(*params)
    
        def method(
            self,
            name: str,
            returns: UserTypeSpec = PsCustomType("void"),
            inline: bool = False,
            const: bool = False,
        ):
            """In a class or struct body or visibility block, add a method.
            The usage is similar to :any:`SfgBasicComposer.function`.
    
            Args:
                name: The method name
                returns: The method's return type
                inline: Whether or not the method should be defined in-line.
                const: Whether or not the method is const-qualified.
            """
    
            def sequencer(*args: SequencerArg):
                tree = make_sequence(*args)
                return SfgMethod(
                    name,
                    tree,
                    return_type=self._composer.cpptype(returns),
                    inline=inline,
                    const=const,
                )
    
            return sequencer
    
        #   INTERNALS
    
        def _class(self, class_name: str, keyword: SfgClassKeyword, bases: Sequence[str]):
            if self._ctx.get_class(class_name) is not None:
                raise ValueError(f"Class or struct {class_name} already exists.")
    
            cls = SfgClass(class_name, class_keyword=keyword, bases=bases)
            self._ctx.add_class(cls)
    
            def sequencer(
                *args: (
                    SfgClassComposer.VisibilityContext
                    | SfgClassMember
                    | SfgClassComposer.ConstructorBuilder
                    | VarLike
                    | str
                ),
            ):
                default_ended = False
    
                for arg in args:
                    if isinstance(arg, SfgClassComposer.VisibilityContext):
                        default_ended = True
                        arg.resolve(cls)
                    elif isinstance(
                        arg,
                        (
                            SfgClassMember,
                            SfgClassComposer.ConstructorBuilder,
                            str,
                        )
                        + _VarLike,
                    ):
                        if default_ended:
                            raise SfgException(
                                "Composer Syntax Error: "
                                "Cannot add members with default visibility after a visibility block."
                            )
                        else:
                            cls.default.append_member(self._resolve_member(arg))
                    else:
                        raise SfgException(f"{arg} is not a valid class member.")
    
            return sequencer
    
        @staticmethod
        def _resolve_member(
            arg: SfgClassMember | SfgClassComposer.ConstructorBuilder | VarLike | str,
        ) -> SfgClassMember:
            match arg:
                case _ if isinstance(arg, _VarLike):
                    var = asvar(arg)
                    return SfgMemberVariable(var.name, var.dtype)
                case str():
                    return SfgInClassDefinition(arg)
                case SfgClassComposer.ConstructorBuilder():
                    return arg.resolve()
                case SfgClassMember():
                    return arg
                case _:
                    raise ValueError(f"Invalid class member: {arg}")