Skip to content

Commit e528122

Browse files
committed
#2923 Convert logical sympy expressions back to PSyIR.
1 parent 600311a commit e528122

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

src/psyclone/psyir/frontend/sympy_reader.py

+30-1
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,37 @@
3737
'''PSyIR frontend to convert a SymPy expression to PSyIR
3838
'''
3939

40+
from sympy.printing.printer import Printer
4041

4142
from psyclone.psyir.frontend.fortran import FortranReader
4243

4344

45+
# pylint: disable=invalid-name
46+
class FortranPrinter(Printer):
47+
'''A helper class that converts Fortran logical operators back
48+
to Fortran format (while SymPy has a Fortran printer (fcode) does this
49+
as well, it does not handle e.g. Fortran Array expressions (a(2:5)),
50+
so we need to use the not-Fortran-aware output to a normal string,
51+
but handle logical operators separately.
52+
'''
53+
def _print_And(self, expr):
54+
'''Called when converting an AND expression.'''
55+
return f"({'.AND.' .join(self._print(i) for i in expr.args)})"
56+
57+
def _print_Or(self, expr):
58+
'''Called when converting an OR expression.'''
59+
return f"({'.OR.' .join(self._print(i) for i in expr.args)})"
60+
61+
def _print_Equivalent(self, expr):
62+
'''Called when converting an EQUIVALENT expression.'''
63+
return f"({'.EQV.' .join(self._print(i) for i in expr.args)})"
64+
65+
def _print_Xor(self, expr):
66+
'''Called when converting an XOR expression, which in Fortran
67+
is NEQV.'''
68+
return f"({'.NEQV.' .join(self._print(i) for i in expr.args)})"
69+
70+
4471
class SymPyReader():
4572
'''This class converts a SymPy expression, that was created by the
4673
SymPyWriter, back to PSyIR. It basically allows to use SymPy to modify
@@ -121,7 +148,9 @@ def psyir_from_expression(self, sympy_expr, symbol_table):
121148
'''
122149
# Convert the new sympy expression to PSyIR
123150
reader = FortranReader()
124-
return reader.psyir_from_expression(str(sympy_expr), symbol_table)
151+
fp = FortranPrinter()
152+
return reader.psyir_from_expression(fp.doprint(sympy_expr),
153+
symbol_table)
125154

126155
# -------------------------------------------------------------------------
127156
# pylint: disable=no-self-argument, too-many-branches

src/psyclone/tests/psyir/frontend/sympy_reader_test.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ def test_sympy_reader_constructor():
7373
("b(:5:2)", "b(:5:2)"),
7474
("b(2:5:1)", "b(2:5)"),
7575
("b(2:5:2)", "b(2:5:2)"),
76+
("i .and. j", "i .AND. j"),
77+
("i .and. j .and. k",
78+
"i .AND. j .AND. k"),
79+
("i .or. j", "i .OR. j"),
80+
# Precedence requires the ()
81+
("i .and. (i .or. j)",
82+
"i .AND. (i .OR. j)"),
83+
# Precedence rules discard the ()
84+
("i .or. (i .and. j)",
85+
"i .OR. i .AND. j"),
86+
("i .eqv. j", "i .EQV. j"),
87+
("i .neqv. j", "i .NEQV. j"),
7688
])
7789
def test_sympy_psyir_from_expression(fortran_reader, fortran_writer,
7890
expressions):
@@ -87,7 +99,7 @@ def test_sympy_psyir_from_expression(fortran_reader, fortran_writer,
8799
'''
88100
source = f'''program test_prog
89101
use my_mod
90-
integer :: i, j
102+
integer :: i, j, k
91103
integer :: a, b(10), c(10, 10)
92104
type(my_mod_type) :: d, e(10)
93105
x = {expressions[0]}

0 commit comments

Comments
 (0)