[COMMITTED] algol68: elaborate bounds in declarers only once

Jose E. Marchesi jemarch@gnu.org
Sun May 25 21:29:46 GMT 2025


The Revised language specified that when a declarer is used in several
generators, its constituent unit shall be elaborated only once.  This
happens in variable declarations:

  [n +:= 1]real a, b;

In the example above, the unit `n +:= 1' shall be evaluated only once,
and its result used twice in the two implicit generators for a and for
b.
---
 gcc/algol68/a68-low-generator.cc             | 45 +++++++++++++++-----
 gcc/algol68/a68-low-multiples.cc             |  4 +-
 gcc/testsuite/algol68/execute/declarer-2.a68 |  6 +++
 3 files changed, 43 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/algol68/execute/declarer-2.a68

diff --git a/gcc/algol68/a68-low-generator.cc b/gcc/algol68/a68-low-generator.cc
index 225346b248c..7c2e7327cf0 100644
--- a/gcc/algol68/a68-low-generator.cc
+++ b/gcc/algol68/a68-low-generator.cc
@@ -361,8 +361,10 @@ collect_bounds (NODE_T *p, LOW_CTX_T ctx)
 	  /* Now the upper bound.  */
 	  tree upper_bound = a68_lower_tree (p, ctx);
 
-	  a68_add_stmt (lower_bound);
-	  a68_add_stmt (upper_bound);
+	  /* See the comment for collect_declarer_bounds for an explanation for
+	     the usage of save_expr here.  */
+	  a68_add_stmt (save_expr (lower_bound));
+	  a68_add_stmt (save_expr (upper_bound));
 	}
     }
 }
@@ -371,7 +373,7 @@ collect_bounds (NODE_T *p, LOW_CTX_T ctx)
    list.  */
 
 static void
-collect_declarer_bounds (NODE_T *p, LOW_CTX_T ctx)
+collect_declarer_bounds_1 (NODE_T *p, LOW_CTX_T ctx)
 {
   for (; p != NO_NODE; FORWARD (p))
     {
@@ -383,14 +385,39 @@ collect_declarer_bounds (NODE_T *p, LOW_CTX_T ctx)
 	{
 	  if (TAX (p) != NO_TAG && HAS_ROWS (MOID (TAX (p))))
 	    /* Continue from definition at MODE A = ....  */
-	    collect_declarer_bounds (NEXT_NEXT (NODE (TAX (p))), ctx);
+	    collect_declarer_bounds_1 (NEXT_NEXT (NODE (TAX (p))), ctx);
 	}
       else if (IS (p, DECLARER)
 	       && (IS_UNION (MOID (p)) || !HAS_ROWS (MOID (p))))
 	  return;
       else
-	collect_declarer_bounds (SUB (p), ctx);
+	collect_declarer_bounds_1 (SUB (p), ctx);
+    }
+}
+
+/* Given a declarer node, return a statements list with all the expressions of
+   the bounds within it.
+
+   Note that the language rules mandates that the bounds expression shall be
+   evaluated just once even when they are used by several generators, such as
+   in
+
+     [n +:= 1]real a, b;
+
+     Therefore the expressions are saved in save_exprs and the statements list
+     is cached in the CDECL field of the parse tree node.  */
+
+static tree
+collect_declarer_bounds (NODE_T *p, LOW_CTX_T ctx)
+{
+  if (CDECL (p) == NULL_TREE)
+    {
+      a68_push_stmt_list (M_VOID);
+      collect_declarer_bounds_1 (SUB (p), ctx);
+      CDECL (p) = a68_pop_stmt_list ();
     }
+
+  return CDECL (p);
 }
 
 /* Low the elaboration of a generator.
@@ -450,9 +477,7 @@ a68_low_generator (NODE_T *declarer,
       a68_push_function_range (func_decl, ret_type);
 
       /* Collect bounds from declarer.  */
-      a68_push_stmt_list (M_VOID);
-      collect_declarer_bounds (SUB (declarer), ctx);
-      tree bounds = a68_pop_stmt_list ();
+      tree bounds = collect_declarer_bounds (declarer, ctx);
 
       /* Allocate and initialize a memory buffer for a value of mode MODE with
 	 bounds in BOUNDS.  */
@@ -468,9 +493,7 @@ a68_low_generator (NODE_T *declarer,
   else
     {
       /* Collect bounds from declarer.  */
-      a68_push_stmt_list (M_VOID);
-      collect_declarer_bounds (SUB (declarer), ctx);
-      tree bounds = a68_pop_stmt_list ();
+      tree bounds = collect_declarer_bounds (declarer, ctx);
 
       /* Allocate and initialize a memory buffer for a value of mode MODE with
 	 bounds in BOUNDS.  */
diff --git a/gcc/algol68/a68-low-multiples.cc b/gcc/algol68/a68-low-multiples.cc
index cf08c3977d6..d35854e31c7 100644
--- a/gcc/algol68/a68-low-multiples.cc
+++ b/gcc/algol68/a68-low-multiples.cc
@@ -632,7 +632,9 @@ a68_multiple_slice (NODE_T *p,
 
    The dimensions and bounds of both multiples are supposed to match, but since
    strides can be different the elements buffers may be of different sizes.
-   Therefore we have to copy element by element, slicing the destination.  */
+
+   Therefore we have to copy element by element, dimension by dimension,
+   slicing the destination, and taking strides into account.  */
 
 tree
 a68_multiple_copy_elems (tree to, tree from)
diff --git a/gcc/testsuite/algol68/execute/declarer-2.a68 b/gcc/testsuite/algol68/execute/declarer-2.a68
new file mode 100644
index 00000000000..b474e3e516e
--- /dev/null
+++ b/gcc/testsuite/algol68/execute/declarer-2.a68
@@ -0,0 +1,6 @@
+begin int n := 1;
+      { The actual-declarer below should be
+        elaborated only once.  }
+      [1: n +:= 1]real a, b;
+      assert (n = 2)
+end
-- 
2.30.2



More information about the Algol68 mailing list