From ad60a70c6da158d9d60b216103ee1a0ac274b4ea Mon Sep 17 00:00:00 2001 From: Andrew Porter Date: Tue, 17 Jun 2025 10:22:04 +0100 Subject: [PATCH 1/3] #466 fix bug in match for implicit loop in array constructor --- src/fparser/two/Fortran2003.py | 19 +++++++++++++++---- .../test_array_constructor_implied_do_r470.py | 14 +++++++++++++- .../two/tests/fortran2003/test_intrinsics.py | 13 ++++++++++++- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/fparser/two/Fortran2003.py b/src/fparser/two/Fortran2003.py index 64b6291ef..e20407e26 100644 --- a/src/fparser/two/Fortran2003.py +++ b/src/fparser/two/Fortran2003.py @@ -2945,13 +2945,24 @@ class Ac_Implied_Do(Base): use_names = ["Ac_Value_List", "Ac_Implied_Do_Control"] @staticmethod - def match(string): + def match(string: str): + """ + Attempts to match the supplied string as an implicit do within an + array constructor. + + :param string: the text to match against. + + :returns: a tuple describing the match or None if there is no match. + :rtype: Optional[Tuple[Ac_Value_List, Ac_Implied_Do_Control]] + + """ if string[0] + string[-1] != "()": - return + return None line, repmap = string_replace_map(string[1:-1].strip()) i = line.rfind("=") - if i == -1: - return + if i == -1 or (i > 0 and line[i-1] == "="): + # No "=" or it is "==" so no match. + return None j = line[:i].rfind(",") assert j != -1 s1 = repmap(line[:j].rstrip()) diff --git a/src/fparser/two/tests/fortran2003/test_array_constructor_implied_do_r470.py b/src/fparser/two/tests/fortran2003/test_array_constructor_implied_do_r470.py index 828c6c379..1f778125c 100644 --- a/src/fparser/two/tests/fortran2003/test_array_constructor_implied_do_r470.py +++ b/src/fparser/two/tests/fortran2003/test_array_constructor_implied_do_r470.py @@ -1,4 +1,4 @@ -# Copyright (c) 2020-2021 Science and Technology Facilities Council. +# Copyright (c) 2020-2025 Science and Technology Facilities Council. # # All rights reserved. # @@ -57,6 +57,18 @@ def test_implicit_loop_constructor_no_parentheses(): assert ast is None +@pytest.mark.usefixtures("f2003_create") +def test_no_implicit_loop_constructor_with_is_equal_to(): + """Test that the parser does not match an implicit loop if the + array constructor contains '=='.""" + fcode = "(/lval1, ival1==ival2/)" + reader = FortranStringReader(fcode) + ast = Fortran2003.Array_Constructor(reader) + # Should have an array constructor without an implicit loop. + assert isinstance(ast, Fortran2003.Array_Constructor) + assert isinstance(ast.children[1], Fortran2003.Ac_Value_List) + + @pytest.mark.xfail(reason="#257 Constraint C497 is not checked.") @pytest.mark.usefixtures("f2003_create") def test_nested_implied_do(): diff --git a/src/fparser/two/tests/fortran2003/test_intrinsics.py b/src/fparser/two/tests/fortran2003/test_intrinsics.py index 61938b8a8..21a5270b0 100644 --- a/src/fparser/two/tests/fortran2003/test_intrinsics.py +++ b/src/fparser/two/tests/fortran2003/test_intrinsics.py @@ -1,7 +1,7 @@ # ----------------------------------------------------------------------------- # BSD 3-Clause License # -# Copyright (c) 2019-2023, Science and Technology Facilities Council. +# Copyright (c) 2019-2025, Science and Technology Facilities Council. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -206,6 +206,17 @@ def test_intrinsic_function_reference_unlimited_args(): assert str(result) == f"MAX({args})" +@pytest.mark.usefixtures("f2003_create") +def test_intrinsic_function_reference_all_args(): + """Check that we match a call to ALL containing an array constructor + of logical type. + + """ + code = "all( (/ var1, var2, (i1==i2) /) )" + result = Intrinsic_Function_Reference(code) + assert isinstance(result, Intrinsic_Function_Reference) + + @pytest.mark.usefixtures("f2003_create") def test_intrinsic_function_reference_error1(): """Test that class Intrinsic_Function_Reference raises the expected From adf36ceec09767c10d3e69c0c2f207e3cdb9a762 Mon Sep 17 00:00:00 2001 From: Andrew Porter Date: Tue, 17 Jun 2025 10:22:48 +0100 Subject: [PATCH 2/3] #466 fix Black formatting --- src/fparser/two/Fortran2003.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fparser/two/Fortran2003.py b/src/fparser/two/Fortran2003.py index e20407e26..93c919cc5 100644 --- a/src/fparser/two/Fortran2003.py +++ b/src/fparser/two/Fortran2003.py @@ -2960,7 +2960,7 @@ def match(string: str): return None line, repmap = string_replace_map(string[1:-1].strip()) i = line.rfind("=") - if i == -1 or (i > 0 and line[i-1] == "="): + if i == -1 or (i > 0 and line[i - 1] == "="): # No "=" or it is "==" so no match. return None j = line[:i].rfind(",") From 2a0cabcea4d39e76a66fd113ae29b91e81a624dc Mon Sep 17 00:00:00 2001 From: LonelyCat124 <3043914+LonelyCat124@users.noreply.github.com.> Date: Mon, 21 Jul 2025 09:20:40 +0100 Subject: [PATCH 3/3] Updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8431dd782..f8074f681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ Modifications by (in alphabetical order): * P. Vitt, University of Siegen, Germany * A. Voysey, UK Met Office +21/07/2025 PR #467 for #466. Fix "==" when matching implicit loops in array constructors. + 26/06/2025 PR #471 for #470. Drop support for Python 3.7 and 3.8. 25/06/2025 PR #459 for #458. Improvements to the 'make public' example script.