Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Turn py expression lists into arrays #697

Merged
merged 2 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions guppylang/checker/expr_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
from guppylang.span import Span, to_span
from guppylang.tys.arg import TypeArg
from guppylang.tys.builtin import (
array_type,
bool_type,
get_element_type,
is_bool_type,
Expand Down Expand Up @@ -1171,7 +1172,7 @@ def _python_list_to_guppy_type(
representable in Guppy.
"""
if len(vs) == 0:
return list_type(ExistentialTypeVar.fresh("T", False))
return array_type(ExistentialTypeVar.fresh("T", False), 0)

# All the list elements must have a unifiable types
v, *rest = vs
Expand All @@ -1185,4 +1186,4 @@ def _python_list_to_guppy_type(
if (subst := unify(ty, el_ty, {})) is None:
raise GuppyError(PyExprIncoherentListError(node))
el_ty = el_ty.substitute(subst)
return list_type(el_ty)
return array_type(el_ty, len(vs))
15 changes: 11 additions & 4 deletions guppylang/compiler/expr_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from hugr import val as hv
from hugr.build.cond_loop import Conditional
from hugr.build.dfg import DP, DfBase
from hugr.std.collections import ListVal
from typing_extensions import assert_never

from guppylang.ast_util import AstNode, AstVisitor, get_type
Expand Down Expand Up @@ -55,8 +54,8 @@
from guppylang.tys.builtin import (
get_element_type,
int_type,
is_array_type,
is_bool_type,
is_list_type,
)
from guppylang.tys.const import BoundConstVar, ConstValue, ExistentialConstVar
from guppylang.tys.subst import Inst
Expand Down Expand Up @@ -601,10 +600,18 @@ def python_value_to_hugr(v: Any, exp_ty: Type) -> hv.Value | None:
if doesnt_contain_none(vs):
return hv.Tuple(*vs)
case list(elts):
assert is_list_type(exp_ty)
assert is_array_type(exp_ty)
vs = [python_value_to_hugr(elt, get_element_type(exp_ty)) for elt in elts]
if doesnt_contain_none(vs):
return ListVal(vs, get_element_type(exp_ty).to_hugr())
# TODO: Use proper array value: https://github.com/CQCL/hugr/issues/1497
return hv.Extension(
name="ArrayValue",
typ=exp_ty.to_hugr(),
# The value list must be serialized at this point, otherwise the
# `Extension` value would not be serializable.
val=[v._to_serial_root() for v in vs],
extensions=["unsupported"],
)
case _:
# TODO replace with hugr protocol handling: https://github.com/CQCL/guppylang/issues/563
# Pytket conversion is an experimental feature
Expand Down
2 changes: 1 addition & 1 deletion tests/error/py_errors/list_empty.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ Error: Cannot infer type (at $FILE:6:9)
5 | def foo() -> None:
6 | xs = py([])
| ^^^^^^ Cannot infer type variables in expression of type
| `list[?T]`
| `array[?T, 0]`

Guppy compilation failed due to 1 previous error
8 changes: 4 additions & 4 deletions tests/integration/test_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def foo() -> int:

def test_list_basic(validate):
@compile_guppy
def foo() -> list[int]:
def foo() -> array[int, 3]:
xs = py([1, 2, 3])
return xs

Expand All @@ -85,7 +85,7 @@ def foo() -> list[int]:

def test_list_empty(validate):
@compile_guppy
def foo() -> list[int]:
def foo() -> array[int, 0]:
return py([])

validate(foo)
Expand All @@ -94,15 +94,15 @@ def foo() -> list[int]:
def test_list_empty_nested(validate):
@compile_guppy
def foo() -> None:
xs: list[tuple[int, list[bool]]] = py([(42, [])])
xs: array[tuple[int, array[bool, 0]], 1] = py([(42, [])])

validate(foo)


def test_list_empty_multiple(validate):
@compile_guppy
def foo() -> None:
xs: tuple[list[int], list[bool]] = py([], [])
xs: tuple[array[int, 0], array[bool, 0]] = py([], [])

validate(foo)

Expand Down
Loading