From fc8becc431b22e3545812cfaa01a994f2500dcdd Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Mon, 15 Jan 2024 19:54:40 +0000 Subject: [PATCH 01/14] feat: Implicit local modules in @guppy Tentatively adds a `compiled` option for directly generating a Hugr. --- guppy/decorator.py | 123 +++++++++++++++++++++++----- guppy/error.py | 4 +- poetry.lock | 36 ++++---- tests/integration/test_decorator.py | 43 ++++++++++ 4 files changed, 165 insertions(+), 41 deletions(-) create mode 100644 tests/integration/test_decorator.py diff --git a/guppy/decorator.py b/guppy/decorator.py index d4518f7b..a2ef1dac 100644 --- a/guppy/decorator.py +++ b/guppy/decorator.py @@ -1,6 +1,8 @@ import functools +import inspect from collections.abc import Callable, Iterator, Sequence from dataclasses import dataclass +from pathlib import Path from typing import Any, ClassVar, TypeVar from guppy.ast_util import AstNode, has_empty_body @@ -23,44 +25,104 @@ ClassDecorator = Callable[[type], type] +@dataclass +class CallerIdentifier: + """Identifier for the interpreter frame that called the decorator.""" + + filename: Path + function: str + + @property + def name(self) -> str: + """Returns a user-friendly name for the caller. + + If the called is not a function, uses the file name. + """ + if self.function == "": + return self.filename.name + return self.function + + def __hash__(self) -> int: + return hash((self.filename, self.function)) + + class _Guppy: """Class for the `@guppy` decorator.""" - # The current module - _module: GuppyModule | None + # The currently-alive modules, associated with an element in the call stack. + _modules: dict[CallerIdentifier, GuppyModule] def __init__(self) -> None: - self._module = None - - def set_module(self, module: GuppyModule) -> None: - self._module = module + self._modules = {} @pretty_errors - def __call__(self, arg: PyFunc | GuppyModule) -> Hugr | None | FuncDecorator: + def __call__( + self, arg: PyFunc | GuppyModule | None = None, *, compile: bool = False + ) -> Hugr | None | FuncDecorator: """Decorator to annotate Python functions as Guppy code. - Optionally, the `GuppyModule` in which the function should be placed can be - passed to the decorator. + Optionally, the `GuppyModule` in which the function should be placed can + be passed to the decorator. + + If `compile` is set to `True` and no `GuppyModule` is passed, the + function is compiled immediately as an standalone module and the Hugr is + returned. """ + if arg is not None and not isinstance(arg, GuppyModule): + # Decorator used without any arguments. + f = arg + return self.__call__(None)(f) + + def make_dummy(wraps: PyFunc) -> Callable[..., Any]: + @functools.wraps(wraps) + def dummy(*args: Any, **kwargs: Any) -> Any: + raise GuppyError( + "Guppy functions can only be called in a Guppy context" + ) + + return dummy + + if arg is None and compile: + # No module passed, and compile option is set. + def dec(f: Callable[..., Any]) -> Callable[..., Any]: + module = GuppyModule("module") + module.register_func_def(f) + return module.compile() + + return dec + + if arg is None and not compile: + # No module specified, and `compile` option is not set. + # We use a module associate with the caller of the decorator. + def dec(f: Callable[..., Any]) -> Callable[..., Any]: + caller = self._get_python_caller() + if caller not in self._modules: + self._modules[caller] = GuppyModule(caller.name) + module = self._modules[caller] + module.register_func_def(f) + return make_dummy(f) + + return dec + if isinstance(arg, GuppyModule): + # Module passed. Ignore `compile` option. def dec(f: Callable[..., Any]) -> Callable[..., Any]: - assert isinstance(arg, GuppyModule) arg.register_func_def(f) + return make_dummy(f) - @functools.wraps(f) - def dummy(*args: Any, **kwargs: Any) -> Any: - raise GuppyError( - "Guppy functions can only be called in a Guppy context" - ) + return dec - return dummy + raise ValueError(f"Invalid arguments to `@guppy` decorator: {arg}") - return dec - else: - module = self._module or GuppyModule("module") - module.register_func_def(arg) - return module.compile() + def _get_python_caller(self) -> CallerIdentifier: + """Returns an identifier for the interpreter frame that called the decorator.""" + for s in inspect.stack(): + # Note the hacky check for the pretty errors wrapper, + # since @pretty_errors wraps the __call__ method. + if s.filename != __file__ and s.function != "pretty_errors_wrapped": + return CallerIdentifier(Path(s.filename), s.function) + raise GuppyError("Could not find caller of `@guppy` decorator") @pretty_errors def extend_type(self, module: GuppyModule, ty: type[GuppyType]) -> ClassDecorator: @@ -204,5 +266,24 @@ def dummy(*args: Any, **kwargs: Any) -> Any: return dec + def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule | None: + """Returns the local GuppyModule, removing it from the local state.""" + if id is None: + id = self._get_python_caller() + if id not in self._modules: + return None + module = self._modules[id] + del self._modules[id] + return module + + def compile(self, id: CallerIdentifier | None = None) -> Hugr | None: + """Compiles the local module into a Hugr.""" + module = self.take_module(id) + return module.compile() if module else None + + def registered_modules(self) -> list[CallerIdentifier]: + """Returns a list of all currently registered modules for local contexts.""" + return list(self._modules.keys()) + guppy = _Guppy() diff --git a/guppy/error.py b/guppy/error.py index 14bb5813..3a0b4a94 100644 --- a/guppy/error.py +++ b/guppy/error.py @@ -166,7 +166,7 @@ def pretty_errors(f: FuncT) -> FuncT: """Decorator to print custom error banners when a `GuppyError` occurs.""" @functools.wraps(f) - def wrapped(*args: Any, **kwargs: Any) -> Any: + def pretty_errors_wrapped(*args: Any, **kwargs: Any) -> Any: try: return f(*args, **kwargs) except GuppyError as err: @@ -188,4 +188,4 @@ def wrapped(*args: Any, **kwargs: Any) -> Any: sys.exit(1) return None - return cast(FuncT, wrapped) + return cast(FuncT, pretty_errors_wrapped) diff --git a/poetry.lock b/poetry.lock index 7616bebb..3fe7ff53 100644 --- a/poetry.lock +++ b/poetry.lock @@ -542,28 +542,28 @@ files = [ [[package]] name = "ruff" -version = "0.1.12" +version = "0.1.13" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.1.12-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:544038693543c11edc56bb94a9875df2dc249e3616f90c15964c720dcccf0745"}, - {file = "ruff-0.1.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8a0e3ef6299c4eab75a7740730e4b4bd4a36e0bd8102ded01553403cad088fd4"}, - {file = "ruff-0.1.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47f6d939461e3273f10f4cd059fd0b83c249d73f1736032fffbac83a62939395"}, - {file = "ruff-0.1.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25be18abc1fc3f3d3fb55855c41ed5d52063316defde202f413493bb3888218c"}, - {file = "ruff-0.1.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d41e9f100b50526d80b076fc9c103c729387ff3f10f63606ed1038c30a372a40"}, - {file = "ruff-0.1.12-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:472a0548738d4711549c7874b43fab61aacafb1fede29c5232d4cfb8e2d13f69"}, - {file = "ruff-0.1.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46685ef2f106b827705df876d38617741ed4f858bbdbc0817f94476c45ab6669"}, - {file = "ruff-0.1.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf6073749c70b616d7929897b14824ec6713a6c3a8195dfd2ffdcc66594d880c"}, - {file = "ruff-0.1.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bdf26e5a2efab4c3aaf6b61648ea47a525dc12775810a85c285dc9ca03e5ac0"}, - {file = "ruff-0.1.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b631c6a95e4b6d5c4299e599067b5a89f5b18e2f2d9a6c22b879b3c4b077c96e"}, - {file = "ruff-0.1.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f193f460e231e63af5fc7516897cf5ab257cbda72ae83cf9a654f1c80c3b758a"}, - {file = "ruff-0.1.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:718523c3a0b787590511f212d30cc9b194228ef369c8bdd72acd1282cc27c468"}, - {file = "ruff-0.1.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1c49e826de55d81a6ef93808b760925e492bad7cc470aaa114a3be158b2c7f99"}, - {file = "ruff-0.1.12-py3-none-win32.whl", hash = "sha256:fbb1c002eeacb60161e51d77b2274c968656599477a1c8c65066953276e8ee2b"}, - {file = "ruff-0.1.12-py3-none-win_amd64.whl", hash = "sha256:7fe06ba77e5b7b78db1d058478c47176810f69bb5be7c1b0d06876af59198203"}, - {file = "ruff-0.1.12-py3-none-win_arm64.whl", hash = "sha256:bb29f8e3e6c95024902eaec5a9ce1fd5ac4e77f4594f4554e67fbb0f6d9a2f37"}, - {file = "ruff-0.1.12.tar.gz", hash = "sha256:97189f38c655e573f6bea0d12e9f18aad5539fd08ab50651449450999f45383a"}, + {file = "ruff-0.1.13-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e3fd36e0d48aeac672aa850045e784673449ce619afc12823ea7868fcc41d8ba"}, + {file = "ruff-0.1.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9fb6b3b86450d4ec6a6732f9f60c4406061b6851c4b29f944f8c9d91c3611c7a"}, + {file = "ruff-0.1.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b13ba5d7156daaf3fd08b6b993360a96060500aca7e307d95ecbc5bb47a69296"}, + {file = "ruff-0.1.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9ebb40442f7b531e136d334ef0851412410061e65d61ca8ce90d894a094feb22"}, + {file = "ruff-0.1.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226b517f42d59a543d6383cfe03cccf0091e3e0ed1b856c6824be03d2a75d3b6"}, + {file = "ruff-0.1.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5f0312ba1061e9b8c724e9a702d3c8621e3c6e6c2c9bd862550ab2951ac75c16"}, + {file = "ruff-0.1.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2f59bcf5217c661254bd6bc42d65a6fd1a8b80c48763cb5c2293295babd945dd"}, + {file = "ruff-0.1.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6894b00495e00c27b6ba61af1fc666f17de6140345e5ef27dd6e08fb987259d"}, + {file = "ruff-0.1.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a1600942485c6e66119da294c6294856b5c86fd6df591ce293e4a4cc8e72989"}, + {file = "ruff-0.1.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ee3febce7863e231a467f90e681d3d89210b900d49ce88723ce052c8761be8c7"}, + {file = "ruff-0.1.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dcaab50e278ff497ee4d1fe69b29ca0a9a47cd954bb17963628fa417933c6eb1"}, + {file = "ruff-0.1.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f57de973de4edef3ad3044d6a50c02ad9fc2dff0d88587f25f1a48e3f72edf5e"}, + {file = "ruff-0.1.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7a36fa90eb12208272a858475ec43ac811ac37e91ef868759770b71bdabe27b6"}, + {file = "ruff-0.1.13-py3-none-win32.whl", hash = "sha256:a623349a505ff768dad6bd57087e2461be8db58305ebd5577bd0e98631f9ae69"}, + {file = "ruff-0.1.13-py3-none-win_amd64.whl", hash = "sha256:f988746e3c3982bea7f824c8fa318ce7f538c4dfefec99cd09c8770bd33e6539"}, + {file = "ruff-0.1.13-py3-none-win_arm64.whl", hash = "sha256:6bbbc3042075871ec17f28864808540a26f0f79a4478c357d3e3d2284e832998"}, + {file = "ruff-0.1.13.tar.gz", hash = "sha256:e261f1baed6291f434ffb1d5c6bd8051d1c2a26958072d38dfbec39b3dda7352"}, ] [[package]] diff --git a/tests/integration/test_decorator.py b/tests/integration/test_decorator.py new file mode 100644 index 00000000..205c2fdc --- /dev/null +++ b/tests/integration/test_decorator.py @@ -0,0 +1,43 @@ +from guppy.decorator import guppy +from guppy.module import GuppyModule + + +def test_decorator(): + module = GuppyModule("test") + + @guppy + def a() -> None: + pass + + @guppy(module) + def b() -> None: + pass + + @guppy + def c() -> None: + pass + + default_module = guppy.take_module() + + assert not module.contains_function("a") + assert module.contains_function("b") + assert not module.contains_function("c") + + assert default_module.contains_function("a") + assert not default_module.contains_function("b") + assert default_module.contains_function("c") + + +def test_nested(): + def make_module() -> GuppyModule: + @guppy + def a() -> None: + pass + + return guppy.take_module() + + module_a = make_module() + module_b = make_module() + + assert module_a.contains_function("a") + assert module_b.contains_function("a") From ec1c4b829d05981eccbe943fd791874580edd2f6 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Mon, 15 Jan 2024 19:55:12 +0000 Subject: [PATCH 02/14] Use `@guppy(compiled=True)` in tests --- .../error/errors_on_usage/and_not_defined.py | 2 +- .../errors_on_usage/else_expr_not_defined.py | 2 +- .../errors_on_usage/else_expr_type_change.py | 2 +- .../error/errors_on_usage/else_not_defined.py | 2 +- .../else_not_defined_functional.py | 2 +- .../error/errors_on_usage/else_type_change.py | 2 +- .../else_type_change_functional.py | 2 +- .../errors_on_usage/if_different_types.py | 2 +- .../if_different_types_functional.py | 2 +- .../if_expr_cond_type_change.py | 2 +- .../errors_on_usage/if_expr_not_defined.py | 2 +- .../errors_on_usage/if_expr_type_change.py | 2 +- .../errors_on_usage/if_expr_type_conflict.err | 2 +- .../errors_on_usage/if_expr_type_conflict.py | 2 +- tests/error/errors_on_usage/if_not_defined.py | 2 +- .../if_not_defined_functional.py | 2 +- tests/error/errors_on_usage/if_type_change.py | 2 +- .../if_type_change_functional.py | 2 +- tests/error/errors_on_usage/or_not_defined.py | 2 +- tests/error/errors_on_usage/while_new_var.py | 2 +- .../while_new_var_functional.py | 2 +- .../errors_on_usage/while_type_change.py | 2 +- .../while_type_change_functional.py | 2 +- tests/error/misc_errors/arg_not_annotated.err | 2 +- tests/error/misc_errors/arg_not_annotated.py | 2 +- tests/error/misc_errors/functional_break.py | 2 +- .../error/misc_errors/functional_continue.py | 2 +- tests/error/misc_errors/functional_return.py | 2 +- tests/error/misc_errors/nested_functional.py | 2 +- tests/error/misc_errors/no_return.err | 2 +- tests/error/misc_errors/no_return.py | 2 +- .../misc_errors/return_not_annotated.err | 2 +- .../error/misc_errors/return_not_annotated.py | 2 +- .../return_not_annotated_none1.err | 2 +- .../misc_errors/return_not_annotated_none1.py | 2 +- .../return_not_annotated_none2.err | 2 +- .../misc_errors/return_not_annotated_none2.py | 2 +- tests/error/misc_errors/undefined_var.err | 2 +- tests/error/misc_errors/undefined_var.py | 2 +- tests/error/misc_errors/unreachable_1.py | 2 +- tests/error/misc_errors/unreachable_2.py | 2 +- tests/error/misc_errors/unreachable_3.py | 2 +- tests/error/misc_errors/unreachable_4.py | 2 +- tests/error/misc_errors/unreachable_5.py | 2 +- .../error/nested_errors/different_types_if.py | 2 +- tests/error/nested_errors/not_defined_if.py | 2 +- .../error/nested_errors/reassign_capture_1.py | 2 +- .../error/nested_errors/reassign_capture_2.py | 2 +- .../error/nested_errors/reassign_capture_3.py | 2 +- tests/error/nested_errors/var_not_defined.py | 2 +- tests/error/py_errors/guppy_name1.err | 2 +- tests/error/py_errors/guppy_name1.py | 2 +- tests/error/py_errors/guppy_name2.err | 2 +- tests/error/py_errors/guppy_name2.py | 2 +- tests/error/py_errors/no_args.err | 2 +- tests/error/py_errors/no_args.py | 2 +- tests/error/py_errors/python_err.err | 2 +- tests/error/py_errors/python_err.py | 2 +- tests/error/py_errors/unsupported.err | 2 +- tests/error/py_errors/unsupported.py | 2 +- .../type_errors/binary_not_arith_left.err | 2 +- .../type_errors/binary_not_arith_left.py | 2 +- .../type_errors/binary_not_arith_right.err | 2 +- .../type_errors/binary_not_arith_right.py | 2 +- tests/error/type_errors/call_missing_arg.err | 2 +- tests/error/type_errors/call_missing_arg.py | 2 +- tests/error/type_errors/call_not_function.err | 2 +- tests/error/type_errors/call_not_function.py | 2 +- .../error/type_errors/call_unexpected_arg.err | 2 +- .../error/type_errors/call_unexpected_arg.py | 2 +- tests/error/type_errors/call_wrong_arg.err | 2 +- tests/error/type_errors/call_wrong_arg.py | 2 +- tests/error/type_errors/fun_ty_mismatch_1.py | 2 +- tests/error/type_errors/fun_ty_mismatch_2.py | 2 +- tests/error/type_errors/fun_ty_mismatch_3.py | 2 +- .../type_errors/if_not_bool_functional.py | 2 +- tests/error/type_errors/invert_not_int.err | 2 +- tests/error/type_errors/invert_not_int.py | 2 +- tests/error/type_errors/return_mismatch.err | 2 +- tests/error/type_errors/return_mismatch.py | 2 +- tests/error/type_errors/unary_not_arith.err | 2 +- tests/error/type_errors/unary_not_arith.py | 2 +- tests/error/type_errors/unpack_not_enough.err | 2 +- tests/error/type_errors/unpack_not_enough.py | 2 +- tests/error/type_errors/unpack_too_many.err | 2 +- tests/error/type_errors/unpack_too_many.py | 2 +- .../type_errors/while_not_bool_functional.py | 2 +- tests/integration/test_arithmetic.py | 18 ++++---- tests/integration/test_basic.py | 16 +++---- tests/integration/test_call.py | 2 +- tests/integration/test_functional.py | 14 +++--- tests/integration/test_higher_order.py | 2 +- tests/integration/test_if.py | 44 +++++++++---------- tests/integration/test_nested.py | 28 ++++++------ tests/integration/test_programs.py | 6 +-- tests/integration/test_py.py | 12 ++--- tests/integration/test_unused.py | 16 +++---- tests/integration/test_while.py | 14 +++--- 98 files changed, 173 insertions(+), 173 deletions(-) diff --git a/tests/error/errors_on_usage/and_not_defined.py b/tests/error/errors_on_usage/and_not_defined.py index 0f29fa58..eb77665d 100644 --- a/tests/error/errors_on_usage/and_not_defined.py +++ b/tests/error/errors_on_usage/and_not_defined.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool, y: int) -> int: if x and (z := y + 1): return z diff --git a/tests/error/errors_on_usage/else_expr_not_defined.py b/tests/error/errors_on_usage/else_expr_not_defined.py index 04aec300..ca3e127f 100644 --- a/tests/error/errors_on_usage/else_expr_not_defined.py +++ b/tests/error/errors_on_usage/else_expr_not_defined.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: (y := 1) if x else (z := 2) return z diff --git a/tests/error/errors_on_usage/else_expr_type_change.py b/tests/error/errors_on_usage/else_expr_type_change.py index 0f77ff1e..ae5a3aaf 100644 --- a/tests/error/errors_on_usage/else_expr_type_change.py +++ b/tests/error/errors_on_usage/else_expr_type_change.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: y = 3 (y := y + 1) if x else (y := True) diff --git a/tests/error/errors_on_usage/else_not_defined.py b/tests/error/errors_on_usage/else_not_defined.py index a86d6cec..67f8f218 100644 --- a/tests/error/errors_on_usage/else_not_defined.py +++ b/tests/error/errors_on_usage/else_not_defined.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: if x: y = 1 diff --git a/tests/error/errors_on_usage/else_not_defined_functional.py b/tests/error/errors_on_usage/else_not_defined_functional.py index eac88f1b..75b24abb 100644 --- a/tests/error/errors_on_usage/else_not_defined_functional.py +++ b/tests/error/errors_on_usage/else_not_defined_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: _@functional if x: diff --git a/tests/error/errors_on_usage/else_type_change.py b/tests/error/errors_on_usage/else_type_change.py index ac3638a5..bb47734f 100644 --- a/tests/error/errors_on_usage/else_type_change.py +++ b/tests/error/errors_on_usage/else_type_change.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: y = 3 if x: diff --git a/tests/error/errors_on_usage/else_type_change_functional.py b/tests/error/errors_on_usage/else_type_change_functional.py index 34a7a61d..328bf85f 100644 --- a/tests/error/errors_on_usage/else_type_change_functional.py +++ b/tests/error/errors_on_usage/else_type_change_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: y = 3 _@functional diff --git a/tests/error/errors_on_usage/if_different_types.py b/tests/error/errors_on_usage/if_different_types.py index 5a871696..465f868b 100644 --- a/tests/error/errors_on_usage/if_different_types.py +++ b/tests/error/errors_on_usage/if_different_types.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: if x: y = 1 diff --git a/tests/error/errors_on_usage/if_different_types_functional.py b/tests/error/errors_on_usage/if_different_types_functional.py index efe65c51..0f3c2073 100644 --- a/tests/error/errors_on_usage/if_different_types_functional.py +++ b/tests/error/errors_on_usage/if_different_types_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: _@functional if x: diff --git a/tests/error/errors_on_usage/if_expr_cond_type_change.py b/tests/error/errors_on_usage/if_expr_cond_type_change.py index 46af4085..38c14b7c 100644 --- a/tests/error/errors_on_usage/if_expr_cond_type_change.py +++ b/tests/error/errors_on_usage/if_expr_cond_type_change.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: y = 4 0 if (y := x) else (y := 6) diff --git a/tests/error/errors_on_usage/if_expr_not_defined.py b/tests/error/errors_on_usage/if_expr_not_defined.py index b8b7f21f..270b4e6f 100644 --- a/tests/error/errors_on_usage/if_expr_not_defined.py +++ b/tests/error/errors_on_usage/if_expr_not_defined.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: (y := 1) if x else 0 return y diff --git a/tests/error/errors_on_usage/if_expr_type_change.py b/tests/error/errors_on_usage/if_expr_type_change.py index 96e57658..37d26863 100644 --- a/tests/error/errors_on_usage/if_expr_type_change.py +++ b/tests/error/errors_on_usage/if_expr_type_change.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool, a: int) -> int: y = 3 (y := False) if x or a > 5 else 0 diff --git a/tests/error/errors_on_usage/if_expr_type_conflict.err b/tests/error/errors_on_usage/if_expr_type_conflict.err index 3a1efcbb..98b2f422 100644 --- a/tests/error/errors_on_usage/if_expr_type_conflict.err +++ b/tests/error/errors_on_usage/if_expr_type_conflict.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo(x: bool) -> None: 6: y = True if x else 42 ^^^^^^^^^^^^^^^^^ diff --git a/tests/error/errors_on_usage/if_expr_type_conflict.py b/tests/error/errors_on_usage/if_expr_type_conflict.py index f2e921da..bd9eaa1d 100644 --- a/tests/error/errors_on_usage/if_expr_type_conflict.py +++ b/tests/error/errors_on_usage/if_expr_type_conflict.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> None: y = True if x else 42 diff --git a/tests/error/errors_on_usage/if_not_defined.py b/tests/error/errors_on_usage/if_not_defined.py index f613e168..6b6b6c22 100644 --- a/tests/error/errors_on_usage/if_not_defined.py +++ b/tests/error/errors_on_usage/if_not_defined.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: if x: y = 1 diff --git a/tests/error/errors_on_usage/if_not_defined_functional.py b/tests/error/errors_on_usage/if_not_defined_functional.py index 47aff403..7fd9e282 100644 --- a/tests/error/errors_on_usage/if_not_defined_functional.py +++ b/tests/error/errors_on_usage/if_not_defined_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: _@functional if x: diff --git a/tests/error/errors_on_usage/if_type_change.py b/tests/error/errors_on_usage/if_type_change.py index 1e688b5b..ef46c4e0 100644 --- a/tests/error/errors_on_usage/if_type_change.py +++ b/tests/error/errors_on_usage/if_type_change.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: y = 3 if x: diff --git a/tests/error/errors_on_usage/if_type_change_functional.py b/tests/error/errors_on_usage/if_type_change_functional.py index 58ed7baa..605f9871 100644 --- a/tests/error/errors_on_usage/if_type_change_functional.py +++ b/tests/error/errors_on_usage/if_type_change_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: y = 3 _@functional diff --git a/tests/error/errors_on_usage/or_not_defined.py b/tests/error/errors_on_usage/or_not_defined.py index 2435f624..167055d9 100644 --- a/tests/error/errors_on_usage/or_not_defined.py +++ b/tests/error/errors_on_usage/or_not_defined.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool, y: int) -> int: if x or (z := y + 1): return z diff --git a/tests/error/errors_on_usage/while_new_var.py b/tests/error/errors_on_usage/while_new_var.py index 28a63a58..f3c07672 100644 --- a/tests/error/errors_on_usage/while_new_var.py +++ b/tests/error/errors_on_usage/while_new_var.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: while x: y = 5 diff --git a/tests/error/errors_on_usage/while_new_var_functional.py b/tests/error/errors_on_usage/while_new_var_functional.py index d596834c..25844bc7 100644 --- a/tests/error/errors_on_usage/while_new_var_functional.py +++ b/tests/error/errors_on_usage/while_new_var_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/errors_on_usage/while_type_change.py b/tests/error/errors_on_usage/while_type_change.py index c8e565b1..3ee10443 100644 --- a/tests/error/errors_on_usage/while_type_change.py +++ b/tests/error/errors_on_usage/while_type_change.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: y = 5 while x: diff --git a/tests/error/errors_on_usage/while_type_change_functional.py b/tests/error/errors_on_usage/while_type_change_functional.py index 343e4433..9bca1833 100644 --- a/tests/error/errors_on_usage/while_type_change_functional.py +++ b/tests/error/errors_on_usage/while_type_change_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: y = 5 _@functional diff --git a/tests/error/misc_errors/arg_not_annotated.err b/tests/error/misc_errors/arg_not_annotated.err index a607dc9b..5b588fda 100644 --- a/tests/error/misc_errors/arg_not_annotated.err +++ b/tests/error/misc_errors/arg_not_annotated.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:5 -3: @guppy +3: @guppy(compile=True) 4: def foo(x: bool, y) -> int: ^ GuppyError: Argument type must be annotated diff --git a/tests/error/misc_errors/arg_not_annotated.py b/tests/error/misc_errors/arg_not_annotated.py index 503393af..88e2f420 100644 --- a/tests/error/misc_errors/arg_not_annotated.py +++ b/tests/error/misc_errors/arg_not_annotated.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool, y) -> int: return y diff --git a/tests/error/misc_errors/functional_break.py b/tests/error/misc_errors/functional_break.py index 2b03e316..8ba01169 100644 --- a/tests/error/misc_errors/functional_break.py +++ b/tests/error/misc_errors/functional_break.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/misc_errors/functional_continue.py b/tests/error/misc_errors/functional_continue.py index eced5d96..acaea8de 100644 --- a/tests/error/misc_errors/functional_continue.py +++ b/tests/error/misc_errors/functional_continue.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/misc_errors/functional_return.py b/tests/error/misc_errors/functional_return.py index 1821020e..9125d489 100644 --- a/tests/error/misc_errors/functional_return.py +++ b/tests/error/misc_errors/functional_return.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/misc_errors/nested_functional.py b/tests/error/misc_errors/nested_functional.py index 7094903c..b47d11a2 100644 --- a/tests/error/misc_errors/nested_functional.py +++ b/tests/error/misc_errors/nested_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/misc_errors/no_return.err b/tests/error/misc_errors/no_return.err index 21a5858e..36693946 100644 --- a/tests/error/misc_errors/no_return.err +++ b/tests/error/misc_errors/no_return.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> int: 6: pass ^^^^ diff --git a/tests/error/misc_errors/no_return.py b/tests/error/misc_errors/no_return.py index 3f70926a..5eac1ffc 100644 --- a/tests/error/misc_errors/no_return.py +++ b/tests/error/misc_errors/no_return.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: pass diff --git a/tests/error/misc_errors/return_not_annotated.err b/tests/error/misc_errors/return_not_annotated.err index dcce68ed..35e9e27f 100644 --- a/tests/error/misc_errors/return_not_annotated.err +++ b/tests/error/misc_errors/return_not_annotated.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:5 -3: @guppy +3: @guppy(compile=True) 4: def foo(x: bool): ^^^^^^^^^^^^^^^^^ GuppyError: Return type must be annotated diff --git a/tests/error/misc_errors/return_not_annotated.py b/tests/error/misc_errors/return_not_annotated.py index 43ce1a8c..25444a56 100644 --- a/tests/error/misc_errors/return_not_annotated.py +++ b/tests/error/misc_errors/return_not_annotated.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool): return x diff --git a/tests/error/misc_errors/return_not_annotated_none1.err b/tests/error/misc_errors/return_not_annotated_none1.err index 58d79a43..fc8ab7e9 100644 --- a/tests/error/misc_errors/return_not_annotated_none1.err +++ b/tests/error/misc_errors/return_not_annotated_none1.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:5 -3: @guppy +3: @guppy(compile=True) 4: def foo(): ^^^^^^^^^^ GuppyError: Return type must be annotated. Try adding a `-> None` annotation. diff --git a/tests/error/misc_errors/return_not_annotated_none1.py b/tests/error/misc_errors/return_not_annotated_none1.py index b85e6de1..81d8f9cd 100644 --- a/tests/error/misc_errors/return_not_annotated_none1.py +++ b/tests/error/misc_errors/return_not_annotated_none1.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(): return diff --git a/tests/error/misc_errors/return_not_annotated_none2.err b/tests/error/misc_errors/return_not_annotated_none2.err index 58d79a43..fc8ab7e9 100644 --- a/tests/error/misc_errors/return_not_annotated_none2.err +++ b/tests/error/misc_errors/return_not_annotated_none2.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:5 -3: @guppy +3: @guppy(compile=True) 4: def foo(): ^^^^^^^^^^ GuppyError: Return type must be annotated. Try adding a `-> None` annotation. diff --git a/tests/error/misc_errors/return_not_annotated_none2.py b/tests/error/misc_errors/return_not_annotated_none2.py index ffd09c8c..72528695 100644 --- a/tests/error/misc_errors/return_not_annotated_none2.py +++ b/tests/error/misc_errors/return_not_annotated_none2.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(): def bar(x: int) -> int: return x diff --git a/tests/error/misc_errors/undefined_var.err b/tests/error/misc_errors/undefined_var.err index b405ba4a..12c99cfd 100644 --- a/tests/error/misc_errors/undefined_var.err +++ b/tests/error/misc_errors/undefined_var.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> int: 6: return x ^ diff --git a/tests/error/misc_errors/undefined_var.py b/tests/error/misc_errors/undefined_var.py index 6ff8e942..ea6e45f4 100644 --- a/tests/error/misc_errors/undefined_var.py +++ b/tests/error/misc_errors/undefined_var.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: return x diff --git a/tests/error/misc_errors/unreachable_1.py b/tests/error/misc_errors/unreachable_1.py index bf4948e5..d19aa08d 100644 --- a/tests/error/misc_errors/unreachable_1.py +++ b/tests/error/misc_errors/unreachable_1.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: return 0 x = 42 diff --git a/tests/error/misc_errors/unreachable_2.py b/tests/error/misc_errors/unreachable_2.py index 1a9722fd..31edf016 100644 --- a/tests/error/misc_errors/unreachable_2.py +++ b/tests/error/misc_errors/unreachable_2.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: if x: return 4 diff --git a/tests/error/misc_errors/unreachable_3.py b/tests/error/misc_errors/unreachable_3.py index 9bf3265e..aab12fcf 100644 --- a/tests/error/misc_errors/unreachable_3.py +++ b/tests/error/misc_errors/unreachable_3.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: while x: break diff --git a/tests/error/misc_errors/unreachable_4.py b/tests/error/misc_errors/unreachable_4.py index 076c4e68..d0735436 100644 --- a/tests/error/misc_errors/unreachable_4.py +++ b/tests/error/misc_errors/unreachable_4.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: while x: continue diff --git a/tests/error/misc_errors/unreachable_5.py b/tests/error/misc_errors/unreachable_5.py index ba3e5740..c9faee15 100644 --- a/tests/error/misc_errors/unreachable_5.py +++ b/tests/error/misc_errors/unreachable_5.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: bool) -> int: while x: return 42 diff --git a/tests/error/nested_errors/different_types_if.py b/tests/error/nested_errors/different_types_if.py index 7641d715..9068c0dd 100644 --- a/tests/error/nested_errors/different_types_if.py +++ b/tests/error/nested_errors/different_types_if.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(b: bool) -> int: if b: def bar() -> int: diff --git a/tests/error/nested_errors/not_defined_if.py b/tests/error/nested_errors/not_defined_if.py index 40b0833d..6fb9d7a0 100644 --- a/tests/error/nested_errors/not_defined_if.py +++ b/tests/error/nested_errors/not_defined_if.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(b: bool) -> int: if b: def bar() -> int: diff --git a/tests/error/nested_errors/reassign_capture_1.py b/tests/error/nested_errors/reassign_capture_1.py index 33151d92..d353e007 100644 --- a/tests/error/nested_errors/reassign_capture_1.py +++ b/tests/error/nested_errors/reassign_capture_1.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: y = x + 1 diff --git a/tests/error/nested_errors/reassign_capture_2.py b/tests/error/nested_errors/reassign_capture_2.py index 83769889..8f75b585 100644 --- a/tests/error/nested_errors/reassign_capture_2.py +++ b/tests/error/nested_errors/reassign_capture_2.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: y = x + 1 diff --git a/tests/error/nested_errors/reassign_capture_3.py b/tests/error/nested_errors/reassign_capture_3.py index b26fdd89..09ae0ed1 100644 --- a/tests/error/nested_errors/reassign_capture_3.py +++ b/tests/error/nested_errors/reassign_capture_3.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: y = x + 1 diff --git a/tests/error/nested_errors/var_not_defined.py b/tests/error/nested_errors/var_not_defined.py index 8d7abb7e..d991cc65 100644 --- a/tests/error/nested_errors/var_not_defined.py +++ b/tests/error/nested_errors/var_not_defined.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: def bar() -> int: return x diff --git a/tests/error/py_errors/guppy_name1.err b/tests/error/py_errors/guppy_name1.err index f870fe12..2699fd77 100644 --- a/tests/error/py_errors/guppy_name1.err +++ b/tests/error/py_errors/guppy_name1.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo(x: int) -> int: 6: return py(x + 1) ^ diff --git a/tests/error/py_errors/guppy_name1.py b/tests/error/py_errors/guppy_name1.py index d1697d0a..13ef567c 100644 --- a/tests/error/py_errors/guppy_name1.py +++ b/tests/error/py_errors/guppy_name1.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: return py(x + 1) diff --git a/tests/error/py_errors/guppy_name2.err b/tests/error/py_errors/guppy_name2.err index fb0c8437..10dc8e38 100644 --- a/tests/error/py_errors/guppy_name2.err +++ b/tests/error/py_errors/guppy_name2.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:9 -7: @guppy +7: @guppy(compile=True) 8: def foo(x: int) -> int: 9: return py(x + 1) ^ diff --git a/tests/error/py_errors/guppy_name2.py b/tests/error/py_errors/guppy_name2.py index 44ca9852..7141a612 100644 --- a/tests/error/py_errors/guppy_name2.py +++ b/tests/error/py_errors/guppy_name2.py @@ -4,6 +4,6 @@ x = 42 -@guppy +@guppy(compile=True) def foo(x: int) -> int: return py(x + 1) diff --git a/tests/error/py_errors/no_args.err b/tests/error/py_errors/no_args.err index 5f8f43fb..28b70b9e 100644 --- a/tests/error/py_errors/no_args.err +++ b/tests/error/py_errors/no_args.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> int: 6: return py() ^^^^ diff --git a/tests/error/py_errors/no_args.py b/tests/error/py_errors/no_args.py index 26bdda63..176fd688 100644 --- a/tests/error/py_errors/no_args.py +++ b/tests/error/py_errors/no_args.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: return py() diff --git a/tests/error/py_errors/python_err.err b/tests/error/py_errors/python_err.err index 9d4c1e70..85f2ff66 100644 --- a/tests/error/py_errors/python_err.err +++ b/tests/error/py_errors/python_err.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> int: 6: return py(1 / 0) ^^^^^^^^^ diff --git a/tests/error/py_errors/python_err.py b/tests/error/py_errors/python_err.py index 803ec227..9fd5737f 100644 --- a/tests/error/py_errors/python_err.py +++ b/tests/error/py_errors/python_err.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: return py(1 / 0) diff --git a/tests/error/py_errors/unsupported.err b/tests/error/py_errors/unsupported.err index 22343611..d9310150 100644 --- a/tests/error/py_errors/unsupported.err +++ b/tests/error/py_errors/unsupported.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> int: 6: return py({1, 2, 3}) ^^^^^^^^^^^^^ diff --git a/tests/error/py_errors/unsupported.py b/tests/error/py_errors/unsupported.py index e238f300..68b1dd2b 100644 --- a/tests/error/py_errors/unsupported.py +++ b/tests/error/py_errors/unsupported.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: return py({1, 2, 3}) diff --git a/tests/error/type_errors/binary_not_arith_left.err b/tests/error/type_errors/binary_not_arith_left.err index 4a532750..bbac107a 100644 --- a/tests/error/type_errors/binary_not_arith_left.err +++ b/tests/error/type_errors/binary_not_arith_left.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo(x: int) -> int: 6: return (1, 1) * 4 ^^^^^^^^^^ diff --git a/tests/error/type_errors/binary_not_arith_left.py b/tests/error/type_errors/binary_not_arith_left.py index fd79799c..c9cda792 100644 --- a/tests/error/type_errors/binary_not_arith_left.py +++ b/tests/error/type_errors/binary_not_arith_left.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: return (1, 1) * 4 diff --git a/tests/error/type_errors/binary_not_arith_right.err b/tests/error/type_errors/binary_not_arith_right.err index 0d9447c0..08ff77a7 100644 --- a/tests/error/type_errors/binary_not_arith_right.err +++ b/tests/error/type_errors/binary_not_arith_right.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo(x: int) -> int: 6: return x + True ^^^^^^^^ diff --git a/tests/error/type_errors/binary_not_arith_right.py b/tests/error/type_errors/binary_not_arith_right.py index 8240774c..d70b9424 100644 --- a/tests/error/type_errors/binary_not_arith_right.py +++ b/tests/error/type_errors/binary_not_arith_right.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: return x + True diff --git a/tests/error/type_errors/call_missing_arg.err b/tests/error/type_errors/call_missing_arg.err index 10ccaed5..7efbe771 100644 --- a/tests/error/type_errors/call_missing_arg.err +++ b/tests/error/type_errors/call_missing_arg.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo(x: int) -> int: 6: return foo() ^^^^^ diff --git a/tests/error/type_errors/call_missing_arg.py b/tests/error/type_errors/call_missing_arg.py index 26160fbd..2aee1287 100644 --- a/tests/error/type_errors/call_missing_arg.py +++ b/tests/error/type_errors/call_missing_arg.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: return foo() diff --git a/tests/error/type_errors/call_not_function.err b/tests/error/type_errors/call_not_function.err index a2e5befb..e0a31066 100644 --- a/tests/error/type_errors/call_not_function.err +++ b/tests/error/type_errors/call_not_function.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo(x: int) -> int: 6: return x(42) ^ diff --git a/tests/error/type_errors/call_not_function.py b/tests/error/type_errors/call_not_function.py index 0dde7dc9..15b5ffe3 100644 --- a/tests/error/type_errors/call_not_function.py +++ b/tests/error/type_errors/call_not_function.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: return x(42) diff --git a/tests/error/type_errors/call_unexpected_arg.err b/tests/error/type_errors/call_unexpected_arg.err index c09395c5..38d4685e 100644 --- a/tests/error/type_errors/call_unexpected_arg.err +++ b/tests/error/type_errors/call_unexpected_arg.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo(x: int) -> int: 6: return foo(x, x) ^ diff --git a/tests/error/type_errors/call_unexpected_arg.py b/tests/error/type_errors/call_unexpected_arg.py index 0d1f7975..5b87f4a6 100644 --- a/tests/error/type_errors/call_unexpected_arg.py +++ b/tests/error/type_errors/call_unexpected_arg.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: return foo(x, x) diff --git a/tests/error/type_errors/call_wrong_arg.err b/tests/error/type_errors/call_wrong_arg.err index 94daf5dc..30a2f122 100644 --- a/tests/error/type_errors/call_wrong_arg.err +++ b/tests/error/type_errors/call_wrong_arg.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo(x: int) -> int: 6: return foo(True) ^^^^ diff --git a/tests/error/type_errors/call_wrong_arg.py b/tests/error/type_errors/call_wrong_arg.py index 78d37c70..1115b40a 100644 --- a/tests/error/type_errors/call_wrong_arg.py +++ b/tests/error/type_errors/call_wrong_arg.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: return foo(True) diff --git a/tests/error/type_errors/fun_ty_mismatch_1.py b/tests/error/type_errors/fun_ty_mismatch_1.py index 69ba1cfc..fc933a1b 100644 --- a/tests/error/type_errors/fun_ty_mismatch_1.py +++ b/tests/error/type_errors/fun_ty_mismatch_1.py @@ -3,7 +3,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> Callable[[int], int]: def bar(x: int) -> bool: return x > 0 diff --git a/tests/error/type_errors/fun_ty_mismatch_2.py b/tests/error/type_errors/fun_ty_mismatch_2.py index 602c00f6..9f32a6bc 100644 --- a/tests/error/type_errors/fun_ty_mismatch_2.py +++ b/tests/error/type_errors/fun_ty_mismatch_2.py @@ -3,7 +3,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: def bar(f: Callable[[], int]) -> int: return f() diff --git a/tests/error/type_errors/fun_ty_mismatch_3.py b/tests/error/type_errors/fun_ty_mismatch_3.py index bfe5b742..3b697f75 100644 --- a/tests/error/type_errors/fun_ty_mismatch_3.py +++ b/tests/error/type_errors/fun_ty_mismatch_3.py @@ -3,7 +3,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo(x: int) -> int: def bar(f: Callable[[int], bool]) -> bool: return f(42) diff --git a/tests/error/type_errors/if_not_bool_functional.py b/tests/error/type_errors/if_not_bool_functional.py index 09ecd285..581eec63 100644 --- a/tests/error/type_errors/if_not_bool_functional.py +++ b/tests/error/type_errors/if_not_bool_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: _@functional if 42: diff --git a/tests/error/type_errors/invert_not_int.err b/tests/error/type_errors/invert_not_int.err index fa1d83a2..e3317d5c 100644 --- a/tests/error/type_errors/invert_not_int.err +++ b/tests/error/type_errors/invert_not_int.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> int: 6: return ~True ^^^^ diff --git a/tests/error/type_errors/invert_not_int.py b/tests/error/type_errors/invert_not_int.py index c18fd4e1..41d6f27f 100644 --- a/tests/error/type_errors/invert_not_int.py +++ b/tests/error/type_errors/invert_not_int.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: return ~True diff --git a/tests/error/type_errors/return_mismatch.err b/tests/error/type_errors/return_mismatch.err index a59582be..0f6dfa97 100644 --- a/tests/error/type_errors/return_mismatch.err +++ b/tests/error/type_errors/return_mismatch.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> bool: 6: return 42 ^^ diff --git a/tests/error/type_errors/return_mismatch.py b/tests/error/type_errors/return_mismatch.py index ca2fd8b5..7a517d61 100644 --- a/tests/error/type_errors/return_mismatch.py +++ b/tests/error/type_errors/return_mismatch.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> bool: return 42 diff --git a/tests/error/type_errors/unary_not_arith.err b/tests/error/type_errors/unary_not_arith.err index 5baf6757..f7c7daa7 100644 --- a/tests/error/type_errors/unary_not_arith.err +++ b/tests/error/type_errors/unary_not_arith.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> int: 6: return -True ^^^^ diff --git a/tests/error/type_errors/unary_not_arith.py b/tests/error/type_errors/unary_not_arith.py index 81134390..b5682c03 100644 --- a/tests/error/type_errors/unary_not_arith.py +++ b/tests/error/type_errors/unary_not_arith.py @@ -1,6 +1,6 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: return -True diff --git a/tests/error/type_errors/unpack_not_enough.err b/tests/error/type_errors/unpack_not_enough.err index 9628fc53..a1330755 100644 --- a/tests/error/type_errors/unpack_not_enough.err +++ b/tests/error/type_errors/unpack_not_enough.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> int: 6: a, b, c = 1, True ^^^^^^^^^^^^^^^^^ diff --git a/tests/error/type_errors/unpack_not_enough.py b/tests/error/type_errors/unpack_not_enough.py index c022b692..1ec5a423 100644 --- a/tests/error/type_errors/unpack_not_enough.py +++ b/tests/error/type_errors/unpack_not_enough.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: a, b, c = 1, True return a diff --git a/tests/error/type_errors/unpack_too_many.err b/tests/error/type_errors/unpack_too_many.err index aee08762..9590a2f4 100644 --- a/tests/error/type_errors/unpack_too_many.err +++ b/tests/error/type_errors/unpack_too_many.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @guppy(compile=True) 5: def foo() -> int: 6: a, b = 1, True, 3.0 ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/error/type_errors/unpack_too_many.py b/tests/error/type_errors/unpack_too_many.py index 71946970..12d3b402 100644 --- a/tests/error/type_errors/unpack_too_many.py +++ b/tests/error/type_errors/unpack_too_many.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: a, b = 1, True, 3.0 return a diff --git a/tests/error/type_errors/while_not_bool_functional.py b/tests/error/type_errors/while_not_bool_functional.py index 53c53bf1..43e40a9a 100644 --- a/tests/error/type_errors/while_not_bool_functional.py +++ b/tests/error/type_errors/while_not_bool_functional.py @@ -1,7 +1,7 @@ from guppy.decorator import guppy -@guppy +@guppy(compile=True) def foo() -> int: _@functional while 42: diff --git a/tests/integration/test_arithmetic.py b/tests/integration/test_arithmetic.py index c4112fd1..fcef4a06 100644 --- a/tests/integration/test_arithmetic.py +++ b/tests/integration/test_arithmetic.py @@ -2,7 +2,7 @@ def test_arith_basic(validate): - @guppy + @guppy(compile=True) def add(x: int, y: int) -> int: return x + y @@ -10,7 +10,7 @@ def add(x: int, y: int) -> int: def test_constant(validate): - @guppy + @guppy(compile=True) def const() -> float: return 42.0 @@ -18,7 +18,7 @@ def const() -> float: def test_aug_assign(validate): - @guppy + @guppy(compile=True) def add(x: int) -> int: x += 1 return x @@ -27,7 +27,7 @@ def add(x: int) -> int: def test_float_coercion(validate): - @guppy + @guppy(compile=True) def coerce(x: int, y: float) -> float: return x * y @@ -35,7 +35,7 @@ def coerce(x: int, y: float) -> float: def test_arith_big(validate): - @guppy + @guppy(compile=True) def arith(x: int, y: float, z: int) -> bool: a = x // y + 3 * z b = -8 >= a > 5 or (x * y == 0 and a % 3 < x) @@ -45,7 +45,7 @@ def arith(x: int, y: float, z: int) -> bool: def test_shortcircuit_assign1(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> bool: if (z := x) and y > 0: return z @@ -55,7 +55,7 @@ def foo(x: bool, y: int) -> bool: def test_shortcircuit_assign2(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> bool: if y > 0 and (z := x): return z @@ -65,7 +65,7 @@ def foo(x: bool, y: int) -> bool: def test_shortcircuit_assign3(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> bool: if (z := x) or y > 0: return z @@ -75,7 +75,7 @@ def foo(x: bool, y: int) -> bool: def test_shortcircuit_assign4(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> bool: if y > 0 or (z := x): return False diff --git a/tests/integration/test_basic.py b/tests/integration/test_basic.py index 487f0197..a7cffc99 100644 --- a/tests/integration/test_basic.py +++ b/tests/integration/test_basic.py @@ -4,7 +4,7 @@ def test_id(validate): - @guppy + @guppy(compile=True) def identity(x: int) -> int: return x @@ -12,7 +12,7 @@ def identity(x: int) -> int: def test_void(validate): - @guppy + @guppy(compile=True) def void() -> None: return @@ -20,7 +20,7 @@ def void() -> None: def test_copy(validate): - @guppy + @guppy(compile=True) def copy(x: int) -> (int, int): return x, x @@ -28,7 +28,7 @@ def copy(x: int) -> (int, int): def test_discard(validate): - @guppy + @guppy(compile=True) def discard(x: int) -> None: return @@ -36,7 +36,7 @@ def discard(x: int) -> None: def test_implicit_return(validate): - @guppy + @guppy(compile=True) def ret() -> None: pass @@ -44,7 +44,7 @@ def ret() -> None: def test_assign(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> bool: y = x return y @@ -53,7 +53,7 @@ def foo(x: bool) -> bool: def test_assign_expr(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> bool: (y := x) return y @@ -62,7 +62,7 @@ def foo(x: bool) -> bool: def test_func_def_name(): - @guppy + @guppy(compile=True) def func_name() -> None: return diff --git a/tests/integration/test_call.py b/tests/integration/test_call.py index 2cb7ec80..63cfc954 100644 --- a/tests/integration/test_call.py +++ b/tests/integration/test_call.py @@ -31,7 +31,7 @@ def bar(x: int) -> int: def test_recursion(validate): - @guppy + @guppy(compile=True) def main(x: int) -> int: return main(x) diff --git a/tests/integration/test_functional.py b/tests/integration/test_functional.py index ae61a30d..2955b897 100644 --- a/tests/integration/test_functional.py +++ b/tests/integration/test_functional.py @@ -6,7 +6,7 @@ @pytest.mark.skip() def test_if_no_else(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: _ @ functional if x: @@ -18,7 +18,7 @@ def foo(x: bool, y: int) -> int: @pytest.mark.skip() def test_if_else(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: _ @ functional if x: @@ -32,7 +32,7 @@ def foo(x: bool, y: int) -> int: @pytest.mark.skip() def test_if_elif(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: _ @ functional if x: @@ -46,7 +46,7 @@ def foo(x: bool, y: int) -> int: @pytest.mark.skip() def test_if_elif_else(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: _ @ functional if x: @@ -62,7 +62,7 @@ def foo(x: bool, y: int) -> int: @pytest.mark.skip() def test_infinite_loop(validate): - @guppy + @guppy(compile=True) def foo() -> int: while True: pass @@ -73,7 +73,7 @@ def foo() -> int: @pytest.mark.skip() def test_counting_loop(validate): - @guppy + @guppy(compile=True) def foo(i: int) -> int: while i > 0: i -= 1 @@ -84,7 +84,7 @@ def foo(i: int) -> int: @pytest.mark.skip() def test_nested_loop(validate): - @guppy + @guppy(compile=True) def foo(x: int, y: int) -> int: p = 0 _ @ functional diff --git a/tests/integration/test_higher_order.py b/tests/integration/test_higher_order.py index fd8856d8..80e2ead3 100644 --- a/tests/integration/test_higher_order.py +++ b/tests/integration/test_higher_order.py @@ -55,7 +55,7 @@ def baz(y: int) -> None: def test_nested(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> Callable[[int], bool]: def bar(y: int) -> bool: return x > y diff --git a/tests/integration/test_if.py b/tests/integration/test_if.py index ac4f5f10..69f6938b 100644 --- a/tests/integration/test_if.py +++ b/tests/integration/test_if.py @@ -4,7 +4,7 @@ def test_if_no_else(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: if x: y += 1 @@ -14,7 +14,7 @@ def foo(x: bool, y: int) -> int: def test_if_else(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: if x: y += 1 @@ -26,7 +26,7 @@ def foo(x: bool, y: int) -> int: def test_if_elif(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: if x: y += 1 @@ -38,7 +38,7 @@ def foo(x: bool, y: int) -> int: def test_if_elif_else(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: if x: y += 1 @@ -52,7 +52,7 @@ def foo(x: bool, y: int) -> int: def test_if_expr(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: return y + 1 if x else 42 @@ -60,7 +60,7 @@ def foo(x: bool, y: int) -> int: def test_if_expr_nested(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: a = y + 1 if x else y * y if 0 < y <= 10 else 42 b = a if a < 5 or (not x and -7 >= a > 42) else -a @@ -70,7 +70,7 @@ def foo(x: bool, y: int) -> int: def test_if_expr_tuple(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> (int, int, int): t = (y + 1 if x else 42), 8, (y * 2 if x else 64) return t @@ -79,7 +79,7 @@ def foo(x: bool, y: int) -> (int, int, int): def test_if_expr_assign_both(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: (z := 5) if x else (z := 42) return z @@ -88,7 +88,7 @@ def foo(x: bool) -> int: def test_if_expr_assign_cond(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> bool: return z if (z := x) else False @@ -96,7 +96,7 @@ def foo(x: bool) -> bool: def test_if_expr_reassign(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: y = 5 (y := 1) if x else 6 @@ -108,7 +108,7 @@ def foo(x: bool) -> int: def test_if_expr_reassign_cond(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: y = 5 return y if (y := 42) > 5 else 64 if x else y @@ -117,7 +117,7 @@ def foo(x: bool) -> int: def test_if_expr_double_type_change(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: y = 4 (y := 1) if (y := x) else (y := 6) @@ -127,7 +127,7 @@ def foo(x: bool) -> int: def test_if_return(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: if x: return y @@ -138,7 +138,7 @@ def foo(x: bool, y: int) -> int: def test_else_return(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: if x: y += 3 @@ -151,7 +151,7 @@ def foo(x: bool, y: int) -> int: def test_both_return(validate): - @guppy + @guppy(compile=True) def foo(x: bool, y: int) -> int: if x: y += 3 @@ -164,7 +164,7 @@ def foo(x: bool, y: int) -> int: def test_nested_return(validate): - @guppy + @guppy(compile=True) def foo(x: int, y: int) -> int: if x > 5: if y == 4: @@ -177,7 +177,7 @@ def foo(x: int, y: int) -> int: def test_return_defined1(validate): - @guppy + @guppy(compile=True) def foo(x: int, y: int) -> int: if x > 5: return y @@ -189,7 +189,7 @@ def foo(x: int, y: int) -> int: def test_return_defined2(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: if x > 5: z = 45 @@ -201,7 +201,7 @@ def foo(x: int) -> int: def test_break_different_types1(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: z = 0 while True: @@ -217,7 +217,7 @@ def foo(x: int) -> int: def test_break_different_types2(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: z = 0 while True: @@ -234,7 +234,7 @@ def foo(x: int) -> int: @pytest.mark.skip("Known bug") def test_continue_different_types1(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: z = 0 while True: @@ -251,7 +251,7 @@ def foo(x: int) -> int: @pytest.mark.skip("Known bug") def test_continue_different_types2(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: z = 0 while True: diff --git a/tests/integration/test_nested.py b/tests/integration/test_nested.py index 23698f59..fe0892e8 100644 --- a/tests/integration/test_nested.py +++ b/tests/integration/test_nested.py @@ -2,7 +2,7 @@ def test_basic(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: def bar(y: int) -> int: return y @@ -13,7 +13,7 @@ def bar(y: int) -> int: def test_call_twice(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: def bar(y: int) -> int: return y + 3 @@ -27,7 +27,7 @@ def bar(y: int) -> int: def test_redefine(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: def bar(y: int) -> int: return y + 3 @@ -44,7 +44,7 @@ def bar(y: int) -> int: def test_define_twice(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: if x == 0: @@ -61,7 +61,7 @@ def bar(y: int) -> int: def test_nested_deep(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: def bar(y: int) -> int: def baz(z: int) -> int: @@ -75,7 +75,7 @@ def baz(z: int) -> int: def test_recurse(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: def bar(y: int) -> int: if y == 0: @@ -88,7 +88,7 @@ def bar(y: int) -> int: def test_capture_arg(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: def bar() -> int: return 1 + x @@ -99,7 +99,7 @@ def bar() -> int: def test_capture_assigned(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: y = x + 1 @@ -112,7 +112,7 @@ def bar() -> int: def test_capture_multiple(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: if x > 5: y = 3 @@ -130,7 +130,7 @@ def bar() -> int: def test_capture_cfg(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: a = x + 4 if x > 5: @@ -146,7 +146,7 @@ def bar() -> int: def test_capture_deep(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: a = x * 2 @@ -165,7 +165,7 @@ def baz(y: int) -> int: def test_capture_recurse(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: def bar(y: int, z: int) -> int: if y == 0: @@ -178,7 +178,7 @@ def bar(y: int, z: int) -> int: def test_capture_recurse_nested(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: def bar(y: int, z: int) -> int: if y == 0: @@ -197,7 +197,7 @@ def baz() -> int: def test_capture_while(validate): - @guppy + @guppy(compile=True) def foo(x: int) -> int: a = 0 while x > 0: diff --git a/tests/integration/test_programs.py b/tests/integration/test_programs.py index ee7c87cc..345c2d20 100644 --- a/tests/integration/test_programs.py +++ b/tests/integration/test_programs.py @@ -3,7 +3,7 @@ def test_factorial(validate): - @guppy + @guppy(compile=True) def factorial1(x: int) -> int: acc = 1 while x > 0: @@ -11,13 +11,13 @@ def factorial1(x: int) -> int: x -= 1 return acc - @guppy + @guppy(compile=True) def factorial2(x: int) -> int: if x == 0: return 1 return factorial2(x - 1) * x - @guppy + @guppy(compile=True) def factorial3(x: int, acc: int) -> int: if x == 0: return acc diff --git a/tests/integration/test_py.py b/tests/integration/test_py.py index 2e896aee..ced0e07f 100644 --- a/tests/integration/test_py.py +++ b/tests/integration/test_py.py @@ -5,7 +5,7 @@ def test_basic(validate): x = 42 - @guppy + @guppy(compile=True) def foo() -> int: return py(x + 1) @@ -13,7 +13,7 @@ def foo() -> int: def test_builtin(validate): - @guppy + @guppy(compile=True) def foo() -> int: return py(len({"a": 1337, "b": None})) @@ -23,7 +23,7 @@ def foo() -> int: def test_if(validate): b = True - @guppy + @guppy(compile=True) def foo() -> int: if py(b or 1 > 6): return 0 @@ -35,7 +35,7 @@ def foo() -> int: def test_redeclare_after(validate): x = 1 - @guppy + @guppy(compile=True) def foo() -> int: return py(x) @@ -45,7 +45,7 @@ def foo() -> int: def test_tuple(validate): - @guppy + @guppy(compile=True) def foo() -> int: x, y = py((1, False)) return x @@ -54,7 +54,7 @@ def foo() -> int: def test_tuple_implicit(validate): - @guppy + @guppy(compile=True) def foo() -> int: x, y = py(1, False) return x diff --git a/tests/integration/test_unused.py b/tests/integration/test_unused.py index b8592bc4..a62a506e 100644 --- a/tests/integration/test_unused.py +++ b/tests/integration/test_unused.py @@ -4,7 +4,7 @@ def test_not_always_defined1(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: if x: z = 5 @@ -14,7 +14,7 @@ def foo(x: bool) -> int: def test_not_always_defined2(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: if x: pass @@ -26,7 +26,7 @@ def foo(x: bool) -> int: def test_not_always_defined3(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: if x: y = True @@ -38,7 +38,7 @@ def foo(x: bool) -> int: def test_different_types1(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: if x: z = True @@ -50,7 +50,7 @@ def foo(x: bool) -> int: def test_different_types2(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: z = False if x: @@ -63,7 +63,7 @@ def foo(x: bool) -> int: def test_different_types3(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> int: z = False if x: @@ -76,7 +76,7 @@ def foo(x: bool) -> int: def test_while_change_type(validate): - @guppy + @guppy(compile=True) def foo() -> None: x = 42 while True: @@ -86,7 +86,7 @@ def foo() -> None: def test_if_expr_different_types(validate): - @guppy + @guppy(compile=True) def foo(x: bool) -> None: 5 if x else False diff --git a/tests/integration/test_while.py b/tests/integration/test_while.py index 28d20dc0..6a5ec06b 100644 --- a/tests/integration/test_while.py +++ b/tests/integration/test_while.py @@ -2,7 +2,7 @@ def test_infinite_loop(validate): - @guppy + @guppy(compile=True) def foo() -> int: while True: pass @@ -12,7 +12,7 @@ def foo() -> int: def test_counting_loop(validate): - @guppy + @guppy(compile=True) def foo(i: int) -> int: while i > 0: i -= 1 @@ -22,7 +22,7 @@ def foo(i: int) -> int: def test_break(validate): - @guppy + @guppy(compile=True) def foo(i: int) -> int: while True: if i == 0: @@ -34,7 +34,7 @@ def foo(i: int) -> int: def test_continue(validate): - @guppy + @guppy(compile=True) def foo(i: int) -> int: x = 42 while True: @@ -47,7 +47,7 @@ def foo(i: int) -> int: def test_return_in_loop(validate): - @guppy + @guppy(compile=True) def foo(i: int) -> int: x = 42 while i > 0: @@ -61,7 +61,7 @@ def foo(i: int) -> int: def test_nested_loop(validate): - @guppy + @guppy(compile=True) def foo(x: int, y: int) -> int: p = 0 while x > 0: @@ -77,7 +77,7 @@ def foo(x: int, y: int) -> int: def test_nested_loop_break_continue(validate): - @guppy + @guppy(compile=True) def foo(x: int, y: int) -> int: p = 0 while x > 0: From a40fed50c99f572a68a7e6f1aeafd65894bf4124 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Mon, 15 Jan 2024 20:14:59 +0000 Subject: [PATCH 03/14] fix mypy --- guppy/decorator.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/guppy/decorator.py b/guppy/decorator.py index a2ef1dac..c38e0ae4 100644 --- a/guppy/decorator.py +++ b/guppy/decorator.py @@ -20,7 +20,7 @@ from guppy.hugr.hugr import Hugr from guppy.module import GuppyModule, PyFunc, parse_py_func -FuncDecorator = Callable[[PyFunc], PyFunc] +FuncDecorator = Callable[[PyFunc], PyFunc | Hugr] CustomFuncDecorator = Callable[[PyFunc], CustomFunction] ClassDecorator = Callable[[type], type] @@ -71,7 +71,8 @@ def __call__( if arg is not None and not isinstance(arg, GuppyModule): # Decorator used without any arguments. f = arg - return self.__call__(None)(f) + decorator: FuncDecorator = self.__call__(None) # type: ignore[assignment] + return decorator(f) def make_dummy(wraps: PyFunc) -> Callable[..., Any]: @functools.wraps(wraps) @@ -84,17 +85,19 @@ def dummy(*args: Any, **kwargs: Any) -> Any: if arg is None and compile: # No module passed, and compile option is set. - def dec(f: Callable[..., Any]) -> Callable[..., Any]: + def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: module = GuppyModule("module") module.register_func_def(f) - return module.compile() + compiled = module.compile() + assert compiled is not None + return compiled return dec if arg is None and not compile: # No module specified, and `compile` option is not set. # We use a module associate with the caller of the decorator. - def dec(f: Callable[..., Any]) -> Callable[..., Any]: + def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: caller = self._get_python_caller() if caller not in self._modules: self._modules[caller] = GuppyModule(caller.name) @@ -107,7 +110,7 @@ def dec(f: Callable[..., Any]) -> Callable[..., Any]: if isinstance(arg, GuppyModule): # Module passed. Ignore `compile` option. - def dec(f: Callable[..., Any]) -> Callable[..., Any]: + def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: arg.register_func_def(f) return make_dummy(f) From 12ec3f98fbce748d53d083fc44b3051f740b78b1 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Tue, 16 Jan 2024 13:39:20 +0000 Subject: [PATCH 04/14] review comments --- guppy/decorator.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/guppy/decorator.py b/guppy/decorator.py index c38e0ae4..b41f0a72 100644 --- a/guppy/decorator.py +++ b/guppy/decorator.py @@ -25,7 +25,7 @@ ClassDecorator = Callable[[type], type] -@dataclass +@dataclass(frozen=True) class CallerIdentifier: """Identifier for the interpreter frame that called the decorator.""" @@ -38,18 +38,20 @@ def name(self) -> str: If the called is not a function, uses the file name. """ - if self.function == "": - return self.filename.name - return self.function - - def __hash__(self) -> int: - return hash((self.filename, self.function)) + module_name = inspect.getmodulename(self.filename) + if self.function != "": + return self.function + if module_name is not None: + return module_name + return self.filename.name class _Guppy: """Class for the `@guppy` decorator.""" # The currently-alive modules, associated with an element in the call stack. + # + # Only contains **uncompiled** modules. _modules: dict[CallerIdentifier, GuppyModule] def __init__(self) -> None: @@ -275,9 +277,7 @@ def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule | None: id = self._get_python_caller() if id not in self._modules: return None - module = self._modules[id] - del self._modules[id] - return module + return self._modules.pop(id) def compile(self, id: CallerIdentifier | None = None) -> Hugr | None: """Compiles the local module into a Hugr.""" From 4e521411318f0e50606a4863800d4e29ae18e36a Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 13:10:31 +0000 Subject: [PATCH 05/14] Move `compile=True` decorator to a test util. Update tests --- guppylang/decorator.py | 31 +++---------- guppylang/hugr/__init__.py | 5 ++ .../illegal_short_circuit.err | 2 +- .../illegal_short_circuit.py | 4 +- .../comprehension_errors/illegal_ternary.err | 2 +- .../comprehension_errors/illegal_ternary.py | 4 +- .../comprehension_errors/illegal_walrus.err | 2 +- .../comprehension_errors/illegal_walrus.py | 4 +- .../error/errors_on_usage/and_not_defined.py | 4 +- .../errors_on_usage/else_expr_not_defined.py | 4 +- .../errors_on_usage/else_expr_type_change.py | 4 +- .../error/errors_on_usage/else_not_defined.py | 4 +- .../else_not_defined_functional.py | 2 +- .../error/errors_on_usage/else_type_change.py | 4 +- .../else_type_change_functional.py | 2 +- tests/error/errors_on_usage/for_new_var.py | 4 +- tests/error/errors_on_usage/for_target.py | 4 +- .../errors_on_usage/for_target_type_change.py | 4 +- .../error/errors_on_usage/for_type_change.py | 4 +- .../errors_on_usage/if_different_types.py | 4 +- .../if_different_types_functional.py | 2 +- .../if_expr_cond_type_change.py | 4 +- .../errors_on_usage/if_expr_not_defined.py | 4 +- .../errors_on_usage/if_expr_type_change.py | 4 +- .../errors_on_usage/if_expr_type_conflict.err | 2 +- .../errors_on_usage/if_expr_type_conflict.py | 4 +- tests/error/errors_on_usage/if_not_defined.py | 4 +- .../if_not_defined_functional.py | 2 +- tests/error/errors_on_usage/if_type_change.py | 4 +- .../if_type_change_functional.py | 2 +- tests/error/errors_on_usage/or_not_defined.py | 4 +- tests/error/errors_on_usage/while_new_var.py | 4 +- .../while_new_var_functional.py | 2 +- .../errors_on_usage/while_type_change.py | 4 +- .../while_type_change_functional.py | 2 +- tests/error/misc_errors/arg_not_annotated.err | 2 +- tests/error/misc_errors/arg_not_annotated.py | 4 +- tests/error/misc_errors/functional_break.py | 2 +- .../error/misc_errors/functional_continue.py | 2 +- tests/error/misc_errors/functional_return.py | 2 +- tests/error/misc_errors/nested_functional.py | 2 +- tests/error/misc_errors/no_return.err | 2 +- tests/error/misc_errors/no_return.py | 4 +- .../misc_errors/return_not_annotated.err | 2 +- .../error/misc_errors/return_not_annotated.py | 4 +- .../return_not_annotated_none1.err | 2 +- .../misc_errors/return_not_annotated_none1.py | 4 +- .../return_not_annotated_none2.err | 2 +- .../misc_errors/return_not_annotated_none2.py | 4 +- tests/error/misc_errors/undefined_var.err | 2 +- tests/error/misc_errors/undefined_var.py | 4 +- tests/error/misc_errors/unreachable_1.py | 4 +- tests/error/misc_errors/unreachable_2.py | 4 +- tests/error/misc_errors/unreachable_3.py | 4 +- tests/error/misc_errors/unreachable_4.py | 4 +- tests/error/misc_errors/unreachable_5.py | 4 +- .../error/nested_errors/different_types_if.py | 4 +- tests/error/nested_errors/not_defined_if.py | 4 +- .../error/nested_errors/reassign_capture_1.py | 4 +- .../error/nested_errors/reassign_capture_2.py | 4 +- .../error/nested_errors/reassign_capture_3.py | 4 +- tests/error/nested_errors/var_not_defined.py | 4 +- tests/error/py_errors/guppy_name1.err | 2 +- tests/error/py_errors/guppy_name1.py | 4 +- tests/error/py_errors/guppy_name2.err | 2 +- tests/error/py_errors/guppy_name2.py | 4 +- tests/error/py_errors/no_args.err | 2 +- tests/error/py_errors/no_args.py | 4 +- tests/error/py_errors/python_err.err | 2 +- tests/error/py_errors/python_err.py | 4 +- tests/error/py_errors/unsupported.err | 2 +- tests/error/py_errors/unsupported.py | 4 +- .../type_errors/binary_not_arith_left.err | 2 +- .../type_errors/binary_not_arith_left.py | 4 +- .../type_errors/binary_not_arith_right.err | 2 +- .../type_errors/binary_not_arith_right.py | 4 +- tests/error/type_errors/call_missing_arg.err | 2 +- tests/error/type_errors/call_missing_arg.py | 4 +- tests/error/type_errors/call_not_function.err | 2 +- tests/error/type_errors/call_not_function.py | 4 +- .../error/type_errors/call_unexpected_arg.err | 2 +- .../error/type_errors/call_unexpected_arg.py | 4 +- tests/error/type_errors/call_wrong_arg.err | 2 +- tests/error/type_errors/call_wrong_arg.py | 4 +- tests/error/type_errors/fun_ty_mismatch_1.py | 4 +- tests/error/type_errors/fun_ty_mismatch_2.py | 4 +- tests/error/type_errors/fun_ty_mismatch_3.py | 4 +- .../type_errors/if_not_bool_functional.py | 2 +- tests/error/type_errors/invert_not_int.err | 2 +- tests/error/type_errors/invert_not_int.py | 4 +- tests/error/type_errors/return_mismatch.err | 2 +- tests/error/type_errors/return_mismatch.py | 4 +- tests/error/type_errors/unary_not_arith.err | 2 +- tests/error/type_errors/unary_not_arith.py | 4 +- tests/error/type_errors/unpack_not_enough.err | 2 +- tests/error/type_errors/unpack_not_enough.py | 4 +- tests/error/type_errors/unpack_too_many.err | 2 +- tests/error/type_errors/unpack_too_many.py | 4 +- .../type_errors/while_not_bool_functional.py | 2 +- tests/error/util.py | 2 +- tests/integration/test_arithmetic.py | 20 ++++---- tests/integration/test_basic.py | 17 +++---- tests/integration/test_call.py | 3 +- tests/integration/test_comprehension.py | 19 ++++---- tests/integration/test_for.py | 21 +++++---- tests/integration/test_functional.py | 15 +++--- tests/integration/test_higher_order.py | 3 +- tests/integration/test_if.py | 46 +++++++++---------- tests/integration/test_list.py | 12 ++--- tests/integration/test_nested.py | 30 ++++++------ tests/integration/test_programs.py | 7 +-- tests/integration/test_py.py | 13 +++--- tests/integration/test_unused.py | 17 +++---- tests/integration/test_while.py | 15 +++--- tests/util.py | 18 ++++++++ 115 files changed, 310 insertions(+), 294 deletions(-) create mode 100644 tests/util.py diff --git a/guppylang/decorator.py b/guppylang/decorator.py index 143abfb2..f6ab2c7f 100644 --- a/guppylang/decorator.py +++ b/guppylang/decorator.py @@ -58,9 +58,7 @@ def __init__(self) -> None: self._modules = {} @pretty_errors - def __call__( - self, arg: PyFunc | GuppyModule | None = None, *, compile: bool = False - ) -> Hugr | None | FuncDecorator: + def __call__(self, arg: PyFunc | GuppyModule) -> None | FuncDecorator: """Decorator to annotate Python functions as Guppy code. Optionally, the `GuppyModule` in which the function should be placed can @@ -70,11 +68,6 @@ def __call__( function is compiled immediately as an standalone module and the Hugr is returned. """ - if arg is not None and not isinstance(arg, GuppyModule): - # Decorator used without any arguments. - f = arg - decorator: FuncDecorator = self.__call__(None) # type: ignore[assignment] - return decorator(f) def make_dummy(wraps: PyFunc) -> Callable[..., Any]: @functools.wraps(wraps) @@ -85,20 +78,11 @@ def dummy(*args: Any, **kwargs: Any) -> Any: return dummy - if arg is None and compile: - # No module passed, and compile option is set. - def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: - module = GuppyModule("module") - module.register_func_def(f) - compiled = module.compile() - assert compiled is not None - return compiled - - return dec + if not isinstance(arg, GuppyModule): + # Decorator used without any arguments. + # We default to a module associated with the caller of the decorator. + f = arg - if arg is None and not compile: - # No module specified, and `compile` option is not set. - # We use a module associate with the caller of the decorator. def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: caller = self._get_python_caller() if caller not in self._modules: @@ -107,11 +91,10 @@ def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: module.register_func_def(f) return make_dummy(f) - return dec + return dec(f) if isinstance(arg, GuppyModule): - # Module passed. Ignore `compile` option. - + # Module passed. def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: arg.register_func_def(f) return make_dummy(f) diff --git a/guppylang/hugr/__init__.py b/guppylang/hugr/__init__.py index e69de29b..0f6535c5 100644 --- a/guppylang/hugr/__init__.py +++ b/guppylang/hugr/__init__.py @@ -0,0 +1,5 @@ +"""Python definitions for the Hierarchical Unified Graph Representation.""" + +from .hugr import Hugr + +__all__ = ["Hugr"] diff --git a/tests/error/comprehension_errors/illegal_short_circuit.err b/tests/error/comprehension_errors/illegal_short_circuit.err index 6c8bfb78..d05dc6a8 100644 --- a/tests/error/comprehension_errors/illegal_short_circuit.err +++ b/tests/error/comprehension_errors/illegal_short_circuit.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @compile_guppy 5: def foo(xs: list[int]) -> None: 6: [x for x in xs if x < 5 and x != 6] ^^^^^^^^^^^^^^^^ diff --git a/tests/error/comprehension_errors/illegal_short_circuit.py b/tests/error/comprehension_errors/illegal_short_circuit.py index f54d5209..103d72f5 100644 --- a/tests/error/comprehension_errors/illegal_short_circuit.py +++ b/tests/error/comprehension_errors/illegal_short_circuit.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy +@compile_guppy def foo(xs: list[int]) -> None: [x for x in xs if x < 5 and x != 6] diff --git a/tests/error/comprehension_errors/illegal_ternary.err b/tests/error/comprehension_errors/illegal_ternary.err index b7e9e7a9..d99720ac 100644 --- a/tests/error/comprehension_errors/illegal_ternary.err +++ b/tests/error/comprehension_errors/illegal_ternary.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @compile_guppy 5: def foo(xs: list[int], ys: list[int], b: bool) -> None: 6: [x for x in (xs if b else ys)] ^^^^^^^^^^^^^^^ diff --git a/tests/error/comprehension_errors/illegal_ternary.py b/tests/error/comprehension_errors/illegal_ternary.py index 7c1a7715..d3136514 100644 --- a/tests/error/comprehension_errors/illegal_ternary.py +++ b/tests/error/comprehension_errors/illegal_ternary.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy +@compile_guppy def foo(xs: list[int], ys: list[int], b: bool) -> None: [x for x in (xs if b else ys)] diff --git a/tests/error/comprehension_errors/illegal_walrus.err b/tests/error/comprehension_errors/illegal_walrus.err index 2fbb77d7..4b19d4ba 100644 --- a/tests/error/comprehension_errors/illegal_walrus.err +++ b/tests/error/comprehension_errors/illegal_walrus.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy +4: @compile_guppy 5: def foo(xs: list[int]) -> None: 6: [y := x for x in xs] ^^^^^^ diff --git a/tests/error/comprehension_errors/illegal_walrus.py b/tests/error/comprehension_errors/illegal_walrus.py index cf252b96..ea168ab2 100644 --- a/tests/error/comprehension_errors/illegal_walrus.py +++ b/tests/error/comprehension_errors/illegal_walrus.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy +@compile_guppy def foo(xs: list[int]) -> None: [y := x for x in xs] diff --git a/tests/error/errors_on_usage/and_not_defined.py b/tests/error/errors_on_usage/and_not_defined.py index 5fa5c9dc..ebe2a498 100644 --- a/tests/error/errors_on_usage/and_not_defined.py +++ b/tests/error/errors_on_usage/and_not_defined.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool, y: int) -> int: if x and (z := y + 1): return z diff --git a/tests/error/errors_on_usage/else_expr_not_defined.py b/tests/error/errors_on_usage/else_expr_not_defined.py index b3fb80d8..c348a85e 100644 --- a/tests/error/errors_on_usage/else_expr_not_defined.py +++ b/tests/error/errors_on_usage/else_expr_not_defined.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: (y := 1) if x else (z := 2) return z diff --git a/tests/error/errors_on_usage/else_expr_type_change.py b/tests/error/errors_on_usage/else_expr_type_change.py index ab03bff0..0c93cae7 100644 --- a/tests/error/errors_on_usage/else_expr_type_change.py +++ b/tests/error/errors_on_usage/else_expr_type_change.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: y = 3 (y := y + 1) if x else (y := True) diff --git a/tests/error/errors_on_usage/else_not_defined.py b/tests/error/errors_on_usage/else_not_defined.py index de4e31d6..0c48ba75 100644 --- a/tests/error/errors_on_usage/else_not_defined.py +++ b/tests/error/errors_on_usage/else_not_defined.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: if x: y = 1 diff --git a/tests/error/errors_on_usage/else_not_defined_functional.py b/tests/error/errors_on_usage/else_not_defined_functional.py index 3f4a08dc..e3aae879 100644 --- a/tests/error/errors_on_usage/else_not_defined_functional.py +++ b/tests/error/errors_on_usage/else_not_defined_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: _@functional if x: diff --git a/tests/error/errors_on_usage/else_type_change.py b/tests/error/errors_on_usage/else_type_change.py index d506f4af..e1623f32 100644 --- a/tests/error/errors_on_usage/else_type_change.py +++ b/tests/error/errors_on_usage/else_type_change.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: y = 3 if x: diff --git a/tests/error/errors_on_usage/else_type_change_functional.py b/tests/error/errors_on_usage/else_type_change_functional.py index 561225f1..5f96b5ca 100644 --- a/tests/error/errors_on_usage/else_type_change_functional.py +++ b/tests/error/errors_on_usage/else_type_change_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: y = 3 _@functional diff --git a/tests/error/errors_on_usage/for_new_var.py b/tests/error/errors_on_usage/for_new_var.py index f3c29ab1..42d4d917 100644 --- a/tests/error/errors_on_usage/for_new_var.py +++ b/tests/error/errors_on_usage/for_new_var.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy +@compile_guppy def foo(xs: list[int]) -> int: for _ in xs: y = 5 diff --git a/tests/error/errors_on_usage/for_target.py b/tests/error/errors_on_usage/for_target.py index b2876dc2..cfca2ee1 100644 --- a/tests/error/errors_on_usage/for_target.py +++ b/tests/error/errors_on_usage/for_target.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy +@compile_guppy def foo(xs: list[int]) -> int: for x in xs: pass diff --git a/tests/error/errors_on_usage/for_target_type_change.py b/tests/error/errors_on_usage/for_target_type_change.py index 4f5f3b08..90af80d6 100644 --- a/tests/error/errors_on_usage/for_target_type_change.py +++ b/tests/error/errors_on_usage/for_target_type_change.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy +@compile_guppy def foo(xs: list[bool]) -> int: x = 5 for x in xs: diff --git a/tests/error/errors_on_usage/for_type_change.py b/tests/error/errors_on_usage/for_type_change.py index e4be618d..c12a5d59 100644 --- a/tests/error/errors_on_usage/for_type_change.py +++ b/tests/error/errors_on_usage/for_type_change.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy +@compile_guppy def foo(xs: list[int]) -> int: y = 5 for x in xs: diff --git a/tests/error/errors_on_usage/if_different_types.py b/tests/error/errors_on_usage/if_different_types.py index 15a31700..4723e9d0 100644 --- a/tests/error/errors_on_usage/if_different_types.py +++ b/tests/error/errors_on_usage/if_different_types.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: if x: y = 1 diff --git a/tests/error/errors_on_usage/if_different_types_functional.py b/tests/error/errors_on_usage/if_different_types_functional.py index 50e523a7..0b364870 100644 --- a/tests/error/errors_on_usage/if_different_types_functional.py +++ b/tests/error/errors_on_usage/if_different_types_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: _@functional if x: diff --git a/tests/error/errors_on_usage/if_expr_cond_type_change.py b/tests/error/errors_on_usage/if_expr_cond_type_change.py index 6d6102c4..809999a4 100644 --- a/tests/error/errors_on_usage/if_expr_cond_type_change.py +++ b/tests/error/errors_on_usage/if_expr_cond_type_change.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: y = 4 0 if (y := x) else (y := 6) diff --git a/tests/error/errors_on_usage/if_expr_not_defined.py b/tests/error/errors_on_usage/if_expr_not_defined.py index 079b6937..570ef5a7 100644 --- a/tests/error/errors_on_usage/if_expr_not_defined.py +++ b/tests/error/errors_on_usage/if_expr_not_defined.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: (y := 1) if x else 0 return y diff --git a/tests/error/errors_on_usage/if_expr_type_change.py b/tests/error/errors_on_usage/if_expr_type_change.py index afeff682..65b5132b 100644 --- a/tests/error/errors_on_usage/if_expr_type_change.py +++ b/tests/error/errors_on_usage/if_expr_type_change.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool, a: int) -> int: y = 3 (y := False) if x or a > 5 else 0 diff --git a/tests/error/errors_on_usage/if_expr_type_conflict.err b/tests/error/errors_on_usage/if_expr_type_conflict.err index 98b2f422..239b9059 100644 --- a/tests/error/errors_on_usage/if_expr_type_conflict.err +++ b/tests/error/errors_on_usage/if_expr_type_conflict.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo(x: bool) -> None: 6: y = True if x else 42 ^^^^^^^^^^^^^^^^^ diff --git a/tests/error/errors_on_usage/if_expr_type_conflict.py b/tests/error/errors_on_usage/if_expr_type_conflict.py index 1b4d1a43..9dfec99a 100644 --- a/tests/error/errors_on_usage/if_expr_type_conflict.py +++ b/tests/error/errors_on_usage/if_expr_type_conflict.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> None: y = True if x else 42 diff --git a/tests/error/errors_on_usage/if_not_defined.py b/tests/error/errors_on_usage/if_not_defined.py index d30c958c..11dd7e99 100644 --- a/tests/error/errors_on_usage/if_not_defined.py +++ b/tests/error/errors_on_usage/if_not_defined.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: if x: y = 1 diff --git a/tests/error/errors_on_usage/if_not_defined_functional.py b/tests/error/errors_on_usage/if_not_defined_functional.py index ad03eb70..a3ff1a46 100644 --- a/tests/error/errors_on_usage/if_not_defined_functional.py +++ b/tests/error/errors_on_usage/if_not_defined_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: _@functional if x: diff --git a/tests/error/errors_on_usage/if_type_change.py b/tests/error/errors_on_usage/if_type_change.py index 43d92e22..9a1c8928 100644 --- a/tests/error/errors_on_usage/if_type_change.py +++ b/tests/error/errors_on_usage/if_type_change.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: y = 3 if x: diff --git a/tests/error/errors_on_usage/if_type_change_functional.py b/tests/error/errors_on_usage/if_type_change_functional.py index 6bb2ee6e..9bb0a814 100644 --- a/tests/error/errors_on_usage/if_type_change_functional.py +++ b/tests/error/errors_on_usage/if_type_change_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: y = 3 _@functional diff --git a/tests/error/errors_on_usage/or_not_defined.py b/tests/error/errors_on_usage/or_not_defined.py index 03a6c7b9..4e6d4283 100644 --- a/tests/error/errors_on_usage/or_not_defined.py +++ b/tests/error/errors_on_usage/or_not_defined.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool, y: int) -> int: if x or (z := y + 1): return z diff --git a/tests/error/errors_on_usage/while_new_var.py b/tests/error/errors_on_usage/while_new_var.py index 9e2096f7..1d230852 100644 --- a/tests/error/errors_on_usage/while_new_var.py +++ b/tests/error/errors_on_usage/while_new_var.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: while x: y = 5 diff --git a/tests/error/errors_on_usage/while_new_var_functional.py b/tests/error/errors_on_usage/while_new_var_functional.py index fff1d570..33604b36 100644 --- a/tests/error/errors_on_usage/while_new_var_functional.py +++ b/tests/error/errors_on_usage/while_new_var_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/errors_on_usage/while_type_change.py b/tests/error/errors_on_usage/while_type_change.py index 93a7dc26..4086422c 100644 --- a/tests/error/errors_on_usage/while_type_change.py +++ b/tests/error/errors_on_usage/while_type_change.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: y = 5 while x: diff --git a/tests/error/errors_on_usage/while_type_change_functional.py b/tests/error/errors_on_usage/while_type_change_functional.py index 4450c8ad..fcc3c302 100644 --- a/tests/error/errors_on_usage/while_type_change_functional.py +++ b/tests/error/errors_on_usage/while_type_change_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: y = 5 _@functional diff --git a/tests/error/misc_errors/arg_not_annotated.err b/tests/error/misc_errors/arg_not_annotated.err index 5b588fda..0e680b48 100644 --- a/tests/error/misc_errors/arg_not_annotated.err +++ b/tests/error/misc_errors/arg_not_annotated.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:5 -3: @guppy(compile=True) +3: @compile_guppy 4: def foo(x: bool, y) -> int: ^ GuppyError: Argument type must be annotated diff --git a/tests/error/misc_errors/arg_not_annotated.py b/tests/error/misc_errors/arg_not_annotated.py index 3a099936..608a1c01 100644 --- a/tests/error/misc_errors/arg_not_annotated.py +++ b/tests/error/misc_errors/arg_not_annotated.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool, y) -> int: return y diff --git a/tests/error/misc_errors/functional_break.py b/tests/error/misc_errors/functional_break.py index 93564ecf..3dd1b6d5 100644 --- a/tests/error/misc_errors/functional_break.py +++ b/tests/error/misc_errors/functional_break.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/misc_errors/functional_continue.py b/tests/error/misc_errors/functional_continue.py index 78f4c675..8e5f04d4 100644 --- a/tests/error/misc_errors/functional_continue.py +++ b/tests/error/misc_errors/functional_continue.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/misc_errors/functional_return.py b/tests/error/misc_errors/functional_return.py index d4b5da94..835a3afe 100644 --- a/tests/error/misc_errors/functional_return.py +++ b/tests/error/misc_errors/functional_return.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/misc_errors/nested_functional.py b/tests/error/misc_errors/nested_functional.py index 4399e488..0008dc0d 100644 --- a/tests/error/misc_errors/nested_functional.py +++ b/tests/error/misc_errors/nested_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: _@functional while x: diff --git a/tests/error/misc_errors/no_return.err b/tests/error/misc_errors/no_return.err index 36693946..676e2bf1 100644 --- a/tests/error/misc_errors/no_return.err +++ b/tests/error/misc_errors/no_return.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> int: 6: pass ^^^^ diff --git a/tests/error/misc_errors/no_return.py b/tests/error/misc_errors/no_return.py index e08cdacb..3c853d95 100644 --- a/tests/error/misc_errors/no_return.py +++ b/tests/error/misc_errors/no_return.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: pass diff --git a/tests/error/misc_errors/return_not_annotated.err b/tests/error/misc_errors/return_not_annotated.err index 35e9e27f..e66c67e0 100644 --- a/tests/error/misc_errors/return_not_annotated.err +++ b/tests/error/misc_errors/return_not_annotated.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:5 -3: @guppy(compile=True) +3: @compile_guppy 4: def foo(x: bool): ^^^^^^^^^^^^^^^^^ GuppyError: Return type must be annotated diff --git a/tests/error/misc_errors/return_not_annotated.py b/tests/error/misc_errors/return_not_annotated.py index e76085d8..fd0389f9 100644 --- a/tests/error/misc_errors/return_not_annotated.py +++ b/tests/error/misc_errors/return_not_annotated.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool): return x diff --git a/tests/error/misc_errors/return_not_annotated_none1.err b/tests/error/misc_errors/return_not_annotated_none1.err index fc8ab7e9..2798749f 100644 --- a/tests/error/misc_errors/return_not_annotated_none1.err +++ b/tests/error/misc_errors/return_not_annotated_none1.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:5 -3: @guppy(compile=True) +3: @compile_guppy 4: def foo(): ^^^^^^^^^^ GuppyError: Return type must be annotated. Try adding a `-> None` annotation. diff --git a/tests/error/misc_errors/return_not_annotated_none1.py b/tests/error/misc_errors/return_not_annotated_none1.py index 74daa3ec..29f10063 100644 --- a/tests/error/misc_errors/return_not_annotated_none1.py +++ b/tests/error/misc_errors/return_not_annotated_none1.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(): return diff --git a/tests/error/misc_errors/return_not_annotated_none2.err b/tests/error/misc_errors/return_not_annotated_none2.err index fc8ab7e9..2798749f 100644 --- a/tests/error/misc_errors/return_not_annotated_none2.err +++ b/tests/error/misc_errors/return_not_annotated_none2.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:5 -3: @guppy(compile=True) +3: @compile_guppy 4: def foo(): ^^^^^^^^^^ GuppyError: Return type must be annotated. Try adding a `-> None` annotation. diff --git a/tests/error/misc_errors/return_not_annotated_none2.py b/tests/error/misc_errors/return_not_annotated_none2.py index 51571cfe..861342b8 100644 --- a/tests/error/misc_errors/return_not_annotated_none2.py +++ b/tests/error/misc_errors/return_not_annotated_none2.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(): def bar(x: int) -> int: return x diff --git a/tests/error/misc_errors/undefined_var.err b/tests/error/misc_errors/undefined_var.err index 12c99cfd..d5cf6925 100644 --- a/tests/error/misc_errors/undefined_var.err +++ b/tests/error/misc_errors/undefined_var.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> int: 6: return x ^ diff --git a/tests/error/misc_errors/undefined_var.py b/tests/error/misc_errors/undefined_var.py index 46bfbb06..753bd4ed 100644 --- a/tests/error/misc_errors/undefined_var.py +++ b/tests/error/misc_errors/undefined_var.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: return x diff --git a/tests/error/misc_errors/unreachable_1.py b/tests/error/misc_errors/unreachable_1.py index 00653c9f..2a2c264b 100644 --- a/tests/error/misc_errors/unreachable_1.py +++ b/tests/error/misc_errors/unreachable_1.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: return 0 x = 42 diff --git a/tests/error/misc_errors/unreachable_2.py b/tests/error/misc_errors/unreachable_2.py index 9826262e..6a4a2750 100644 --- a/tests/error/misc_errors/unreachable_2.py +++ b/tests/error/misc_errors/unreachable_2.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: if x: return 4 diff --git a/tests/error/misc_errors/unreachable_3.py b/tests/error/misc_errors/unreachable_3.py index a2c50eef..f14290eb 100644 --- a/tests/error/misc_errors/unreachable_3.py +++ b/tests/error/misc_errors/unreachable_3.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: while x: break diff --git a/tests/error/misc_errors/unreachable_4.py b/tests/error/misc_errors/unreachable_4.py index 0fb2f6e3..10b9fac3 100644 --- a/tests/error/misc_errors/unreachable_4.py +++ b/tests/error/misc_errors/unreachable_4.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: while x: continue diff --git a/tests/error/misc_errors/unreachable_5.py b/tests/error/misc_errors/unreachable_5.py index 56e26d03..7875e472 100644 --- a/tests/error/misc_errors/unreachable_5.py +++ b/tests/error/misc_errors/unreachable_5.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: bool) -> int: while x: return 42 diff --git a/tests/error/nested_errors/different_types_if.py b/tests/error/nested_errors/different_types_if.py index c5e653df..2dcd722e 100644 --- a/tests/error/nested_errors/different_types_if.py +++ b/tests/error/nested_errors/different_types_if.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(b: bool) -> int: if b: def bar() -> int: diff --git a/tests/error/nested_errors/not_defined_if.py b/tests/error/nested_errors/not_defined_if.py index 131dc577..fe9f9a4f 100644 --- a/tests/error/nested_errors/not_defined_if.py +++ b/tests/error/nested_errors/not_defined_if.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(b: bool) -> int: if b: def bar() -> int: diff --git a/tests/error/nested_errors/reassign_capture_1.py b/tests/error/nested_errors/reassign_capture_1.py index 9a6bb21e..78d60ec2 100644 --- a/tests/error/nested_errors/reassign_capture_1.py +++ b/tests/error/nested_errors/reassign_capture_1.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: y = x + 1 diff --git a/tests/error/nested_errors/reassign_capture_2.py b/tests/error/nested_errors/reassign_capture_2.py index 9a05f977..70f83748 100644 --- a/tests/error/nested_errors/reassign_capture_2.py +++ b/tests/error/nested_errors/reassign_capture_2.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: y = x + 1 diff --git a/tests/error/nested_errors/reassign_capture_3.py b/tests/error/nested_errors/reassign_capture_3.py index 197ea695..0a597a42 100644 --- a/tests/error/nested_errors/reassign_capture_3.py +++ b/tests/error/nested_errors/reassign_capture_3.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: y = x + 1 diff --git a/tests/error/nested_errors/var_not_defined.py b/tests/error/nested_errors/var_not_defined.py index 48efc3ae..0fb7e3fb 100644 --- a/tests/error/nested_errors/var_not_defined.py +++ b/tests/error/nested_errors/var_not_defined.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: def bar() -> int: return x diff --git a/tests/error/py_errors/guppy_name1.err b/tests/error/py_errors/guppy_name1.err index 2699fd77..1b8d8b62 100644 --- a/tests/error/py_errors/guppy_name1.err +++ b/tests/error/py_errors/guppy_name1.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo(x: int) -> int: 6: return py(x + 1) ^ diff --git a/tests/error/py_errors/guppy_name1.py b/tests/error/py_errors/guppy_name1.py index 13bd3ccd..87994b92 100644 --- a/tests/error/py_errors/guppy_name1.py +++ b/tests/error/py_errors/guppy_name1.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: return py(x + 1) diff --git a/tests/error/py_errors/guppy_name2.err b/tests/error/py_errors/guppy_name2.err index 10dc8e38..73d2d298 100644 --- a/tests/error/py_errors/guppy_name2.err +++ b/tests/error/py_errors/guppy_name2.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:9 -7: @guppy(compile=True) +7: @compile_guppy 8: def foo(x: int) -> int: 9: return py(x + 1) ^ diff --git a/tests/error/py_errors/guppy_name2.py b/tests/error/py_errors/guppy_name2.py index e1ffe9aa..6558c20f 100644 --- a/tests/error/py_errors/guppy_name2.py +++ b/tests/error/py_errors/guppy_name2.py @@ -1,9 +1,9 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy x = 42 -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: return py(x + 1) diff --git a/tests/error/py_errors/no_args.err b/tests/error/py_errors/no_args.err index 28b70b9e..7c30ee04 100644 --- a/tests/error/py_errors/no_args.err +++ b/tests/error/py_errors/no_args.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> int: 6: return py() ^^^^ diff --git a/tests/error/py_errors/no_args.py b/tests/error/py_errors/no_args.py index 1e38fb5f..074479e8 100644 --- a/tests/error/py_errors/no_args.py +++ b/tests/error/py_errors/no_args.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: return py() diff --git a/tests/error/py_errors/python_err.err b/tests/error/py_errors/python_err.err index 85f2ff66..5d21c3e8 100644 --- a/tests/error/py_errors/python_err.err +++ b/tests/error/py_errors/python_err.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> int: 6: return py(1 / 0) ^^^^^^^^^ diff --git a/tests/error/py_errors/python_err.py b/tests/error/py_errors/python_err.py index 42b631d3..68b874d3 100644 --- a/tests/error/py_errors/python_err.py +++ b/tests/error/py_errors/python_err.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: return py(1 / 0) diff --git a/tests/error/py_errors/unsupported.err b/tests/error/py_errors/unsupported.err index d9310150..4de7be8c 100644 --- a/tests/error/py_errors/unsupported.err +++ b/tests/error/py_errors/unsupported.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> int: 6: return py({1, 2, 3}) ^^^^^^^^^^^^^ diff --git a/tests/error/py_errors/unsupported.py b/tests/error/py_errors/unsupported.py index a7d9c918..08c0daeb 100644 --- a/tests/error/py_errors/unsupported.py +++ b/tests/error/py_errors/unsupported.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: return py({1, 2, 3}) diff --git a/tests/error/type_errors/binary_not_arith_left.err b/tests/error/type_errors/binary_not_arith_left.err index bbac107a..36bb9a57 100644 --- a/tests/error/type_errors/binary_not_arith_left.err +++ b/tests/error/type_errors/binary_not_arith_left.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo(x: int) -> int: 6: return (1, 1) * 4 ^^^^^^^^^^ diff --git a/tests/error/type_errors/binary_not_arith_left.py b/tests/error/type_errors/binary_not_arith_left.py index 8bc6761d..0fddfc17 100644 --- a/tests/error/type_errors/binary_not_arith_left.py +++ b/tests/error/type_errors/binary_not_arith_left.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: return (1, 1) * 4 diff --git a/tests/error/type_errors/binary_not_arith_right.err b/tests/error/type_errors/binary_not_arith_right.err index 08ff77a7..7bd8ce2d 100644 --- a/tests/error/type_errors/binary_not_arith_right.err +++ b/tests/error/type_errors/binary_not_arith_right.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo(x: int) -> int: 6: return x + True ^^^^^^^^ diff --git a/tests/error/type_errors/binary_not_arith_right.py b/tests/error/type_errors/binary_not_arith_right.py index 5b07a409..7222dba3 100644 --- a/tests/error/type_errors/binary_not_arith_right.py +++ b/tests/error/type_errors/binary_not_arith_right.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: return x + True diff --git a/tests/error/type_errors/call_missing_arg.err b/tests/error/type_errors/call_missing_arg.err index 7efbe771..9562fd5a 100644 --- a/tests/error/type_errors/call_missing_arg.err +++ b/tests/error/type_errors/call_missing_arg.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo(x: int) -> int: 6: return foo() ^^^^^ diff --git a/tests/error/type_errors/call_missing_arg.py b/tests/error/type_errors/call_missing_arg.py index 7cabd523..301afc4c 100644 --- a/tests/error/type_errors/call_missing_arg.py +++ b/tests/error/type_errors/call_missing_arg.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: return foo() diff --git a/tests/error/type_errors/call_not_function.err b/tests/error/type_errors/call_not_function.err index e0a31066..f04efe2b 100644 --- a/tests/error/type_errors/call_not_function.err +++ b/tests/error/type_errors/call_not_function.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo(x: int) -> int: 6: return x(42) ^ diff --git a/tests/error/type_errors/call_not_function.py b/tests/error/type_errors/call_not_function.py index 9cda081c..cb912bfe 100644 --- a/tests/error/type_errors/call_not_function.py +++ b/tests/error/type_errors/call_not_function.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: return x(42) diff --git a/tests/error/type_errors/call_unexpected_arg.err b/tests/error/type_errors/call_unexpected_arg.err index 38d4685e..8fe6436d 100644 --- a/tests/error/type_errors/call_unexpected_arg.err +++ b/tests/error/type_errors/call_unexpected_arg.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo(x: int) -> int: 6: return foo(x, x) ^ diff --git a/tests/error/type_errors/call_unexpected_arg.py b/tests/error/type_errors/call_unexpected_arg.py index e2d0977a..99c901ff 100644 --- a/tests/error/type_errors/call_unexpected_arg.py +++ b/tests/error/type_errors/call_unexpected_arg.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: return foo(x, x) diff --git a/tests/error/type_errors/call_wrong_arg.err b/tests/error/type_errors/call_wrong_arg.err index 30a2f122..8642b137 100644 --- a/tests/error/type_errors/call_wrong_arg.err +++ b/tests/error/type_errors/call_wrong_arg.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo(x: int) -> int: 6: return foo(True) ^^^^ diff --git a/tests/error/type_errors/call_wrong_arg.py b/tests/error/type_errors/call_wrong_arg.py index db8504bb..ab9b98ee 100644 --- a/tests/error/type_errors/call_wrong_arg.py +++ b/tests/error/type_errors/call_wrong_arg.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: return foo(True) diff --git a/tests/error/type_errors/fun_ty_mismatch_1.py b/tests/error/type_errors/fun_ty_mismatch_1.py index cffa16bf..d7e956b8 100644 --- a/tests/error/type_errors/fun_ty_mismatch_1.py +++ b/tests/error/type_errors/fun_ty_mismatch_1.py @@ -1,9 +1,9 @@ from collections.abc import Callable -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> Callable[[int], int]: def bar(x: int) -> bool: return x > 0 diff --git a/tests/error/type_errors/fun_ty_mismatch_2.py b/tests/error/type_errors/fun_ty_mismatch_2.py index 35313a85..fc3af13e 100644 --- a/tests/error/type_errors/fun_ty_mismatch_2.py +++ b/tests/error/type_errors/fun_ty_mismatch_2.py @@ -1,9 +1,9 @@ from collections.abc import Callable -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: def bar(f: Callable[[], int]) -> int: return f() diff --git a/tests/error/type_errors/fun_ty_mismatch_3.py b/tests/error/type_errors/fun_ty_mismatch_3.py index e6dd23a6..e9dc0b48 100644 --- a/tests/error/type_errors/fun_ty_mismatch_3.py +++ b/tests/error/type_errors/fun_ty_mismatch_3.py @@ -1,9 +1,9 @@ from collections.abc import Callable -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo(x: int) -> int: def bar(f: Callable[[int], bool]) -> bool: return f(42) diff --git a/tests/error/type_errors/if_not_bool_functional.py b/tests/error/type_errors/if_not_bool_functional.py index bab50ace..0b240fab 100644 --- a/tests/error/type_errors/if_not_bool_functional.py +++ b/tests/error/type_errors/if_not_bool_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: _@functional if 42: diff --git a/tests/error/type_errors/invert_not_int.err b/tests/error/type_errors/invert_not_int.err index e3317d5c..16524a1f 100644 --- a/tests/error/type_errors/invert_not_int.err +++ b/tests/error/type_errors/invert_not_int.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> int: 6: return ~True ^^^^ diff --git a/tests/error/type_errors/invert_not_int.py b/tests/error/type_errors/invert_not_int.py index a348bf1f..39399e81 100644 --- a/tests/error/type_errors/invert_not_int.py +++ b/tests/error/type_errors/invert_not_int.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: return ~True diff --git a/tests/error/type_errors/return_mismatch.err b/tests/error/type_errors/return_mismatch.err index 0f6dfa97..0d9a0605 100644 --- a/tests/error/type_errors/return_mismatch.err +++ b/tests/error/type_errors/return_mismatch.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> bool: 6: return 42 ^^ diff --git a/tests/error/type_errors/return_mismatch.py b/tests/error/type_errors/return_mismatch.py index 65af0e99..9328972e 100644 --- a/tests/error/type_errors/return_mismatch.py +++ b/tests/error/type_errors/return_mismatch.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> bool: return 42 diff --git a/tests/error/type_errors/unary_not_arith.err b/tests/error/type_errors/unary_not_arith.err index f7c7daa7..ae82206b 100644 --- a/tests/error/type_errors/unary_not_arith.err +++ b/tests/error/type_errors/unary_not_arith.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> int: 6: return -True ^^^^ diff --git a/tests/error/type_errors/unary_not_arith.py b/tests/error/type_errors/unary_not_arith.py index 9813943a..bf9ce2cb 100644 --- a/tests/error/type_errors/unary_not_arith.py +++ b/tests/error/type_errors/unary_not_arith.py @@ -1,6 +1,6 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: return -True diff --git a/tests/error/type_errors/unpack_not_enough.err b/tests/error/type_errors/unpack_not_enough.err index a1330755..d9523c30 100644 --- a/tests/error/type_errors/unpack_not_enough.err +++ b/tests/error/type_errors/unpack_not_enough.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> int: 6: a, b, c = 1, True ^^^^^^^^^^^^^^^^^ diff --git a/tests/error/type_errors/unpack_not_enough.py b/tests/error/type_errors/unpack_not_enough.py index 792cb634..389b9fd9 100644 --- a/tests/error/type_errors/unpack_not_enough.py +++ b/tests/error/type_errors/unpack_not_enough.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: a, b, c = 1, True return a diff --git a/tests/error/type_errors/unpack_too_many.err b/tests/error/type_errors/unpack_too_many.err index 9590a2f4..44ffb60f 100644 --- a/tests/error/type_errors/unpack_too_many.err +++ b/tests/error/type_errors/unpack_too_many.err @@ -1,6 +1,6 @@ Guppy compilation failed. Error in file $FILE:6 -4: @guppy(compile=True) +4: @compile_guppy 5: def foo() -> int: 6: a, b = 1, True, 3.0 ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/error/type_errors/unpack_too_many.py b/tests/error/type_errors/unpack_too_many.py index 472aa000..b252cf7d 100644 --- a/tests/error/type_errors/unpack_too_many.py +++ b/tests/error/type_errors/unpack_too_many.py @@ -1,7 +1,7 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: a, b = 1, True, 3.0 return a diff --git a/tests/error/type_errors/while_not_bool_functional.py b/tests/error/type_errors/while_not_bool_functional.py index 4c74b1b2..78c66c40 100644 --- a/tests/error/type_errors/while_not_bool_functional.py +++ b/tests/error/type_errors/while_not_bool_functional.py @@ -1,7 +1,7 @@ from guppylang.decorator import guppy -@guppy(compile=True) +@compile_guppy def foo() -> int: _@functional while 42: diff --git a/tests/error/util.py b/tests/error/util.py index 821aa2f4..88c3182c 100644 --- a/tests/error/util.py +++ b/tests/error/util.py @@ -26,7 +26,7 @@ def run_error_test(file, capsys): exp_err = f.read() exp_err = exp_err.replace("$FILE", str(file)) - assert err == exp_err + assert err == exp_err, f"Expected error '{err}', but got '{exp_err}'." util = GuppyModule("test") diff --git a/tests/integration/test_arithmetic.py b/tests/integration/test_arithmetic.py index 7eeda1b9..a31db662 100644 --- a/tests/integration/test_arithmetic.py +++ b/tests/integration/test_arithmetic.py @@ -1,8 +1,8 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy def test_arith_basic(validate): - @guppy(compile=True) + @compile_guppy def add(x: int, y: int) -> int: return x + y @@ -10,7 +10,7 @@ def add(x: int, y: int) -> int: def test_constant(validate): - @guppy(compile=True) + @compile_guppy def const() -> float: return 42.0 @@ -18,7 +18,7 @@ def const() -> float: def test_aug_assign(validate): - @guppy(compile=True) + @compile_guppy def add(x: int) -> int: x += 1 return x @@ -27,7 +27,7 @@ def add(x: int) -> int: def test_float_coercion(validate): - @guppy(compile=True) + @compile_guppy def coerce(x: int, y: float) -> float: return x * y @@ -35,7 +35,7 @@ def coerce(x: int, y: float) -> float: def test_arith_big(validate): - @guppy(compile=True) + @compile_guppy def arith(x: int, y: float, z: int) -> bool: a = x // y + 3 * z b = -8 >= a > 5 or (x * y == 0 and a % 3 < x) @@ -45,7 +45,7 @@ def arith(x: int, y: float, z: int) -> bool: def test_shortcircuit_assign1(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> bool: if (z := x) and y > 0: return z @@ -55,7 +55,7 @@ def foo(x: bool, y: int) -> bool: def test_shortcircuit_assign2(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> bool: if y > 0 and (z := x): return z @@ -65,7 +65,7 @@ def foo(x: bool, y: int) -> bool: def test_shortcircuit_assign3(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> bool: if (z := x) or y > 0: return z @@ -75,7 +75,7 @@ def foo(x: bool, y: int) -> bool: def test_shortcircuit_assign4(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> bool: if y > 0 or (z := x): return False diff --git a/tests/integration/test_basic.py b/tests/integration/test_basic.py index 7bcb48cc..bb57695e 100644 --- a/tests/integration/test_basic.py +++ b/tests/integration/test_basic.py @@ -1,10 +1,11 @@ from guppylang.decorator import guppy from guppylang.hugr import ops from guppylang.module import GuppyModule +from tests.util import compile_guppy def test_id(validate): - @guppy(compile=True) + @compile_guppy def identity(x: int) -> int: return x @@ -12,7 +13,7 @@ def identity(x: int) -> int: def test_void(validate): - @guppy(compile=True) + @compile_guppy def void() -> None: return @@ -20,7 +21,7 @@ def void() -> None: def test_copy(validate): - @guppy(compile=True) + @compile_guppy def copy(x: int) -> (int, int): return x, x @@ -28,7 +29,7 @@ def copy(x: int) -> (int, int): def test_discard(validate): - @guppy(compile=True) + @compile_guppy def discard(x: int) -> None: return @@ -36,7 +37,7 @@ def discard(x: int) -> None: def test_implicit_return(validate): - @guppy(compile=True) + @compile_guppy def ret() -> None: pass @@ -44,7 +45,7 @@ def ret() -> None: def test_assign(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> bool: y = x return y @@ -53,7 +54,7 @@ def foo(x: bool) -> bool: def test_assign_expr(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> bool: (y := x) return y @@ -62,7 +63,7 @@ def foo(x: bool) -> bool: def test_func_def_name(): - @guppy(compile=True) + @compile_guppy def func_name() -> None: return diff --git a/tests/integration/test_call.py b/tests/integration/test_call.py index eee02085..01a520c9 100644 --- a/tests/integration/test_call.py +++ b/tests/integration/test_call.py @@ -1,5 +1,6 @@ from guppylang.decorator import guppy from guppylang.module import GuppyModule +from tests.util import compile_guppy def test_call(validate): @@ -31,7 +32,7 @@ def bar(x: int) -> int: def test_recursion(validate): - @guppy(compile=True) + @compile_guppy def main(x: int) -> int: return main(x) diff --git a/tests/integration/test_comprehension.py b/tests/integration/test_comprehension.py index 3b5c0774..76da7749 100644 --- a/tests/integration/test_comprehension.py +++ b/tests/integration/test_comprehension.py @@ -5,10 +5,11 @@ from guppylang.prelude.quantum import Qubit, h, cx import guppylang.prelude.quantum as quantum +from tests.util import compile_guppy def test_basic(validate): - @guppy + @compile_guppy def test(xs: list[float]) -> list[int]: return [int(x) for x in xs] @@ -27,7 +28,7 @@ def test(qs: linst[Qubit]) -> linst[Qubit]: def test_guarded(validate): - @guppy + @compile_guppy def test(xs: list[int]) -> list[int]: return [2 * x for x in xs if x > 0 if x < 20] @@ -35,7 +36,7 @@ def test(xs: list[int]) -> list[int]: def test_multiple(validate): - @guppy + @compile_guppy def test(xs: list[int], ys: list[int]) -> list[int]: return [x + y for x in xs for y in ys if x + y > 42] @@ -43,7 +44,7 @@ def test(xs: list[int], ys: list[int]) -> list[int]: def test_tuple_pat(validate): - @guppy + @compile_guppy def test(xs: list[tuple[int, int, float]]) -> list[float]: return [x + y * z for x, y, z in xs if x - y > z] @@ -62,7 +63,7 @@ def test(qs: linst[tuple[int, Qubit, Qubit]]) -> linst[tuple[Qubit, Qubit]]: def test_tuple_return(validate): - @guppy + @compile_guppy def test(xs: list[int], ys: list[float]) -> list[tuple[int, float]]: return [(x, y) for x in xs for y in ys] @@ -84,7 +85,7 @@ def test(xs: list[float]) -> list[float]: def test_capture(validate): - @guppy + @compile_guppy def test(xs: list[int], y: int) -> list[int]: return [x + y for x in xs if x > y] @@ -92,7 +93,7 @@ def test(xs: list[int], y: int) -> list[int]: def test_scope(validate): - @guppy + @compile_guppy def test(xs: list[None]) -> float: x = 42.0 [x for x in xs] @@ -102,7 +103,7 @@ def test(xs: list[None]) -> float: def test_nested_left(validate): - @guppy + @compile_guppy def test(xs: list[int], ys: list[float]) -> list[list[float]]: return [[x + y for y in ys] for x in xs] @@ -110,7 +111,7 @@ def test(xs: list[int], ys: list[float]) -> list[list[float]]: def test_nested_right(validate): - @guppy + @compile_guppy def test(xs: list[int]) -> list[int]: return [-x for x in [2 * x for x in xs]] diff --git a/tests/integration/test_for.py b/tests/integration/test_for.py index 08a26e96..57a9f750 100644 --- a/tests/integration/test_for.py +++ b/tests/integration/test_for.py @@ -1,8 +1,9 @@ from guppylang.decorator import guppy +from tests.util import compile_guppy def test_basic(validate): - @guppy + @compile_guppy def foo(xs: list[int]) -> int: for x in xs: pass @@ -12,7 +13,7 @@ def foo(xs: list[int]) -> int: def test_counting_loop(validate): - @guppy + @compile_guppy def foo(xs: list[int]) -> int: s = 0 for x in xs: @@ -23,7 +24,7 @@ def foo(xs: list[int]) -> int: def test_multi_targets(validate): - @guppy + @compile_guppy def foo(xs: list[tuple[int, float]]) -> float: s = 0.0 for x, y in xs: @@ -34,7 +35,7 @@ def foo(xs: list[tuple[int, float]]) -> float: def test_multi_targets_same(validate): - @guppy + @compile_guppy def foo(xs: list[tuple[int, float]]) -> float: s = 1.0 for x, x in xs: @@ -45,7 +46,7 @@ def foo(xs: list[tuple[int, float]]) -> float: def test_reassign_iter(validate): - @guppy + @compile_guppy def foo(xs: list[int]) -> int: s = 1 for x in xs: @@ -57,7 +58,7 @@ def foo(xs: list[int]) -> int: def test_break(validate): - @guppy + @compile_guppy def foo(xs: list[int]) -> int: i = 1 for x in xs: @@ -70,7 +71,7 @@ def foo(xs: list[int]) -> int: def test_continue(validate): - @guppy + @compile_guppy def foo(xs: list[int]) -> int: i = len(xs) for x in xs: @@ -83,7 +84,7 @@ def foo(xs: list[int]) -> int: def test_return_in_loop(validate): - @guppy + @compile_guppy def foo(xs: list[int]) -> int: y = 42 for x in xs: @@ -96,7 +97,7 @@ def foo(xs: list[int]) -> int: def test_nested_loop(validate): - @guppy + @compile_guppy def foo(xs: list[int], ys: list[int]) -> int: p = 0 for x in xs: @@ -110,7 +111,7 @@ def foo(xs: list[int], ys: list[int]) -> int: def test_nested_loop_break_continue(validate): - @guppy + @compile_guppy def foo(xs: list[int], ys: list[int]) -> int: p = 0 for x in xs: diff --git a/tests/integration/test_functional.py b/tests/integration/test_functional.py index d0c90d70..7f994e4a 100644 --- a/tests/integration/test_functional.py +++ b/tests/integration/test_functional.py @@ -2,11 +2,12 @@ from guppylang.decorator import guppy from tests.integration.util import functional, _ +from tests.util import compile_guppy @pytest.mark.skip() def test_if_no_else(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: _ @ functional if x: @@ -18,7 +19,7 @@ def foo(x: bool, y: int) -> int: @pytest.mark.skip() def test_if_else(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: _ @ functional if x: @@ -32,7 +33,7 @@ def foo(x: bool, y: int) -> int: @pytest.mark.skip() def test_if_elif(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: _ @ functional if x: @@ -46,7 +47,7 @@ def foo(x: bool, y: int) -> int: @pytest.mark.skip() def test_if_elif_else(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: _ @ functional if x: @@ -62,7 +63,7 @@ def foo(x: bool, y: int) -> int: @pytest.mark.skip() def test_infinite_loop(validate): - @guppy(compile=True) + @compile_guppy def foo() -> int: while True: pass @@ -73,7 +74,7 @@ def foo() -> int: @pytest.mark.skip() def test_counting_loop(validate): - @guppy(compile=True) + @compile_guppy def foo(i: int) -> int: while i > 0: i -= 1 @@ -84,7 +85,7 @@ def foo(i: int) -> int: @pytest.mark.skip() def test_nested_loop(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int, y: int) -> int: p = 0 _ @ functional diff --git a/tests/integration/test_higher_order.py b/tests/integration/test_higher_order.py index 3fa857a4..94de2b31 100644 --- a/tests/integration/test_higher_order.py +++ b/tests/integration/test_higher_order.py @@ -2,6 +2,7 @@ from guppylang.decorator import guppy from guppylang.module import GuppyModule +from tests.util import compile_guppy def test_basic(validate): @@ -55,7 +56,7 @@ def baz(y: int) -> None: def test_nested(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> Callable[[int], bool]: def bar(y: int) -> bool: return x > y diff --git a/tests/integration/test_if.py b/tests/integration/test_if.py index 4a7752a7..67dfb7be 100644 --- a/tests/integration/test_if.py +++ b/tests/integration/test_if.py @@ -1,10 +1,10 @@ import pytest -from guppylang.decorator import guppy +from tests.util import compile_guppy def test_if_no_else(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: if x: y += 1 @@ -14,7 +14,7 @@ def foo(x: bool, y: int) -> int: def test_if_else(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: if x: y += 1 @@ -26,7 +26,7 @@ def foo(x: bool, y: int) -> int: def test_if_elif(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: if x: y += 1 @@ -38,7 +38,7 @@ def foo(x: bool, y: int) -> int: def test_if_elif_else(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: if x: y += 1 @@ -52,7 +52,7 @@ def foo(x: bool, y: int) -> int: def test_if_expr(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: return y + 1 if x else 42 @@ -60,7 +60,7 @@ def foo(x: bool, y: int) -> int: def test_if_expr_nested(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: a = y + 1 if x else y * y if 0 < y <= 10 else 42 b = a if a < 5 or (not x and -7 >= a > 42) else -a @@ -70,7 +70,7 @@ def foo(x: bool, y: int) -> int: def test_if_expr_tuple(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> (int, int, int): t = (y + 1 if x else 42), 8, (y * 2 if x else 64) return t @@ -79,7 +79,7 @@ def foo(x: bool, y: int) -> (int, int, int): def test_if_expr_assign_both(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: (z := 5) if x else (z := 42) return z @@ -88,7 +88,7 @@ def foo(x: bool) -> int: def test_if_expr_assign_cond(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> bool: return z if (z := x) else False @@ -96,7 +96,7 @@ def foo(x: bool) -> bool: def test_if_expr_reassign(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: y = 5 (y := 1) if x else 6 @@ -108,7 +108,7 @@ def foo(x: bool) -> int: def test_if_expr_reassign_cond(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: y = 5 return y if (y := 42) > 5 else 64 if x else y @@ -117,7 +117,7 @@ def foo(x: bool) -> int: def test_if_expr_double_type_change(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: y = 4 (y := 1) if (y := x) else (y := 6) @@ -127,7 +127,7 @@ def foo(x: bool) -> int: def test_if_return(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: if x: return y @@ -138,7 +138,7 @@ def foo(x: bool, y: int) -> int: def test_else_return(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: if x: y += 3 @@ -151,7 +151,7 @@ def foo(x: bool, y: int) -> int: def test_both_return(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool, y: int) -> int: if x: y += 3 @@ -164,7 +164,7 @@ def foo(x: bool, y: int) -> int: def test_nested_return(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int, y: int) -> int: if x > 5: if y == 4: @@ -177,7 +177,7 @@ def foo(x: int, y: int) -> int: def test_return_defined1(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int, y: int) -> int: if x > 5: return y @@ -189,7 +189,7 @@ def foo(x: int, y: int) -> int: def test_return_defined2(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: if x > 5: z = 45 @@ -201,7 +201,7 @@ def foo(x: int) -> int: def test_break_different_types1(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: z = 0 while True: @@ -217,7 +217,7 @@ def foo(x: int) -> int: def test_break_different_types2(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: z = 0 while True: @@ -234,7 +234,7 @@ def foo(x: int) -> int: @pytest.mark.skip("Known bug") def test_continue_different_types1(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: z = 0 while True: @@ -251,7 +251,7 @@ def foo(x: int) -> int: @pytest.mark.skip("Known bug") def test_continue_different_types2(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: z = 0 while True: diff --git a/tests/integration/test_list.py b/tests/integration/test_list.py index 9bee4016..e90f1bfe 100644 --- a/tests/integration/test_list.py +++ b/tests/integration/test_list.py @@ -1,8 +1,8 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy def test_types(validate): - @guppy + @compile_guppy def test( xs: list[int], ys: list[tuple[int, float]] ) -> tuple[list[int], list[tuple[int, float]]]: @@ -12,7 +12,7 @@ def test( def test_len(validate): - @guppy + @compile_guppy def test(xs: list[int]) -> int: return len(xs) @@ -20,7 +20,7 @@ def test(xs: list[int]) -> int: def test_literal(validate): - @guppy + @compile_guppy def test(x: float) -> list[float]: return [1.0, 2.0, 3.0, 4.0 + x] @@ -28,7 +28,7 @@ def test(x: float) -> list[float]: def test_arith(validate): - @guppy + @compile_guppy def test(xs: list[int]) -> list[int]: xs += xs + [42] xs = 3 * xs @@ -38,7 +38,7 @@ def test(xs: list[int]) -> list[int]: def test_subscript(validate): - @guppy + @compile_guppy def test(xs: list[float], i: int) -> float: return xs[2 * i] diff --git a/tests/integration/test_nested.py b/tests/integration/test_nested.py index 9e445f84..aac788ba 100644 --- a/tests/integration/test_nested.py +++ b/tests/integration/test_nested.py @@ -1,8 +1,8 @@ -from guppylang.decorator import guppy +from tests.util import compile_guppy def test_basic(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: def bar(y: int) -> int: return y @@ -13,7 +13,7 @@ def bar(y: int) -> int: def test_call_twice(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: def bar(y: int) -> int: return y + 3 @@ -27,7 +27,7 @@ def bar(y: int) -> int: def test_redefine(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: def bar(y: int) -> int: return y + 3 @@ -44,7 +44,7 @@ def bar(y: int) -> int: def test_define_twice(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: if x == 0: @@ -61,7 +61,7 @@ def bar(y: int) -> int: def test_nested_deep(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: def bar(y: int) -> int: def baz(z: int) -> int: @@ -75,7 +75,7 @@ def baz(z: int) -> int: def test_recurse(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: def bar(y: int) -> int: if y == 0: @@ -88,7 +88,7 @@ def bar(y: int) -> int: def test_capture_arg(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: def bar() -> int: return 1 + x @@ -99,7 +99,7 @@ def bar() -> int: def test_capture_assigned(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: y = x + 1 @@ -112,7 +112,7 @@ def bar() -> int: def test_capture_multiple(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: if x > 5: y = 3 @@ -130,7 +130,7 @@ def bar() -> int: def test_capture_cfg(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: a = x + 4 if x > 5: @@ -146,7 +146,7 @@ def bar() -> int: def test_capture_deep(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: a = x * 2 @@ -165,7 +165,7 @@ def baz(y: int) -> int: def test_capture_recurse(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: def bar(y: int, z: int) -> int: if y == 0: @@ -178,7 +178,7 @@ def bar(y: int, z: int) -> int: def test_capture_recurse_nested(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: def bar(y: int, z: int) -> int: if y == 0: @@ -197,7 +197,7 @@ def baz() -> int: def test_capture_while(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int) -> int: a = 0 while x > 0: diff --git a/tests/integration/test_programs.py b/tests/integration/test_programs.py index 47caf96f..44c7968d 100644 --- a/tests/integration/test_programs.py +++ b/tests/integration/test_programs.py @@ -1,9 +1,10 @@ from guppylang.decorator import guppy from guppylang.module import GuppyModule +from tests.util import compile_guppy def test_factorial(validate): - @guppy(compile=True) + @compile_guppy def factorial1(x: int) -> int: acc = 1 while x > 0: @@ -11,13 +12,13 @@ def factorial1(x: int) -> int: x -= 1 return acc - @guppy(compile=True) + @compile_guppy def factorial2(x: int) -> int: if x == 0: return 1 return factorial2(x - 1) * x - @guppy(compile=True) + @compile_guppy def factorial3(x: int, acc: int) -> int: if x == 0: return acc diff --git a/tests/integration/test_py.py b/tests/integration/test_py.py index feaee3dc..ac983942 100644 --- a/tests/integration/test_py.py +++ b/tests/integration/test_py.py @@ -1,11 +1,12 @@ from guppylang.decorator import guppy from tests.integration.util import py +from tests.util import compile_guppy def test_basic(validate): x = 42 - @guppy(compile=True) + @compile_guppy def foo() -> int: return py(x + 1) @@ -13,7 +14,7 @@ def foo() -> int: def test_builtin(validate): - @guppy(compile=True) + @compile_guppy def foo() -> int: return py(len({"a": 1337, "b": None})) @@ -23,7 +24,7 @@ def foo() -> int: def test_if(validate): b = True - @guppy(compile=True) + @compile_guppy def foo() -> int: if py(b or 1 > 6): return 0 @@ -35,7 +36,7 @@ def foo() -> int: def test_redeclare_after(validate): x = 1 - @guppy(compile=True) + @compile_guppy def foo() -> int: return py(x) @@ -45,7 +46,7 @@ def foo() -> int: def test_tuple(validate): - @guppy(compile=True) + @compile_guppy def foo() -> int: x, y = py((1, False)) return x @@ -54,7 +55,7 @@ def foo() -> int: def test_tuple_implicit(validate): - @guppy(compile=True) + @compile_guppy def foo() -> int: x, y = py(1, False) return x diff --git a/tests/integration/test_unused.py b/tests/integration/test_unused.py index d16664ff..9c36aa80 100644 --- a/tests/integration/test_unused.py +++ b/tests/integration/test_unused.py @@ -1,10 +1,11 @@ """ All sorts of weird stuff is allowed when variables are not used. """ from guppylang.decorator import guppy +from tests.util import compile_guppy def test_not_always_defined1(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: if x: z = 5 @@ -14,7 +15,7 @@ def foo(x: bool) -> int: def test_not_always_defined2(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: if x: pass @@ -26,7 +27,7 @@ def foo(x: bool) -> int: def test_not_always_defined3(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: if x: y = True @@ -38,7 +39,7 @@ def foo(x: bool) -> int: def test_different_types1(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: if x: z = True @@ -50,7 +51,7 @@ def foo(x: bool) -> int: def test_different_types2(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: z = False if x: @@ -63,7 +64,7 @@ def foo(x: bool) -> int: def test_different_types3(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> int: z = False if x: @@ -76,7 +77,7 @@ def foo(x: bool) -> int: def test_while_change_type(validate): - @guppy(compile=True) + @compile_guppy def foo() -> None: x = 42 while True: @@ -86,7 +87,7 @@ def foo() -> None: def test_if_expr_different_types(validate): - @guppy(compile=True) + @compile_guppy def foo(x: bool) -> None: 5 if x else False diff --git a/tests/integration/test_while.py b/tests/integration/test_while.py index f7e21678..b97fbd61 100644 --- a/tests/integration/test_while.py +++ b/tests/integration/test_while.py @@ -1,8 +1,9 @@ from guppylang.decorator import guppy +from tests.util import compile_guppy def test_infinite_loop(validate): - @guppy(compile=True) + @compile_guppy def foo() -> int: while True: pass @@ -12,7 +13,7 @@ def foo() -> int: def test_counting_loop(validate): - @guppy(compile=True) + @compile_guppy def foo(i: int) -> int: while i > 0: i -= 1 @@ -22,7 +23,7 @@ def foo(i: int) -> int: def test_break(validate): - @guppy(compile=True) + @compile_guppy def foo(i: int) -> int: while True: if i == 0: @@ -34,7 +35,7 @@ def foo(i: int) -> int: def test_continue(validate): - @guppy(compile=True) + @compile_guppy def foo(i: int) -> int: x = 42 while True: @@ -47,7 +48,7 @@ def foo(i: int) -> int: def test_return_in_loop(validate): - @guppy(compile=True) + @compile_guppy def foo(i: int) -> int: x = 42 while i > 0: @@ -61,7 +62,7 @@ def foo(i: int) -> int: def test_nested_loop(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int, y: int) -> int: p = 0 while x > 0: @@ -77,7 +78,7 @@ def foo(x: int, y: int) -> int: def test_nested_loop_break_continue(validate): - @guppy(compile=True) + @compile_guppy def foo(x: int, y: int) -> int: p = 0 while x > 0: diff --git a/tests/util.py b/tests/util.py new file mode 100644 index 00000000..36cc3175 --- /dev/null +++ b/tests/util.py @@ -0,0 +1,18 @@ +import guppylang +from guppylang.hugr import Hugr +from guppylang.module import GuppyModule + + +def compile_guppy(fn) -> Hugr: + """A decorator that combines @guppy with HUGR compilation. + + Creates a temporary module that only contains the defined function. + """ + assert not isinstance( + fn, + GuppyModule, + ), "`@compile_guppy` does not support extra arguments." + + module = GuppyModule("module") + guppylang.decorator.guppy(module)(fn) + return module.compile() From 1213256b543f317510a3bff139ac507e3dc7f79f Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 13:16:24 +0000 Subject: [PATCH 06/14] fix lints --- tests/integration/test_for.py | 1 - tests/integration/test_functional.py | 1 - tests/integration/test_py.py | 1 - tests/integration/test_unused.py | 1 - tests/integration/test_while.py | 1 - 5 files changed, 5 deletions(-) diff --git a/tests/integration/test_for.py b/tests/integration/test_for.py index 57a9f750..0d82c357 100644 --- a/tests/integration/test_for.py +++ b/tests/integration/test_for.py @@ -1,4 +1,3 @@ -from guppylang.decorator import guppy from tests.util import compile_guppy diff --git a/tests/integration/test_functional.py b/tests/integration/test_functional.py index 7f994e4a..238a04b0 100644 --- a/tests/integration/test_functional.py +++ b/tests/integration/test_functional.py @@ -1,6 +1,5 @@ import pytest -from guppylang.decorator import guppy from tests.integration.util import functional, _ from tests.util import compile_guppy diff --git a/tests/integration/test_py.py b/tests/integration/test_py.py index ac983942..be3353ac 100644 --- a/tests/integration/test_py.py +++ b/tests/integration/test_py.py @@ -1,4 +1,3 @@ -from guppylang.decorator import guppy from tests.integration.util import py from tests.util import compile_guppy diff --git a/tests/integration/test_unused.py b/tests/integration/test_unused.py index 9c36aa80..f4b5b01f 100644 --- a/tests/integration/test_unused.py +++ b/tests/integration/test_unused.py @@ -1,6 +1,5 @@ """ All sorts of weird stuff is allowed when variables are not used. """ -from guppylang.decorator import guppy from tests.util import compile_guppy diff --git a/tests/integration/test_while.py b/tests/integration/test_while.py index b97fbd61..c351481a 100644 --- a/tests/integration/test_while.py +++ b/tests/integration/test_while.py @@ -1,4 +1,3 @@ -from guppylang.decorator import guppy from tests.util import compile_guppy From ad8b49ba82cedc57afa580b95e3a070c50bc4f32 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 13:16:38 +0000 Subject: [PATCH 07/14] Raise errors when compiling decorator without modules --- guppylang/decorator.py | 12 ++++++++---- guppylang/error.py | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/guppylang/decorator.py b/guppylang/decorator.py index f6ab2c7f..25bb9029 100644 --- a/guppylang/decorator.py +++ b/guppylang/decorator.py @@ -14,7 +14,7 @@ DefaultCallCompiler, OpCompiler, ) -from guppylang.error import GuppyError, pretty_errors +from guppylang.error import GuppyError, MissingModuleError, pretty_errors from guppylang.gtypes import GuppyType, TypeTransformer from guppylang.hugr import ops, tys from guppylang.hugr.hugr import Hugr @@ -258,17 +258,21 @@ def dummy(*args: Any, **kwargs: Any) -> Any: return dec - def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule | None: + def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule: """Returns the local GuppyModule, removing it from the local state.""" if id is None: id = self._get_python_caller() if id not in self._modules: - return None + err = f"Module {id.name} not found." if id else "No module found." + raise MissingModuleError(err) return self._modules.pop(id) - def compile(self, id: CallerIdentifier | None = None) -> Hugr | None: + def compile(self, id: CallerIdentifier | None = None) -> Hugr: """Compiles the local module into a Hugr.""" module = self.take_module(id) + if not module: + err = f"Module {id.name} not found." if id else "No module found." + raise MissingModuleError(err) return module.compile() if module else None def registered_modules(self) -> list[CallerIdentifier]: diff --git a/guppylang/error.py b/guppylang/error.py index 91c4d54f..8e8ae4bc 100644 --- a/guppylang/error.py +++ b/guppylang/error.py @@ -76,6 +76,10 @@ class GuppyTypeInferenceError(GuppyError): """Special Guppy exception for type inference errors.""" +class MissingModuleError(GuppyError): + """Special Guppy exception for operations that require a guppy module.""" + + class InternalGuppyError(Exception): """Exception for internal problems during compilation.""" From 816fb6d12b876a457e0cd53d6d4971a0e502acc3 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 13:18:02 +0000 Subject: [PATCH 08/14] s/guppy.compile/guppy.compile_module --- guppylang/decorator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guppylang/decorator.py b/guppylang/decorator.py index 25bb9029..0b833fdd 100644 --- a/guppylang/decorator.py +++ b/guppylang/decorator.py @@ -267,7 +267,7 @@ def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule: raise MissingModuleError(err) return self._modules.pop(id) - def compile(self, id: CallerIdentifier | None = None) -> Hugr: + def compile_module(self, id: CallerIdentifier | None = None) -> Hugr: """Compiles the local module into a Hugr.""" module = self.take_module(id) if not module: From 7d7690be9afd50cb4ee4217986a24ab7c51ec873 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 13:18:49 +0000 Subject: [PATCH 09/14] Update docs --- guppylang/decorator.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/guppylang/decorator.py b/guppylang/decorator.py index 0b833fdd..8900f056 100644 --- a/guppylang/decorator.py +++ b/guppylang/decorator.py @@ -63,10 +63,6 @@ def __call__(self, arg: PyFunc | GuppyModule) -> None | FuncDecorator: Optionally, the `GuppyModule` in which the function should be placed can be passed to the decorator. - - If `compile` is set to `True` and no `GuppyModule` is passed, the - function is compiled immediately as an standalone module and the Hugr is - returned. """ def make_dummy(wraps: PyFunc) -> Callable[..., Any]: @@ -192,7 +188,7 @@ def __str__(self) -> str: def type_var(self, module: GuppyModule, name: str, linear: bool = False) -> TypeVar: """Creates a new type variable in a module.""" module.register_type_var(name, linear) - return TypeVar(name) + return TypeVar(name) # type: ignore[parameter] @pretty_errors def custom( @@ -263,7 +259,11 @@ def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule: if id is None: id = self._get_python_caller() if id not in self._modules: - err = f"Module {id.name} not found." if id else "No module found." + err = ( + f"Module {id.name} not found." + if id + else "No Guppy functions or types defined in this module." + ) raise MissingModuleError(err) return self._modules.pop(id) @@ -271,7 +271,11 @@ def compile_module(self, id: CallerIdentifier | None = None) -> Hugr: """Compiles the local module into a Hugr.""" module = self.take_module(id) if not module: - err = f"Module {id.name} not found." if id else "No module found." + err = ( + f"Module {id.name} not found." + if id + else "No Guppy functions or types defined in this module." + ) raise MissingModuleError(err) return module.compile() if module else None From 008782caf38ac59ecffe3e7ad0ea534f0274a333 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 13:54:27 +0000 Subject: [PATCH 10/14] Associate GuppyModules with the py module, not the function --- guppylang/decorator.py | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/guppylang/decorator.py b/guppylang/decorator.py index 8900f056..2bd48771 100644 --- a/guppylang/decorator.py +++ b/guppylang/decorator.py @@ -30,7 +30,7 @@ class CallerIdentifier: """Identifier for the interpreter frame that called the decorator.""" filename: Path - function: str + module: str | None @property def name(self) -> str: @@ -38,11 +38,8 @@ def name(self) -> str: If the called is not a function, uses the file name. """ - module_name = inspect.getmodulename(self.filename) - if self.function != "": - return self.function - if module_name is not None: - return module_name + if self.module is not None: + return self.module.__name__ return self.filename.name @@ -80,7 +77,7 @@ def dummy(*args: Any, **kwargs: Any) -> Any: f = arg def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: - caller = self._get_python_caller() + caller = self._get_python_caller(f) if caller not in self._modules: self._modules[caller] = GuppyModule(caller.name) module = self._modules[caller] @@ -99,14 +96,23 @@ def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: raise ValueError(f"Invalid arguments to `@guppy` decorator: {arg}") - def _get_python_caller(self) -> CallerIdentifier: - """Returns an identifier for the interpreter frame that called the decorator.""" - for s in inspect.stack(): - # Note the hacky check for the pretty errors wrapper, - # since @pretty_errors wraps the __call__ method. - if s.filename != __file__ and s.function != "pretty_errors_wrapped": - return CallerIdentifier(Path(s.filename), s.function) - raise GuppyError("Could not find caller of `@guppy` decorator") + def _get_python_caller(self, fn: PyFunc | None = None) -> CallerIdentifier: + """Returns an identifier for the interpreter frame that called the decorator. + + :param fn: Optional. The function that was decorated. + """ + if fn is not None: + filename = inspect.getfile(fn) + module = inspect.getmodule(fn) + else: + for s in inspect.stack(): + if s.filename != __file__: + filename = s.filename + module = inspect.getmodule(s.frame) + break + else: + raise GuppyError("Could not find a caller for the `@guppy` decorator") + return CallerIdentifier(Path(filename), module) @pretty_errors def extend_type(self, module: GuppyModule, ty: type[GuppyType]) -> ClassDecorator: @@ -256,12 +262,13 @@ def dummy(*args: Any, **kwargs: Any) -> Any: def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule: """Returns the local GuppyModule, removing it from the local state.""" + orig_id = id if id is None: id = self._get_python_caller() if id not in self._modules: err = ( - f"Module {id.name} not found." - if id + f"Module {orig_id.name} not found." + if orig_id else "No Guppy functions or types defined in this module." ) raise MissingModuleError(err) From 3d303a9590e7053ffebc09bc73c639e68785f8bf Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 14:01:19 +0000 Subject: [PATCH 11/14] fix mypy --- guppylang/decorator.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/guppylang/decorator.py b/guppylang/decorator.py index 2bd48771..7dcd1fde 100644 --- a/guppylang/decorator.py +++ b/guppylang/decorator.py @@ -3,6 +3,7 @@ from collections.abc import Callable, Iterator, Sequence from dataclasses import dataclass from pathlib import Path +from types import ModuleType from typing import Any, ClassVar, TypeVar from guppylang.ast_util import AstNode, has_empty_body @@ -30,7 +31,7 @@ class CallerIdentifier: """Identifier for the interpreter frame that called the decorator.""" filename: Path - module: str | None + module: ModuleType | None @property def name(self) -> str: @@ -39,7 +40,7 @@ def name(self) -> str: If the called is not a function, uses the file name. """ if self.module is not None: - return self.module.__name__ + return str(self.module.__name__) return self.filename.name @@ -55,7 +56,7 @@ def __init__(self) -> None: self._modules = {} @pretty_errors - def __call__(self, arg: PyFunc | GuppyModule) -> None | FuncDecorator: + def __call__(self, arg: PyFunc | GuppyModule) -> FuncDecorator: """Decorator to annotate Python functions as Guppy code. Optionally, the `GuppyModule` in which the function should be placed can @@ -76,7 +77,7 @@ def dummy(*args: Any, **kwargs: Any) -> Any: # We default to a module associated with the caller of the decorator. f = arg - def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: + def dec(f: Callable[..., Any]) -> Callable[..., Any]: caller = self._get_python_caller(f) if caller not in self._modules: self._modules[caller] = GuppyModule(caller.name) @@ -88,7 +89,7 @@ def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: if isinstance(arg, GuppyModule): # Module passed. - def dec(f: Callable[..., Any]) -> Callable[..., Any] | Hugr: + def dec(f: Callable[..., Any]) -> Callable[..., Any]: arg.register_func_def(f) return make_dummy(f) @@ -194,7 +195,7 @@ def __str__(self) -> str: def type_var(self, module: GuppyModule, name: str, linear: bool = False) -> TypeVar: """Creates a new type variable in a module.""" module.register_type_var(name, linear) - return TypeVar(name) # type: ignore[parameter] + return TypeVar(name) @pretty_errors def custom( @@ -274,7 +275,7 @@ def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule: raise MissingModuleError(err) return self._modules.pop(id) - def compile_module(self, id: CallerIdentifier | None = None) -> Hugr: + def compile_module(self, id: CallerIdentifier | None = None) -> Hugr | None: """Compiles the local module into a Hugr.""" module = self.take_module(id) if not module: @@ -284,7 +285,7 @@ def compile_module(self, id: CallerIdentifier | None = None) -> Hugr: else "No Guppy functions or types defined in this module." ) raise MissingModuleError(err) - return module.compile() if module else None + return module.compile() def registered_modules(self) -> list[CallerIdentifier]: """Returns a list of all currently registered modules for local contexts.""" From 4ac68a59fab102a4aab239f40fd6c1de0ad72da3 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 15:07:38 +0000 Subject: [PATCH 12/14] Review comments: Better docs for the identifier --- guppylang/decorator.py | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/guppylang/decorator.py b/guppylang/decorator.py index 7dcd1fde..77538f9e 100644 --- a/guppylang/decorator.py +++ b/guppylang/decorator.py @@ -27,8 +27,8 @@ @dataclass(frozen=True) -class CallerIdentifier: - """Identifier for the interpreter frame that called the decorator.""" +class ModuleIdentifier: + """Identifier for the Python file/module that called the decorator.""" filename: Path module: ModuleType | None @@ -47,10 +47,10 @@ def name(self) -> str: class _Guppy: """Class for the `@guppy` decorator.""" - # The currently-alive modules, associated with an element in the call stack. + # The currently-alive GuppyModules, associated with a Python file/module. # # Only contains **uncompiled** modules. - _modules: dict[CallerIdentifier, GuppyModule] + _modules: dict[ModuleIdentifier, GuppyModule] def __init__(self) -> None: self._modules = {} @@ -77,15 +77,12 @@ def dummy(*args: Any, **kwargs: Any) -> Any: # We default to a module associated with the caller of the decorator. f = arg - def dec(f: Callable[..., Any]) -> Callable[..., Any]: - caller = self._get_python_caller(f) - if caller not in self._modules: - self._modules[caller] = GuppyModule(caller.name) - module = self._modules[caller] - module.register_func_def(f) - return make_dummy(f) - - return dec(f) + caller = self._get_python_caller(f) + if caller not in self._modules: + self._modules[caller] = GuppyModule(caller.name) + module = self._modules[caller] + module.register_func_def(f) + return make_dummy(f) if isinstance(arg, GuppyModule): # Module passed. @@ -97,8 +94,8 @@ def dec(f: Callable[..., Any]) -> Callable[..., Any]: raise ValueError(f"Invalid arguments to `@guppy` decorator: {arg}") - def _get_python_caller(self, fn: PyFunc | None = None) -> CallerIdentifier: - """Returns an identifier for the interpreter frame that called the decorator. + def _get_python_caller(self, fn: PyFunc | None = None) -> ModuleIdentifier: + """Returns an identifier for the Python file/module that called the decorator. :param fn: Optional. The function that was decorated. """ @@ -113,7 +110,7 @@ def _get_python_caller(self, fn: PyFunc | None = None) -> CallerIdentifier: break else: raise GuppyError("Could not find a caller for the `@guppy` decorator") - return CallerIdentifier(Path(filename), module) + return ModuleIdentifier(Path(filename), module) @pretty_errors def extend_type(self, module: GuppyModule, ty: type[GuppyType]) -> ClassDecorator: @@ -261,7 +258,7 @@ def dummy(*args: Any, **kwargs: Any) -> Any: return dec - def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule: + def take_module(self, id: ModuleIdentifier | None = None) -> GuppyModule: """Returns the local GuppyModule, removing it from the local state.""" orig_id = id if id is None: @@ -275,7 +272,7 @@ def take_module(self, id: CallerIdentifier | None = None) -> GuppyModule: raise MissingModuleError(err) return self._modules.pop(id) - def compile_module(self, id: CallerIdentifier | None = None) -> Hugr | None: + def compile_module(self, id: ModuleIdentifier | None = None) -> Hugr | None: """Compiles the local module into a Hugr.""" module = self.take_module(id) if not module: @@ -287,7 +284,7 @@ def compile_module(self, id: CallerIdentifier | None = None) -> Hugr | None: raise MissingModuleError(err) return module.compile() - def registered_modules(self) -> list[CallerIdentifier]: + def registered_modules(self) -> list[ModuleIdentifier]: """Returns a list of all currently registered modules for local contexts.""" return list(self._modules.keys()) From a75ac5001ab09aeb3c68de1eb7fe2d2996365a37 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 15:16:02 +0000 Subject: [PATCH 13/14] Drop assert message --- tests/error/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/error/util.py b/tests/error/util.py index 88c3182c..821aa2f4 100644 --- a/tests/error/util.py +++ b/tests/error/util.py @@ -26,7 +26,7 @@ def run_error_test(file, capsys): exp_err = f.read() exp_err = exp_err.replace("$FILE", str(file)) - assert err == exp_err, f"Expected error '{err}', but got '{exp_err}'." + assert err == exp_err util = GuppyModule("test") From 3042071170d83b263401456d516f6a646e9b4c47 Mon Sep 17 00:00:00 2001 From: Agustin Borgna Date: Thu, 18 Jan 2024 15:43:11 +0000 Subject: [PATCH 14/14] Avoid a circular dependency `hugr` uses `gtypes`, which uses `hugr.tys` --- guppylang/hugr/__init__.py | 5 ----- tests/util.py | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/guppylang/hugr/__init__.py b/guppylang/hugr/__init__.py index 0f6535c5..e69de29b 100644 --- a/guppylang/hugr/__init__.py +++ b/guppylang/hugr/__init__.py @@ -1,5 +0,0 @@ -"""Python definitions for the Hierarchical Unified Graph Representation.""" - -from .hugr import Hugr - -__all__ = ["Hugr"] diff --git a/tests/util.py b/tests/util.py index 36cc3175..3a45073e 100644 --- a/tests/util.py +++ b/tests/util.py @@ -1,5 +1,5 @@ import guppylang -from guppylang.hugr import Hugr +from guppylang.hugr.hugr import Hugr from guppylang.module import GuppyModule