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

MatchOr and guard statements #158

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
77da54b
wrote a basic test that calls visit_Match
juliawgraham Dec 4, 2022
c213d0f
added extra space to publish branch
juliawgraham Dec 4, 2022
73425a6
implementation for MatchValue
Yuqi07 Dec 4, 2022
adb9a50
partial implementation for MatchAs, only implemented for the wildcard…
Yuqi07 Dec 4, 2022
f64490e
changed test names for matchas tests
Yuqi07 Dec 4, 2022
4aa1195
1. merged visit match_case to visit Match; 2. added wildcards error h…
Yuqi07 Dec 7, 2022
607c359
1. removed unused i; 2. added error handling for multiple statements …
Yuqi07 Dec 7, 2022
33f7439
created a function visit_MatchOr, still needs to be implemented
erica-w-fu Dec 7, 2022
a57b6a8
updated matchcase to accept inequalities
juliawgraham Dec 9, 2022
e1d90f9
added support for and/or in guard
juliawgraham Dec 9, 2022
64a281c
matchor implemented with tests
Lucybean-hi Dec 9, 2022
4ab48e8
Merge branch 'integration' into matchand
erica-w-fu Dec 9, 2022
2dbcf03
added requirements for python version 3.10 for all test cases with match
erica-w-fu Dec 9, 2022
62a4633
updated formatting using flake/black
juliawgraham Dec 9, 2022
fc0372a
Merge branch 'integration' into matchand
erica-w-fu Dec 9, 2022
ad11197
Merge pull request #2 from erica-w-fu/matchand
erica-w-fu Dec 9, 2022
5b6e676
updated syntax according to flake/black (after merging match_case gua…
juliawgraham Dec 9, 2022
0a55289
Merge pull request #1 from google/main
juliawgraham Dec 11, 2022
f300ee7
Merge branch 'integration' into updatedMain
juliawgraham Dec 11, 2022
c047696
Moved matchor / match guard test cases into function_codegen_match_test
juliawgraham Dec 11, 2022
3b78dd7
Merge pull request #3 from erica-w-fu/updatedMain
juliawgraham Dec 11, 2022
fc4eca9
updated everything so it's consistent with main
Yuqi07 Dec 11, 2022
1a1cefe
resolved all comments on our latest PR
Yuqi07 Dec 11, 2022
befd6dc
fixed all CI errors, now all tests passed
Yuqi07 Dec 11, 2022
efd60f8
Update src/latexify/codegen/function_codegen.py
Lucybean-hi Dec 11, 2022
7b67262
Update src/latexify/codegen/function_codegen.py
Lucybean-hi Dec 11, 2022
33327a3
Update src/latexify/codegen/function_codegen.py
Lucybean-hi Dec 11, 2022
587c50b
Update src/latexify/codegen/function_codegen.py
Lucybean-hi Dec 11, 2022
ee82180
addressed all comments
Yuqi07 Dec 11, 2022
4db2356
fixed flake errors
Yuqi07 Dec 11, 2022
ccb0c5d
Added spaces to conditionals in tests
juliawgraham Dec 11, 2022
2d5807e
Added more spaces to conditionals in tests
juliawgraham Dec 11, 2022
fd2ddee
fixed style errors and removed guard
Yuqi07 Dec 15, 2022
0daeb72
used _match_subject_stack as suggested
Yuqi07 Dec 15, 2022
3cf0b0e
Merge branch 'main' into integration
Yuqi07 Dec 15, 2022
2019d4b
fixed unit tests, adding cdot back
Yuqi07 Dec 15, 2022
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
28 changes: 20 additions & 8 deletions src/latexify/codegen/function_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def __init__(
use_math_symbols: bool = False,
use_signature: bool = True,
use_set_symbols: bool = False,
_match_subject_stack: list[str] = [],
) -> None:
"""Initializer.

Expand All @@ -34,6 +35,7 @@ def __init__(
use_signature: Whether to add the function signature before the expression
or not.
use_set_symbols: Whether to use set symbols or not.
_match_subject_stack: a stack of subject names that are used in match
"""
self._expression_codegen = expression_codegen.ExpressionCodegen(
use_math_symbols=use_math_symbols, use_set_symbols=use_set_symbols
Expand All @@ -42,6 +44,7 @@ def __init__(
use_math_symbols=use_math_symbols
)
self._use_signature = use_signature
self._match_subject_stack = _match_subject_stack

def generic_visit(self, node: ast.AST) -> str:
raise exceptions.LatexifyNotSupportedError(
Expand Down Expand Up @@ -140,7 +143,10 @@ def visit_If(self, node: ast.If) -> str:
return latex + r", & \mathrm{otherwise} \end{array} \right."

def visit_Match(self, node: ast.Match) -> str:
"""Visit a Match node"""
"""Visit a Match node."""
subject_latex = self._expression_codegen.visit(node.subject)
self._match_subject_stack.append(subject_latex)

if not (
len(node.cases) >= 2
and isinstance(node.cases[-1].pattern, ast.MatchAs)
Expand All @@ -162,21 +168,27 @@ def visit_Match(self, node: ast.Match) -> str:
if i < len(node.cases) - 1:
odashi marked this conversation as resolved.
Show resolved Hide resolved
body_latex = self.visit(case.body[0])
cond_latex = self.visit(case.pattern)
case_latexes.append(
body_latex + r", & \mathrm{if} \ " + subject_latex + cond_latex
)

case_latexes.append(body_latex + r", & \mathrm{if} \ " + cond_latex)
else:
case_latexes.append(
self.visit(node.cases[-1].body[0]) + r", & \mathrm{otherwise}"
self.visit(case.body[0]) + r", & \mathrm{otherwise}"
)

return (
latex = (
r"\left\{ \begin{array}{ll} "
erica-w-fu marked this conversation as resolved.
Show resolved Hide resolved
+ r" \\ ".join(case_latexes)
+ r" \end{array} \right."
)

self._match_subject_stack.pop()
return latex

def visit_MatchValue(self, node: ast.MatchValue) -> str:
"""Visit a MatchValue node"""
"""Visit a MatchValue node."""
latex = self._expression_codegen.visit(node.value)
return " = " + latex
return self._match_subject_stack[-1] + " = " + latex

def visit_MatchOr(self, node: ast.MatchOr) -> str:
"""Visit a MatchOr node."""
return r" \lor ".join(self.visit(p) for p in node.patterns)
50 changes: 25 additions & 25 deletions src/latexify/codegen/function_codegen_match_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


@test_utils.require_at_least(10)
def test_functiondef_match() -> None:
def test_visit_functiondef_match() -> None:
tree = ast.parse(
textwrap.dedent(
"""
Expand All @@ -27,16 +27,16 @@ def f(x):
)
expected = (
r"f(x) ="
r" \left\{ \begin{array}{ll}"
r" 1, & \mathrm{if} \ x = 0 \\"
r" \left\{ \begin{array}{ll} "
r"1, & \mathrm{if} \ x = 0 \\"
r" 3 \cdot x, & \mathrm{otherwise}"
r" \end{array} \right."
)
assert function_codegen.FunctionCodegen().visit(tree) == expected


@test_utils.require_at_least(10)
def test_matchvalue() -> None:
def test_visit_match() -> None:
erica-w-fu marked this conversation as resolved.
Show resolved Hide resolved
tree = ast.parse(
textwrap.dedent(
"""
Expand All @@ -49,16 +49,16 @@ def test_matchvalue() -> None:
)
).body[0]
expected = (
r"\left\{ \begin{array}{ll}"
r" 1, & \mathrm{if} \ x = 0 \\"
r"\left\{ \begin{array}{ll} "
r"1, & \mathrm{if} \ x = 0 \\"
r" 2, & \mathrm{otherwise}"
r" \end{array} \right."
)
assert function_codegen.FunctionCodegen().visit(tree) == expected


@test_utils.require_at_least(10)
def test_multiple_matchvalue() -> None:
def test_visit_multiple_match_cases() -> None:
tree = ast.parse(
textwrap.dedent(
"""
Expand All @@ -73,8 +73,8 @@ def test_multiple_matchvalue() -> None:
)
).body[0]
expected = (
r"\left\{ \begin{array}{ll}"
r" 1, & \mathrm{if} \ x = 0 \\"
r"\left\{ \begin{array}{ll} "
r"1, & \mathrm{if} \ x = 0 \\"
r" 2, & \mathrm{if} \ x = 1 \\"
r" 3, & \mathrm{otherwise}"
r" \end{array} \right."
Expand All @@ -83,7 +83,7 @@ def test_multiple_matchvalue() -> None:


@test_utils.require_at_least(10)
def test_single_matchvalue_no_wildcards() -> None:
def test_visit_single_match_case_no_wildcards() -> None:
tree = ast.parse(
textwrap.dedent(
"""
Expand All @@ -102,7 +102,7 @@ def test_single_matchvalue_no_wildcards() -> None:


@test_utils.require_at_least(10)
def test_multiple_matchvalue_no_wildcards() -> None:
def test_visit_multiple_match_cases_no_wildcards() -> None:
tree = ast.parse(
textwrap.dedent(
"""
Expand All @@ -123,34 +123,35 @@ def test_multiple_matchvalue_no_wildcards() -> None:


@test_utils.require_at_least(10)
def test_matchas_nonempty() -> None:
def test_visit_match_case_no_return() -> None:
tree = ast.parse(
textwrap.dedent(
"""
match x:
case [x] as y:
return 1
case 0:
x = 5
case _:
return 2
return 0
"""
)
).body[0]

with pytest.raises(
exceptions.LatexifyNotSupportedError,
match=r"^Unsupported AST: MatchAs$",
match=r"^Match cases must contain exactly 1 return statement\.$",
):
function_codegen.FunctionCodegen().visit(tree)


@test_utils.require_at_least(10)
def test_matchvalue_no_return() -> None:
def test_visit_match_case_mutliple_statements() -> None:
tree = ast.parse(
textwrap.dedent(
"""
match x:
case 0:
x = 5
return 1
case _:
return 0
"""
Expand All @@ -165,22 +166,21 @@ def test_matchvalue_no_return() -> None:


@test_utils.require_at_least(10)
def test_matchvalue_mutliple_statements() -> None:
def test_visit_match_case_or() -> None:
tree = ast.parse(
textwrap.dedent(
"""
match x:
case 0:
x = 5
case 0 | 1:
return 1
case _:
return 0
return 2
"""
)
).body[0]

with pytest.raises(
exceptions.LatexifyNotSupportedError,
match=r"^Match cases must contain exactly 1 return statement\.$",
):
assert (
function_codegen.FunctionCodegen().visit(tree)
== r"\left\{ \begin{array}{ll} 1, & \mathrm{if} \ x = 0 \lor x = 1 \\"
+ r" 2, & \mathrm{otherwise} \end{array} \right."
)