From 013d4b88344c9cd9a8156a239910325220d9fd2e Mon Sep 17 00:00:00 2001 From: Hannes Vogt Date: Thu, 29 Oct 2026 16:54:27 +0100 Subject: [PATCH] refactor[next]: remove FieldOperatorFromFoast The math builtin test compiles its programmatically built FOAST stage directly through the backend. --- src/gt4py/next/ffront/decorator.py | 24 --------------- .../test_math_builtin_execution.py | 29 ++++++++----------- 2 files changed, 12 insertions(+), 41 deletions(-) diff --git a/src/gt4py/next/ffront/decorator.py b/src/gt4py/next/ffront/decorator.py index bf63aa692a..b40655f358 100644 --- a/src/gt4py/next/ffront/decorator.py +++ b/src/gt4py/next/ffront/decorator.py @@ -702,30 +702,6 @@ def __call__(self, *args: Any, enable_jit: bool | None = None, **kwargs: Any) -> GTEntryPoint: TypeAlias = Program | FieldOperator -# TODO(tehrengruber): This class does not follow the Liskov-Substitution principle as it doesn't -# have a field operator definition. Currently implementation is merely a hack to keep the only -# test relying on this working. Revisit. -@dataclasses.dataclass(frozen=True) -class FieldOperatorFromFoast(FieldOperator): - """ - This version of the field operator does not have a DSL definition. - - FieldOperator AST nodes can be programmatically built, which may be - particularly useful in testing and debugging. - This class provides the appropriate toolchain entry points. - """ - - foast_stage: ffront_stages.FOASTOperatorDef - - @override - def __call__(self, *args: Any, **kwargs: Any) -> Any: - assert self.backend is not None - compiled_fo = self.backend.compile( - self.foast_stage, arguments.CompileTimeArgs.from_concrete(*args, **kwargs) - ) - return compiled_fo(*args, **kwargs) - - @typing.overload def field_operator( definition: Callable, diff --git a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_math_builtin_execution.py b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_math_builtin_execution.py index 9bd7e43273..24318f7747 100644 --- a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_math_builtin_execution.py +++ b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_math_builtin_execution.py @@ -7,21 +7,19 @@ # SPDX-License-Identifier: BSD-3-Clause import math -from typing import Callable, Optional +from typing import Callable import numpy as np import pytest from gt4py.next.ffront import ( - decorator, dialect_ast_enums, fbuiltins, field_operator_ast as foast, stages as ffront_stages, ) from gt4py.next.ffront.foast_passes.type_deduction import FieldOperatorTypeDeduction -from gt4py.next import backend as next_backend -from gt4py.next.otf import options +from gt4py.next.otf import arguments from gt4py.next.type_system import type_translation from next_tests.integration_tests import cases @@ -39,7 +37,7 @@ # becomes easier. -def make_builtin_field_operator(builtin_name: str, backend: Optional[next_backend.Backend]): +def make_builtin_field_operator(builtin_name: str) -> ffront_stages.FOASTOperatorDef: # TODO(tehrengruber): creating a field operator programmatically should be # easier than what we need to do here. # construct annotation dictionary containing the input argument and return @@ -106,15 +104,10 @@ def make_builtin_field_operator(builtin_name: str, backend: Optional[next_backen ) typed_foast_node = FieldOperatorTypeDeduction.apply(foast_node) - return decorator.FieldOperatorFromFoast( - definition_stage=None, - foast_stage=ffront_stages.FOASTOperatorDef( - foast_node=typed_foast_node, - closure_vars=closure_vars, - grid_type=None, - ), - compilation_options=options.CompilationOptions(), - backend=backend, + return ffront_stages.FOASTOperatorDef( + foast_node=typed_foast_node, + closure_vars=closure_vars, + grid_type=None, ) @@ -133,8 +126,10 @@ def test_math_function_builtins_execution(cartesian_case, builtin_name: str, inp expected = ref_impl(*inputs) out = cartesian_case.as_field([IDim], np.zeros_like(expected)) - builtin_field_op = make_builtin_field_operator(builtin_name, cartesian_case.backend) - - builtin_field_op(*inps, out, offset_provider={}) + foast_stage = make_builtin_field_operator(builtin_name) + compiled = cartesian_case.backend.compile( + foast_stage, arguments.CompileTimeArgs.from_concrete(*inps, out, offset_provider={}) + ) + compiled(*inps, out, offset_provider={}) assert np.allclose(out.asnumpy(), expected)