[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