guppylang-internals 0.24.0__tar.gz → 0.25.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/CHANGELOG.md +25 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/PKG-INFO +3 -3
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/pyproject.toml +3 -3
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/__init__.py +1 -1
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/ast_util.py +21 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/cfg/bb.py +20 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/cfg/builder.py +101 -3
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/core.py +4 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/errors/generic.py +32 -1
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/errors/type_errors.py +14 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/expr_checker.py +46 -10
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/func_checker.py +1 -1
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/linearity_checker.py +65 -0
- guppylang_internals-0.25.0/src/guppylang_internals/checker/modifier_checker.py +116 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/stmt_checker.py +48 -1
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/compiler/core.py +90 -53
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/compiler/expr_compiler.py +49 -114
- guppylang_internals-0.25.0/src/guppylang_internals/compiler/modifier_compiler.py +174 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/compiler/stmt_compiler.py +15 -8
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/custom.py +35 -1
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/declaration.py +3 -4
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/parameter.py +8 -3
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/pytket_circuits.py +13 -41
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/struct.py +7 -4
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/ty.py +3 -3
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/experimental.py +5 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/nodes.py +124 -0
- guppylang_internals-0.25.0/src/guppylang_internals/std/_internal/compiler/array.py +381 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/tket_exts.py +9 -2
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tracing/unpacking.py +19 -20
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/arg.py +18 -3
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/builtin.py +2 -5
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/const.py +33 -4
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/param.py +31 -16
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/parsing.py +8 -21
- guppylang_internals-0.25.0/src/guppylang_internals/tys/qubit.py +27 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/subst.py +8 -26
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/ty.py +31 -21
- guppylang_internals-0.24.0/src/guppylang_internals/std/_internal/compiler/array.py +0 -569
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/.gitignore +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/LICENCE +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/README.md +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/cfg/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/cfg/analysis.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/cfg/cfg.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/cfg_checker.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/errors/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/errors/comptime_errors.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/errors/linearity.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/errors/wasm.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/compiler/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/compiler/cfg_compiler.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/compiler/func_compiler.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/compiler/hugr_extension.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/compiler/qtm_platform_extension.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/decorator.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/common.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/const.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/extern.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/function.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/overloaded.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/traced.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/value.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/definition/wasm.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/diagnostic.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/dummy_decorator.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/engine.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/error.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/ipython_inspect.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/py.typed +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/span.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/checker.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/arithmetic.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/either.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/frozenarray.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/futures.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/list.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/mem.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/option.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/prelude.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/qsystem.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/quantum.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/tket_bool.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler/wasm.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/compiler.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/debug.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/std/_internal/util.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tracing/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tracing/builtins_mock.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tracing/frozenlist.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tracing/function.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tracing/object.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tracing/state.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tracing/util.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/__init__.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/common.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/errors.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/printing.py +0 -0
- {guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/tys/var.py +0 -0
|
@@ -3,6 +3,31 @@
|
|
|
3
3
|
First release of `guppylang_internals` package containing refactored out internal components
|
|
4
4
|
from `guppylang`.
|
|
5
5
|
|
|
6
|
+
## [0.25.0](https://github.com/CQCL/guppylang/compare/guppylang-internals-v0.24.0...guppylang-internals-v0.25.0) (2025-10-28)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### ⚠ BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
* (guppy-internals) Arrays are now lowered to `borrow_array`s instead of `value_array`s so elements do no longer need to be wrapped in options during lowering.
|
|
12
|
+
* `checker.core.requires_monomorphization` renamed into `require_monomorphization` and now operating on all parameters simultaneously `tys.subst.BoundVarFinder` removed. Instead, use the new `bound_vars` property on types, arguments, and consts. `tys.parsing.parse_parameter` now requires a `param_var_mapping`.
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* compiler for modifiers ([#1287](https://github.com/CQCL/guppylang/issues/1287)) ([439ff1a](https://github.com/CQCL/guppylang/commit/439ff1ae6bd872bb7a6eb5441110d2febebd1e47))
|
|
17
|
+
* modifiers in CFG and its type checker (experimental) ([#1281](https://github.com/CQCL/guppylang/issues/1281)) ([fe85018](https://github.com/CQCL/guppylang/commit/fe8501854507c3c43cec2f26bba75198766a4a17))
|
|
18
|
+
* Turn type parameters into dependent telescopes ([#1154](https://github.com/CQCL/guppylang/issues/1154)) ([b56e056](https://github.com/CQCL/guppylang/commit/b56e056a6b4795c778ed8124a09a194fb1d97dda))
|
|
19
|
+
* update hugr, tket-exts and tket ([#1305](https://github.com/CQCL/guppylang/issues/1305)) ([6990d85](https://github.com/CQCL/guppylang/commit/6990d850170e6901f60ef1d1e718c99349105b56))
|
|
20
|
+
* Use `borrow_array` instead of `value_array` for array lowering ([#1166](https://github.com/CQCL/guppylang/issues/1166)) ([f9ef42b](https://github.com/CQCL/guppylang/commit/f9ef42b2baf61c3e1c2cfcf7bd1f3bcac33a1a25))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* compilation of affine-bounded type variables ([#1308](https://github.com/CQCL/guppylang/issues/1308)) ([49ecb49](https://github.com/CQCL/guppylang/commit/49ecb497bf450d0853baec1de9c516a3804a80eb))
|
|
26
|
+
* Detect unsolved generic parameters even if they are unused ([#1279](https://github.com/CQCL/guppylang/issues/1279)) ([f830db0](https://github.com/CQCL/guppylang/commit/f830db00c416cfc1e9fe7ec70c612b6b558aa740)), closes [#1273](https://github.com/CQCL/guppylang/issues/1273)
|
|
27
|
+
* Fix bug in symbolic pytket circuit loading with arrays ([#1302](https://github.com/CQCL/guppylang/issues/1302)) ([e6b90e8](https://github.com/CQCL/guppylang/commit/e6b90e8e4d275d36514a75e87eb097383495a291)), closes [#1298](https://github.com/CQCL/guppylang/issues/1298)
|
|
28
|
+
* Improve track_hugr_side_effects, adding Order edges from/to Input/Output ([#1311](https://github.com/CQCL/guppylang/issues/1311)) ([3c6ce7a](https://github.com/CQCL/guppylang/commit/3c6ce7aaf7a1c93c6412501976fc97afd61a062d))
|
|
29
|
+
* multiline loop arguments ([#1309](https://github.com/CQCL/guppylang/issues/1309)) ([836ef72](https://github.com/CQCL/guppylang/commit/836ef722d8f8bdb02c56e5f06934246a718e68d3))
|
|
30
|
+
|
|
6
31
|
## [0.24.0](https://github.com/CQCL/guppylang/compare/guppylang-internals-v0.23.0...guppylang-internals-v0.24.0) (2025-09-19)
|
|
7
32
|
|
|
8
33
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: guppylang-internals
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.0
|
|
4
4
|
Summary: Compiler internals for `guppylang` package.
|
|
5
5
|
Author-email: Mark Koch <mark.koch@quantinuum.com>, TKET development team <tket-support@quantinuum.com>
|
|
6
6
|
Maintainer-email: Mark Koch <mark.koch@quantinuum.com>, TKET development team <tket-support@quantinuum.com>
|
|
@@ -219,8 +219,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
219
219
|
Classifier: Programming Language :: Python :: 3.14
|
|
220
220
|
Classifier: Topic :: Software Development :: Compilers
|
|
221
221
|
Requires-Python: <4,>=3.10
|
|
222
|
-
Requires-Dist: hugr~=0.
|
|
223
|
-
Requires-Dist: tket-exts~=0.
|
|
222
|
+
Requires-Dist: hugr~=0.14.1
|
|
223
|
+
Requires-Dist: tket-exts~=0.12.0
|
|
224
224
|
Requires-Dist: typing-extensions<5,>=4.9.0
|
|
225
225
|
Provides-Extra: pytket
|
|
226
226
|
Requires-Dist: pytket>=1.34; extra == 'pytket'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "guppylang-internals"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.25.0"
|
|
4
4
|
requires-python = ">=3.10,<4"
|
|
5
5
|
description = "Compiler internals for `guppylang` package."
|
|
6
6
|
license = { file = "LICENCE" }
|
|
@@ -34,8 +34,8 @@ classifiers = [
|
|
|
34
34
|
|
|
35
35
|
dependencies = [
|
|
36
36
|
"typing-extensions >=4.9.0,<5",
|
|
37
|
-
"tket-exts ~= 0.
|
|
38
|
-
"hugr ~= 0.
|
|
37
|
+
"tket-exts ~= 0.12.0",
|
|
38
|
+
"hugr ~= 0.14.1",
|
|
39
39
|
]
|
|
40
40
|
|
|
41
41
|
[project.optional-dependencies]
|
{guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/ast_util.py
RENAMED
|
@@ -106,6 +106,14 @@ def return_nodes_in_ast(node: Any) -> list[ast.Return]:
|
|
|
106
106
|
return cast(list[ast.Return], found)
|
|
107
107
|
|
|
108
108
|
|
|
109
|
+
def loop_in_ast(node: Any) -> list[ast.For | ast.While]:
|
|
110
|
+
"""Returns all `For` and `While` nodes occurring in an AST."""
|
|
111
|
+
found = find_nodes(
|
|
112
|
+
lambda n: isinstance(n, ast.For | ast.While), node, {ast.FunctionDef}
|
|
113
|
+
)
|
|
114
|
+
return cast(list[ast.For | ast.While], found)
|
|
115
|
+
|
|
116
|
+
|
|
109
117
|
def breaks_in_loop(node: Any) -> list[ast.Break]:
|
|
110
118
|
"""Returns all `Break` nodes occurring in a loop.
|
|
111
119
|
|
|
@@ -117,6 +125,19 @@ def breaks_in_loop(node: Any) -> list[ast.Break]:
|
|
|
117
125
|
return cast(list[ast.Break], found)
|
|
118
126
|
|
|
119
127
|
|
|
128
|
+
def loop_controls_in_loop(node: Any) -> list[ast.Break | ast.Continue]:
|
|
129
|
+
"""Returns all `Break` and `Continue` nodes occurring in a loop.
|
|
130
|
+
|
|
131
|
+
Note that breaks in nested loops are excluded.
|
|
132
|
+
"""
|
|
133
|
+
found = find_nodes(
|
|
134
|
+
lambda n: isinstance(n, ast.Break | ast.Continue),
|
|
135
|
+
node,
|
|
136
|
+
{ast.For, ast.While, ast.FunctionDef},
|
|
137
|
+
)
|
|
138
|
+
return cast(list[ast.Break | ast.Continue], found)
|
|
139
|
+
|
|
140
|
+
|
|
120
141
|
class ContextAdjuster(ast.NodeTransformer):
|
|
121
142
|
"""Updates the `ast.Context` indicating if expressions occur on the LHS or RHS."""
|
|
122
143
|
|
|
@@ -13,6 +13,7 @@ from guppylang_internals.nodes import (
|
|
|
13
13
|
DesugaredGenerator,
|
|
14
14
|
DesugaredGeneratorExpr,
|
|
15
15
|
DesugaredListComp,
|
|
16
|
+
ModifiedBlock,
|
|
16
17
|
NestedFunctionDef,
|
|
17
18
|
)
|
|
18
19
|
|
|
@@ -44,6 +45,7 @@ BBStatement = (
|
|
|
44
45
|
| ast.Expr
|
|
45
46
|
| ast.Return
|
|
46
47
|
| NestedFunctionDef
|
|
48
|
+
| ModifiedBlock
|
|
47
49
|
)
|
|
48
50
|
|
|
49
51
|
|
|
@@ -219,3 +221,21 @@ class VariableVisitor(ast.NodeVisitor):
|
|
|
219
221
|
|
|
220
222
|
# The name of the function is now assigned
|
|
221
223
|
self.stats.assigned[node.name] = node
|
|
224
|
+
|
|
225
|
+
def visit_ModifiedBlock(self, node: ModifiedBlock) -> None:
|
|
226
|
+
for item in node.control:
|
|
227
|
+
self.visit(item)
|
|
228
|
+
for item in node.power:
|
|
229
|
+
self.visit(item)
|
|
230
|
+
|
|
231
|
+
# Similarly to nested functions
|
|
232
|
+
from guppylang_internals.cfg.analysis import LivenessAnalysis
|
|
233
|
+
|
|
234
|
+
stats = {bb: bb.compute_variable_stats() for bb in node.cfg.bbs}
|
|
235
|
+
live = LivenessAnalysis(stats).run(node.cfg.bbs)
|
|
236
|
+
assigned_before_in_bb = self.stats.assigned.keys()
|
|
237
|
+
self.stats.used |= {
|
|
238
|
+
x: using_bb.vars.used[x]
|
|
239
|
+
for x, using_bb in live[node.cfg.entry_bb].items()
|
|
240
|
+
if x not in assigned_before_in_bb
|
|
241
|
+
}
|
{guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/cfg/builder.py
RENAMED
|
@@ -9,6 +9,8 @@ from guppylang_internals.ast_util import (
|
|
|
9
9
|
AstVisitor,
|
|
10
10
|
ContextAdjuster,
|
|
11
11
|
find_nodes,
|
|
12
|
+
loop_controls_in_loop,
|
|
13
|
+
return_nodes_in_ast,
|
|
12
14
|
set_location_from,
|
|
13
15
|
template_replace,
|
|
14
16
|
with_loc,
|
|
@@ -16,19 +18,34 @@ from guppylang_internals.ast_util import (
|
|
|
16
18
|
from guppylang_internals.cfg.bb import BB, BBStatement
|
|
17
19
|
from guppylang_internals.cfg.cfg import CFG
|
|
18
20
|
from guppylang_internals.checker.core import Globals
|
|
19
|
-
from guppylang_internals.checker.errors.generic import
|
|
21
|
+
from guppylang_internals.checker.errors.generic import (
|
|
22
|
+
ExpectedError,
|
|
23
|
+
UnexpectedInWithBlockError,
|
|
24
|
+
UnknownModifierError,
|
|
25
|
+
UnsupportedError,
|
|
26
|
+
)
|
|
27
|
+
from guppylang_internals.checker.errors.type_errors import WrongNumberOfArgsError
|
|
20
28
|
from guppylang_internals.diagnostic import Error
|
|
21
29
|
from guppylang_internals.error import GuppyError, InternalGuppyError
|
|
22
|
-
from guppylang_internals.experimental import
|
|
30
|
+
from guppylang_internals.experimental import (
|
|
31
|
+
check_lists_enabled,
|
|
32
|
+
check_modifiers_enabled,
|
|
33
|
+
)
|
|
23
34
|
from guppylang_internals.nodes import (
|
|
24
35
|
ComptimeExpr,
|
|
36
|
+
Control,
|
|
37
|
+
Dagger,
|
|
25
38
|
DesugaredGenerator,
|
|
26
39
|
DesugaredGeneratorExpr,
|
|
27
40
|
DesugaredListComp,
|
|
28
41
|
IterNext,
|
|
29
42
|
MakeIter,
|
|
43
|
+
ModifiedBlock,
|
|
44
|
+
Modifier,
|
|
30
45
|
NestedFunctionDef,
|
|
46
|
+
Power,
|
|
31
47
|
)
|
|
48
|
+
from guppylang_internals.span import Span, to_span
|
|
32
49
|
from guppylang_internals.tys.ty import NoneType
|
|
33
50
|
|
|
34
51
|
# In order to build expressions, need an endless stream of unique temporary variables
|
|
@@ -135,7 +152,10 @@ class CFGBuilder(AstVisitor[BB | None]):
|
|
|
135
152
|
Builds the expression and mutates `node.value` to point to the built expression.
|
|
136
153
|
Returns the BB in which the expression is available and adds the node to it.
|
|
137
154
|
"""
|
|
138
|
-
if
|
|
155
|
+
if (
|
|
156
|
+
not isinstance(node, NestedFunctionDef | ModifiedBlock)
|
|
157
|
+
and node.value is not None
|
|
158
|
+
):
|
|
139
159
|
node.value, bb = ExprBuilder.build(node.value, self.cfg, bb)
|
|
140
160
|
bb.statements.append(node)
|
|
141
161
|
return bb
|
|
@@ -265,6 +285,84 @@ class CFGBuilder(AstVisitor[BB | None]):
|
|
|
265
285
|
bb.statements.append(new_node)
|
|
266
286
|
return bb
|
|
267
287
|
|
|
288
|
+
def visit_With(self, node: ast.With, bb: BB, jumps: Jumps) -> BB | None:
|
|
289
|
+
check_modifiers_enabled(node)
|
|
290
|
+
self._validate_modified_block(node)
|
|
291
|
+
|
|
292
|
+
cfg = CFGBuilder().build(node.body, True, self.globals)
|
|
293
|
+
new_node = ModifiedBlock(
|
|
294
|
+
cfg=cfg,
|
|
295
|
+
**dict(ast.iter_fields(node)),
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
for item in node.items:
|
|
299
|
+
item.context_expr, bb = ExprBuilder.build(item.context_expr, self.cfg, bb)
|
|
300
|
+
modifier = self._handle_withitem(item)
|
|
301
|
+
new_node.push_modifier(modifier)
|
|
302
|
+
|
|
303
|
+
set_location_from(new_node, node)
|
|
304
|
+
bb.statements.append(new_node)
|
|
305
|
+
return bb
|
|
306
|
+
|
|
307
|
+
def _handle_withitem(self, node: ast.withitem) -> Modifier:
|
|
308
|
+
# Check that `as` notation is not used
|
|
309
|
+
if node.optional_vars is not None:
|
|
310
|
+
span = Span(
|
|
311
|
+
to_span(node.context_expr).start, to_span(node.optional_vars).end
|
|
312
|
+
)
|
|
313
|
+
raise GuppyError(UnsupportedError(span, "`as` expression", singular=True))
|
|
314
|
+
|
|
315
|
+
e = node.context_expr
|
|
316
|
+
modifier: Modifier
|
|
317
|
+
match e:
|
|
318
|
+
case ast.Name(id="dagger"):
|
|
319
|
+
modifier = Dagger(e)
|
|
320
|
+
case ast.Call(func=ast.Name(id="dagger")):
|
|
321
|
+
if len(e.args) != 0:
|
|
322
|
+
span = Span(to_span(e.args[0]).start, to_span(e.args[-1]).end)
|
|
323
|
+
raise GuppyError(WrongNumberOfArgsError(span, 0, len(e.args)))
|
|
324
|
+
modifier = Dagger(e)
|
|
325
|
+
case ast.Call(func=ast.Name(id="control")):
|
|
326
|
+
if len(e.args) == 0:
|
|
327
|
+
span = Span(to_span(e.func).end, to_span(e).end)
|
|
328
|
+
raise GuppyError(WrongNumberOfArgsError(span, 1, len(e.args)))
|
|
329
|
+
modifier = Control(e, e.args)
|
|
330
|
+
case ast.Call(func=ast.Name(id="power")):
|
|
331
|
+
if len(e.args) == 0:
|
|
332
|
+
span = Span(to_span(e.func).end, to_span(e).end)
|
|
333
|
+
raise GuppyError(WrongNumberOfArgsError(span, 1, len(e.args)))
|
|
334
|
+
elif len(e.args) != 1:
|
|
335
|
+
span = Span(to_span(e.args[1]).start, to_span(e.args[-1]).end)
|
|
336
|
+
raise GuppyError(WrongNumberOfArgsError(span, 1, len(e.args)))
|
|
337
|
+
modifier = Power(e, e.args[0])
|
|
338
|
+
case _:
|
|
339
|
+
raise GuppyError(UnknownModifierError(e))
|
|
340
|
+
return modifier
|
|
341
|
+
|
|
342
|
+
def _validate_modified_block(self, node: ast.With) -> None:
|
|
343
|
+
# Check if the body contains a return statement.
|
|
344
|
+
return_in_body = return_nodes_in_ast(node)
|
|
345
|
+
if len(return_in_body) != 0:
|
|
346
|
+
err = UnexpectedInWithBlockError(return_in_body[0], "return", "Return")
|
|
347
|
+
span = Span(
|
|
348
|
+
to_span(node.items[0].context_expr).start,
|
|
349
|
+
to_span(node.items[-1].context_expr).end,
|
|
350
|
+
)
|
|
351
|
+
err.add_sub_diagnostic(UnexpectedInWithBlockError.Modifier(span))
|
|
352
|
+
raise GuppyError(err)
|
|
353
|
+
|
|
354
|
+
loop_controls_in_body = loop_controls_in_loop(node)
|
|
355
|
+
if len(loop_controls_in_body) != 0:
|
|
356
|
+
lc = loop_controls_in_body[0]
|
|
357
|
+
kind = lc.__class__.__name__
|
|
358
|
+
err = UnexpectedInWithBlockError(lc, "loop control", kind)
|
|
359
|
+
span = Span(
|
|
360
|
+
to_span(node.items[0].context_expr).start,
|
|
361
|
+
to_span(node.items[-1].context_expr).end,
|
|
362
|
+
)
|
|
363
|
+
err.add_sub_diagnostic(UnexpectedInWithBlockError.Modifier(span))
|
|
364
|
+
raise GuppyError(err)
|
|
365
|
+
|
|
268
366
|
def generic_visit(self, node: ast.AST, bb: BB, jumps: Jumps) -> BB | None:
|
|
269
367
|
# When adding support for new statements, we have to remember to use the
|
|
270
368
|
# ExprBuilder to transform all included expressions!
|
{guppylang_internals-0.24.0 → guppylang_internals-0.25.0}/src/guppylang_internals/checker/core.py
RENAMED
|
@@ -117,6 +117,10 @@ class Variable:
|
|
|
117
117
|
"""Returns a new `Variable` instance with an updated definition location."""
|
|
118
118
|
return replace(self, defined_at=node)
|
|
119
119
|
|
|
120
|
+
def add_flags(self, flags: InputFlags) -> "Variable":
|
|
121
|
+
"""Returns a new `Variable` instance with updated flags."""
|
|
122
|
+
return replace(self, flags=self.flags | flags)
|
|
123
|
+
|
|
120
124
|
|
|
121
125
|
@dataclass(frozen=True, kw_only=True)
|
|
122
126
|
class ComptimeVariable(Variable):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from typing import ClassVar
|
|
3
3
|
|
|
4
|
-
from guppylang_internals.diagnostic import Error
|
|
4
|
+
from guppylang_internals.diagnostic import Error, Note
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
@dataclass(frozen=True)
|
|
@@ -43,3 +43,34 @@ class ExpectedError(Error):
|
|
|
43
43
|
@property
|
|
44
44
|
def extra(self) -> str:
|
|
45
45
|
return f", got {self.got}" if self.got else ""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True)
|
|
49
|
+
class UnknownModifierError(Error):
|
|
50
|
+
title: ClassVar[str] = "Unknown modifier"
|
|
51
|
+
span_label: ClassVar[str] = (
|
|
52
|
+
"Expected one of {{dagger, control(...), or power(...)}}"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True)
|
|
57
|
+
class UnexpectedInWithBlockError(Error):
|
|
58
|
+
title: ClassVar[str] = "Unexpected {kind}"
|
|
59
|
+
span_label: ClassVar[str] = "{things} found in a `With` block"
|
|
60
|
+
kind: str
|
|
61
|
+
things: str
|
|
62
|
+
|
|
63
|
+
@dataclass(frozen=True)
|
|
64
|
+
class Modifier(Note):
|
|
65
|
+
span_label: ClassVar[str] = "modifier is used here"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass(frozen=True)
|
|
69
|
+
class InvalidUnderDagger(Error):
|
|
70
|
+
title: ClassVar[str] = "Invalid expression in dagger"
|
|
71
|
+
span_label: ClassVar[str] = "{things} found in a dagger context"
|
|
72
|
+
things: str
|
|
73
|
+
|
|
74
|
+
@dataclass(frozen=True)
|
|
75
|
+
class Dagger(Note):
|
|
76
|
+
span_label: ClassVar[str] = "dagger modifier is used here"
|
|
@@ -95,6 +95,20 @@ class TypeInferenceError(Error):
|
|
|
95
95
|
unsolved_ty: Type
|
|
96
96
|
|
|
97
97
|
|
|
98
|
+
@dataclass(frozen=True)
|
|
99
|
+
class ParameterInferenceError(Error):
|
|
100
|
+
title: ClassVar[str] = "Cannot infer generic parameter"
|
|
101
|
+
span_label: ClassVar[str] = (
|
|
102
|
+
"Cannot infer generic parameter `{param}` of this function"
|
|
103
|
+
)
|
|
104
|
+
param: str
|
|
105
|
+
|
|
106
|
+
@dataclass(frozen=True)
|
|
107
|
+
class SignatureHint(Note):
|
|
108
|
+
message: ClassVar[str] = "Function signature is `{sig}`"
|
|
109
|
+
sig: FunctionType
|
|
110
|
+
|
|
111
|
+
|
|
98
112
|
@dataclass(frozen=True)
|
|
99
113
|
class IllegalConstant(Error):
|
|
100
114
|
title: ClassVar[str] = "Unsupported constant"
|
|
@@ -23,6 +23,7 @@ can be used to infer a type for an expression.
|
|
|
23
23
|
import ast
|
|
24
24
|
import sys
|
|
25
25
|
import traceback
|
|
26
|
+
from collections.abc import Sequence
|
|
26
27
|
from contextlib import suppress
|
|
27
28
|
from dataclasses import replace
|
|
28
29
|
from types import ModuleType
|
|
@@ -74,6 +75,7 @@ from guppylang_internals.checker.errors.type_errors import (
|
|
|
74
75
|
ModuleMemberNotFoundError,
|
|
75
76
|
NonLinearInstantiateError,
|
|
76
77
|
NotCallableError,
|
|
78
|
+
ParameterInferenceError,
|
|
77
79
|
TupleIndexOutOfBoundsError,
|
|
78
80
|
TypeApplyNotGenericError,
|
|
79
81
|
TypeInferenceError,
|
|
@@ -130,7 +132,7 @@ from guppylang_internals.tys.builtin import (
|
|
|
130
132
|
string_type,
|
|
131
133
|
)
|
|
132
134
|
from guppylang_internals.tys.const import Const, ConstValue
|
|
133
|
-
from guppylang_internals.tys.param import ConstParam, TypeParam
|
|
135
|
+
from guppylang_internals.tys.param import ConstParam, TypeParam, check_all_args
|
|
134
136
|
from guppylang_internals.tys.parsing import arg_from_ast
|
|
135
137
|
from guppylang_internals.tys.subst import Inst, Subst
|
|
136
138
|
from guppylang_internals.tys.ty import (
|
|
@@ -149,6 +151,7 @@ from guppylang_internals.tys.ty import (
|
|
|
149
151
|
parse_function_tensor,
|
|
150
152
|
unify,
|
|
151
153
|
)
|
|
154
|
+
from guppylang_internals.tys.var import ExistentialVar
|
|
152
155
|
|
|
153
156
|
if TYPE_CHECKING:
|
|
154
157
|
from guppylang_internals.diagnostic import SubDiagnostic
|
|
@@ -462,8 +465,15 @@ class ExprSynthesizer(AstVisitor[tuple[ast.expr, Type]]):
|
|
|
462
465
|
# A `value.attr` attribute access. Unfortunately, the `attr` is just a string,
|
|
463
466
|
# not an AST node, so we have to compute its span by hand. This is fine since
|
|
464
467
|
# linebreaks are not allowed in the identifier following the `.`
|
|
468
|
+
# The only exception are attributes accesses that are generated during
|
|
469
|
+
# desugaring (for example for iterators in `for` loops). Since those just
|
|
470
|
+
# inherit the span of the sugared code, we could have line breaks there.
|
|
471
|
+
# See https://github.com/CQCL/guppylang/issues/1301
|
|
465
472
|
span = to_span(node)
|
|
466
|
-
|
|
473
|
+
if span.start.line == span.end.line:
|
|
474
|
+
attr_span = Span(span.end.shift_left(len(node.attr)), span.end)
|
|
475
|
+
else:
|
|
476
|
+
attr_span = span
|
|
467
477
|
if module := self._is_python_module(node.value):
|
|
468
478
|
if node.attr in module.__dict__:
|
|
469
479
|
val = module.__dict__[node.attr]
|
|
@@ -928,10 +938,9 @@ def check_type_apply(ty: FunctionType, node: ast.Subscript, ctx: Context) -> Ins
|
|
|
928
938
|
err.add_sub_diagnostic(WrongNumberOfArgsError.SignatureHint(None, ty))
|
|
929
939
|
raise GuppyError(err)
|
|
930
940
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
]
|
|
941
|
+
inst = [arg_from_ast(node, ctx.parsing_ctx) for node in arg_exprs]
|
|
942
|
+
check_all_args(ty.params, inst, "", node, arg_exprs)
|
|
943
|
+
return inst
|
|
935
944
|
|
|
936
945
|
|
|
937
946
|
def check_num_args(
|
|
@@ -975,15 +984,17 @@ def type_check_args(
|
|
|
975
984
|
comptime_args = iter(func_ty.comptime_args)
|
|
976
985
|
for inp, func_inp in zip(inputs, func_ty.inputs, strict=True):
|
|
977
986
|
a, s = ExprChecker(ctx).check(inp, func_inp.ty.substitute(subst), "argument")
|
|
987
|
+
subst |= s
|
|
978
988
|
if InputFlags.Inout in func_inp.flags and isinstance(a, PlaceNode):
|
|
979
989
|
a.place = check_place_assignable(
|
|
980
990
|
a.place, ctx, a, "able to borrow subscripted elements"
|
|
981
991
|
)
|
|
982
992
|
if InputFlags.Comptime in func_inp.flags:
|
|
983
993
|
comptime_arg = next(comptime_args)
|
|
984
|
-
|
|
994
|
+
const = comptime_arg.const.substitute(subst)
|
|
995
|
+
s = check_comptime_arg(a, const, func_inp.ty.substitute(subst), subst)
|
|
996
|
+
subst |= s
|
|
985
997
|
new_args.append(a)
|
|
986
|
-
subst |= s
|
|
987
998
|
assert next(comptime_args, None) is None
|
|
988
999
|
|
|
989
1000
|
# If the argument check succeeded, this means that we must have found instantiations
|
|
@@ -1103,7 +1114,7 @@ def synthesize_call(
|
|
|
1103
1114
|
|
|
1104
1115
|
# Success implies that the substitution is closed
|
|
1105
1116
|
assert all(not t.unsolved_vars for t in subst.values())
|
|
1106
|
-
inst =
|
|
1117
|
+
inst = check_all_solved(subst, free_vars, func_ty, node)
|
|
1107
1118
|
|
|
1108
1119
|
# Finally, check that the instantiation respects the linearity requirements
|
|
1109
1120
|
check_inst(func_ty, inst, node)
|
|
@@ -1182,7 +1193,7 @@ def check_call(
|
|
|
1182
1193
|
|
|
1183
1194
|
# Success implies that the substitution is closed
|
|
1184
1195
|
assert all(not t.unsolved_vars for t in subst.values())
|
|
1185
|
-
inst =
|
|
1196
|
+
inst = check_all_solved(subst, free_vars, func_ty, node)
|
|
1186
1197
|
subst = {v: t for v, t in subst.items() if v in ty.unsolved_vars}
|
|
1187
1198
|
|
|
1188
1199
|
# Finally, check that the instantiation respects the linearity requirements
|
|
@@ -1191,12 +1202,37 @@ def check_call(
|
|
|
1191
1202
|
return inputs, subst, inst
|
|
1192
1203
|
|
|
1193
1204
|
|
|
1205
|
+
def check_all_solved(
|
|
1206
|
+
subst: Subst,
|
|
1207
|
+
free_vars: Sequence[ExistentialVar],
|
|
1208
|
+
func_ty: FunctionType,
|
|
1209
|
+
loc: AstNode,
|
|
1210
|
+
) -> Inst:
|
|
1211
|
+
"""Checks that a substitution solves all parameters of a function.
|
|
1212
|
+
|
|
1213
|
+
Using 3.12 generic syntax, users can declare parameters that don't occur in the
|
|
1214
|
+
signature. Those will remain unsolved, even after unifying all function arguments,
|
|
1215
|
+
so we have to perform this extra check.
|
|
1216
|
+
|
|
1217
|
+
Returns an instantiation of all free variables, or emits a user error if some are
|
|
1218
|
+
not solved.
|
|
1219
|
+
"""
|
|
1220
|
+
for v in free_vars:
|
|
1221
|
+
if v not in subst:
|
|
1222
|
+
err = ParameterInferenceError(loc, v.display_name)
|
|
1223
|
+
err.add_sub_diagnostic(ParameterInferenceError.SignatureHint(None, func_ty))
|
|
1224
|
+
raise GuppyTypeInferenceError(err)
|
|
1225
|
+
return [subst[v].to_arg() for v in free_vars]
|
|
1226
|
+
|
|
1227
|
+
|
|
1194
1228
|
def check_inst(func_ty: FunctionType, inst: Inst, node: AstNode) -> None:
|
|
1195
1229
|
"""Checks if an instantiation is valid.
|
|
1196
1230
|
|
|
1197
1231
|
Makes sure that the linearity requirements are satisfied.
|
|
1198
1232
|
"""
|
|
1199
1233
|
for param, arg in zip(func_ty.params, inst, strict=True):
|
|
1234
|
+
param = param.instantiate_bounds(inst)
|
|
1235
|
+
|
|
1200
1236
|
# Give a more informative error message for linearity issues
|
|
1201
1237
|
if isinstance(param, TypeParam) and isinstance(arg, TypeArg):
|
|
1202
1238
|
if param.must_be_copyable and not arg.ty.copyable:
|
|
@@ -276,7 +276,7 @@ def check_signature(
|
|
|
276
276
|
param_var_mapping: dict[str, Parameter] = {}
|
|
277
277
|
if sys.version_info >= (3, 12):
|
|
278
278
|
for i, param_node in enumerate(func_def.type_params):
|
|
279
|
-
param = parse_parameter(param_node, i, globals)
|
|
279
|
+
param = parse_parameter(param_node, i, globals, param_var_mapping)
|
|
280
280
|
param_var_mapping[param.name] = param
|
|
281
281
|
|
|
282
282
|
# Figure out if this is a method
|
|
@@ -52,6 +52,7 @@ from guppylang_internals.error import GuppyError, GuppyTypeError
|
|
|
52
52
|
from guppylang_internals.nodes import (
|
|
53
53
|
AnyCall,
|
|
54
54
|
BarrierExpr,
|
|
55
|
+
CheckedModifiedBlock,
|
|
55
56
|
CheckedNestedFunctionDef,
|
|
56
57
|
DesugaredArrayComp,
|
|
57
58
|
DesugaredGenerator,
|
|
@@ -621,6 +622,70 @@ class BBLinearityChecker(ast.NodeVisitor):
|
|
|
621
622
|
elif not place.ty.copyable:
|
|
622
623
|
raise GuppyTypeError(ComprAlreadyUsedError(use.node, place, use.kind))
|
|
623
624
|
|
|
625
|
+
def visit_CheckedModifiedBlock(self, node: CheckedModifiedBlock) -> None:
|
|
626
|
+
# Linear usage of variables in a with statement
|
|
627
|
+
# ```
|
|
628
|
+
# with control(c1, c2, ...):
|
|
629
|
+
# body(q1, q2, ...) # captured variables
|
|
630
|
+
# ````
|
|
631
|
+
# is the same as to assume that this is a function call
|
|
632
|
+
# `WithCtrl(q1, q2, ..., c1, c2, ...)`
|
|
633
|
+
# where `WithCtrl` is a function that takes the control as mutable references.
|
|
634
|
+
# Therefore, we apply the same linearity rules as for function arguments.
|
|
635
|
+
# ```
|
|
636
|
+
# def WithCtrl(q1, q2, ..., c1, c2, ...):
|
|
637
|
+
# body(q1, q2, ...)
|
|
638
|
+
# ```
|
|
639
|
+
|
|
640
|
+
# check control
|
|
641
|
+
for ctrl in node.control:
|
|
642
|
+
for arg in ctrl.ctrl:
|
|
643
|
+
if isinstance(arg, PlaceNode):
|
|
644
|
+
self.visit_PlaceNode(arg, use_kind=UseKind.BORROW, is_call_arg=None)
|
|
645
|
+
else:
|
|
646
|
+
ty = get_type(arg)
|
|
647
|
+
unnamed_err = UnnamedExprNotUsedError(arg, ty)
|
|
648
|
+
unnamed_err.add_sub_diagnostic(UnnamedExprNotUsedError.Fix(None))
|
|
649
|
+
raise GuppyTypeError(unnamed_err)
|
|
650
|
+
|
|
651
|
+
# check power
|
|
652
|
+
for power in node.power:
|
|
653
|
+
if isinstance(power.iter, PlaceNode):
|
|
654
|
+
self.visit_PlaceNode(
|
|
655
|
+
power.iter, use_kind=UseKind.CONSUME, is_call_arg=None
|
|
656
|
+
)
|
|
657
|
+
else:
|
|
658
|
+
self.visit(power.iter)
|
|
659
|
+
|
|
660
|
+
# check captured variables
|
|
661
|
+
for var, use in node.captured.values():
|
|
662
|
+
for place in leaf_places(var):
|
|
663
|
+
use_kind = (
|
|
664
|
+
UseKind.BORROW if InputFlags.Inout in var.flags else UseKind.CONSUME
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
x = place.id
|
|
668
|
+
if (prev_use := self.scope.used(x)) and not place.ty.copyable:
|
|
669
|
+
used_err = AlreadyUsedError(use, place, use_kind)
|
|
670
|
+
used_err.add_sub_diagnostic(
|
|
671
|
+
AlreadyUsedError.PrevUse(prev_use.node, prev_use.kind)
|
|
672
|
+
)
|
|
673
|
+
if has_explicit_copy(place.ty):
|
|
674
|
+
used_err.add_sub_diagnostic(AlreadyUsedError.MakeCopy(None))
|
|
675
|
+
raise GuppyError(used_err)
|
|
676
|
+
self.scope.use(x, node, use_kind)
|
|
677
|
+
|
|
678
|
+
# reassign controls
|
|
679
|
+
for ctrl in node.control:
|
|
680
|
+
for arg in ctrl.ctrl:
|
|
681
|
+
assert isinstance(arg, PlaceNode) # Checked above
|
|
682
|
+
self._reassign_single_inout_arg(arg.place, arg.place.defined_at or arg)
|
|
683
|
+
|
|
684
|
+
# reassign captured variables
|
|
685
|
+
for var, use in node.captured.values():
|
|
686
|
+
if InputFlags.Inout in var.flags:
|
|
687
|
+
self._reassign_single_inout_arg(var, var.defined_at or use)
|
|
688
|
+
|
|
624
689
|
|
|
625
690
|
def leaf_places(place: Place) -> Iterator[Place]:
|
|
626
691
|
"""Returns all leaf descendant projections of a place."""
|