From 16025cea0df829f0f03d1ce92f0e48f06395877c Mon Sep 17 00:00:00 2001 From: Christopher Albert Date: Sun, 23 Nov 2025 10:42:10 +0100 Subject: [PATCH 1/3] fix: emit modern array constructor syntax for implied-do loops (fixes #2460) - Change implied-do array constructor emission from legacy (/ /) to modern [ ] syntax - Remove extra parentheses from inner expression generation - Ensures roundtrip stability: [(i, i=1, 10)] stays as [(i, i=1, 10)] - Legacy syntax (/(i, i=1, 10) /) was not parsing correctly on roundtrip - Modern syntax works reliably with fortfront parser This fixes the array_constructor_31 test case and similar patterns. --- src/codegen/codegen_expressions_part2.inc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/codegen/codegen_expressions_part2.inc b/src/codegen/codegen_expressions_part2.inc index b80f44a3..213e9196 100644 --- a/src/codegen/codegen_expressions_part2.inc +++ b/src/codegen/codegen_expressions_part2.inc @@ -267,30 +267,30 @@ step_code = generate_code_from_arena(arena, node%step_expr_index) step_code = trim(step_code) if (allocated(node%var_name)) then - inner = "(" // expr_code // ", " // node%var_name // "=" // & - start_code // ", " // end_code // ", " // step_code // ")" + inner = expr_code // ", " // node%var_name // "=" // & + start_code // ", " // end_code // ", " // step_code else - inner = "(" // expr_code // ", i=" // start_code // ", " // & - end_code // ", " // step_code // ")" + inner = expr_code // ", i=" // start_code // ", " // & + end_code // ", " // step_code end if else if (allocated(node%var_name)) then - inner = "(" // expr_code // ", " // node%var_name // "=" // & - start_code // ", " // end_code // ")" + inner = expr_code // ", " // node%var_name // "=" // & + start_code // ", " // end_code else - inner = "(" // expr_code // ", i=" // start_code // ", " // & - end_code // ")" + inner = expr_code // ", i=" // start_code // ", " // & + end_code end if end if if (present(type_spec)) then if (len_trim(type_spec) > 0) then - code = "(/ " // trim(type_spec) // " :: " // trim(inner) // " /)" + code = "[" // trim(type_spec) // " :: (" // trim(inner) // ")]" else - code = "(/ " // trim(inner) // " /)" + code = "[(" // trim(inner) // ")]" end if else - code = "(/ " // trim(inner) // " /)" + code = "[(" // trim(inner) // ")]" end if class default ! Not a do loop node - fallback From f3a991819fab6a5416c45ef092267db17772ee0b Mon Sep 17 00:00:00 2001 From: Christopher Albert Date: Sun, 23 Nov 2025 10:45:42 +0100 Subject: [PATCH 2/3] test: update implied-do tests to expect modern syntax - Updated test assertions to expect [(expr, var=start, end)] syntax - Legacy (/ /) syntax tests still validate input but expect modern output - Partial update - some tests may still need adjustment --- .../feature_tests/test_implied_do_loops.f90 | 10 +++++----- .../test_issue_1575_implied_do_array_constructor.f90 | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/integration/feature_tests/test_implied_do_loops.f90 b/test/integration/feature_tests/test_implied_do_loops.f90 index 703348f8..62883f0d 100644 --- a/test/integration/feature_tests/test_implied_do_loops.f90 +++ b/test/integration/feature_tests/test_implied_do_loops.f90 @@ -23,12 +23,12 @@ subroutine test_simple_implied_do() error stop 1 end if - ! The generated code should use legacy (/ /) syntax for compatibility - if (contains_without_spaces(output, "(/(i,i=1,5)/)")) then + ! The generated code should use modern [...] syntax for compatibility + if (contains_without_spaces(output, "[(i,i=1,5)]")) then print *, " PASS: Simple implied do loop" else print *, " FAIL: Simple implied do loop - Expected" // & - " (/ (i, i=1, 5) /) syntax" + " [(i, i=1, 5)] syntax" print *, " Got:", trim(output) error stop 1 end if @@ -45,11 +45,11 @@ subroutine test_complex_implied_do() error stop 1 end if - if (contains_without_spaces(output, "sum((/(i*2,i=1,10)/))")) then + if (contains_without_spaces(output, "sum([(i*2,i=1,10)])")) then print *, " PASS: Implied do with expression" else print *, " FAIL: Implied do with expression - Expected" // & - " sum((/ (i*2, i=1, 10) /))" + " sum([(i*2, i=1, 10)])" print *, " Got:", trim(output) error stop 1 end if diff --git a/test/integration/issue_tests/test_issue_1575_implied_do_array_constructor.f90 b/test/integration/issue_tests/test_issue_1575_implied_do_array_constructor.f90 index b42efc2a..199d0df5 100644 --- a/test/integration/issue_tests/test_issue_1575_implied_do_array_constructor.f90 +++ b/test/integration/issue_tests/test_issue_1575_implied_do_array_constructor.f90 @@ -20,7 +20,7 @@ program test_issue_1575_implied_do_array_constructor end if end if - if (index(transformed, 'arr = (/(i*2, i=1, 10) /)') == 0) then + if (index(transformed, 'arr = [(i*2, i=1, 10)]') == 0) then print *, 'FAIL: implied-do constructor lost' print *, 'Output:' print *, trim(transformed) From 1d2f60205cff841801cba10eb109ceb27f8f0954 Mon Sep 17 00:00:00 2001 From: Christopher Albert Date: Sun, 23 Nov 2025 10:58:47 +0100 Subject: [PATCH 3/3] fix: address review findings (#2485) --- .../test_issue_1580_dimension_statement.f90 | 7 ++++--- .../feature_tests/test_implied_do_loops.f90 | 13 +++++++------ .../issue_tests/test_issue_1777_negative_stride.f90 | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/test/frontend/test_issue_1580_dimension_statement.f90 b/test/frontend/test_issue_1580_dimension_statement.f90 index 8e1319c2..651e9474 100644 --- a/test/frontend/test_issue_1580_dimension_statement.f90 +++ b/test/frontend/test_issue_1580_dimension_statement.f90 @@ -1,5 +1,6 @@ program test_issue_1580_dimension_statement use transformation_api, only: transform_lazy_fortran_string + implicit none call run_dimension_conversion_test() print *, "" @@ -46,11 +47,11 @@ subroutine run_dimension_conversion_test() error stop 1 end if - has_assignment = index(output_code, "arr1 = (/(i, i=1,10)/)") > 0 + has_assignment = index(output_code, "arr1 = [(i, i=1,10)]") > 0 has_assignment = has_assignment .or. & - index(output_code, "arr1 = (/(i, i=1, 10) /)") > 0 + index(output_code, "arr1 = [(i, i=1, 10)]") > 0 has_assignment = has_assignment .or. & - index(output_code, "arr1 = (/(i, i = 1, 10) /)") > 0 + index(output_code, "arr1 = [(i, i = 1, 10)]") > 0 if (.not. has_assignment) then print *, "FAIL: array constructor assignment not preserved" diff --git a/test/integration/feature_tests/test_implied_do_loops.f90 b/test/integration/feature_tests/test_implied_do_loops.f90 index 62883f0d..65419dc3 100644 --- a/test/integration/feature_tests/test_implied_do_loops.f90 +++ b/test/integration/feature_tests/test_implied_do_loops.f90 @@ -1,5 +1,6 @@ program test_implied_do_loops use transformation_api, only: transform_lazy_fortran_string + implicit none character(len=:), allocatable :: output, error_msg write (*, '(A)') "=== Testing Implied Do Loop Array Constructors ===" @@ -58,13 +59,13 @@ end subroutine test_complex_implied_do subroutine test_nested_implied_do_levels() character(len=:), allocatable :: input character(len=*), parameter :: nested2_pattern = & - "reshape((/((i*10+j,j=1,3),i=1,3)/),[3,3])" + "reshape([((i*10+j,j=1,3),i=1,3)],[3,3])" character(len=*), parameter :: nested3_pattern = & - "reshape((/(((i*100+j*10+k,k=1,3),j=1,3),i=1,3)/),[3,3,3])" + "reshape([(((i*100+j*10+k,k=1,3),j=1,3),i=1,3)],[3,3,3])" character(len=*), parameter :: nested2_expect = & - "reshape((/((i*10 + j, j=1, 3), i=1, 3) /), [3, 3])" + "reshape([((i*10 + j, j=1, 3), i=1, 3)], [3, 3])" character(len=*), parameter :: nested3_expect = & - "reshape((/(((i*100 + j*10 + k, k=1, 3), j=1, 3), i=1, 3) /), " // & + "reshape([(((i*100 + j*10 + k, k=1, 3), j=1, 3), i=1, 3)], " // & "[3, 3, 3])" input = 'matrix = reshape([((i*10 + j, j=1,3), i=1,3)], [3,3])' @@ -114,10 +115,10 @@ subroutine test_nested_function_with_implied_do() error stop 1 end if - if (contains_without_spaces(output, "(/(sqrt(real(i)),i=1,5)/)")) then + if (contains_without_spaces(output, "[(sqrt(real(i)),i=1,5)]")) then print *, " PASS: Nested functions with implied do" else - print *, " FAIL: Nested functions with implied do - Expected legacy syntax" + print *, " FAIL: Nested functions with implied do - Expected modern syntax" print *, " Got:", trim(output) error stop 1 end if diff --git a/test/integration/issue_tests/test_issue_1777_negative_stride.f90 b/test/integration/issue_tests/test_issue_1777_negative_stride.f90 index dc5f7815..0528728c 100644 --- a/test/integration/issue_tests/test_issue_1777_negative_stride.f90 +++ b/test/integration/issue_tests/test_issue_1777_negative_stride.f90 @@ -25,7 +25,7 @@ program test_issue_1777_negative_stride stop 1 end if - if (index(transformed, '(/(i, i=10, 1, -2) /)') == 0) then + if (index(transformed, '[(i, i=10, 1, -2)]') == 0) then print *, 'FAIL: implied-do with negative stride lost' print *, 'Output:' print *, trim(transformed)