parser-moids-check.c
1 //! @file parser-moids-check.c
2 //! @author J. Marcel van der Veer
3
4 //! @section Copyright
5 //!
6 //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
7 //! Copyright 2001-2024 J. Marcel van der Veer [algol68g@xs4all.nl].
8
9 //! @section License
10 //!
11 //! This program is free software; you can redistribute it and/or modify it
12 //! under the terms of the GNU General Public License as published by the
13 //! Free Software Foundation; either version 3 of the License, or
14 //! (at your option) any later version.
15 //!
16 //! This program is distributed in the hope that it will be useful, but
17 //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 //! more details. You should have received a copy of the GNU General Public
20 //! License along with this program. If not, see [http://www.gnu.org/licenses/].
21
22 //! @section Synopsis
23 //!
24 //! Mode checker routines.
25
26 // Algol 68 contexts are SOFT, WEAK, MEEK, FIRM and STRONG.
27 // These contexts are increasing in strength:
28 //
29 // SOFT: Deproceduring
30 //
31 // WEAK: Dereferencing to REF [] or REF STRUCT
32 //
33 // MEEK: Deproceduring and dereferencing
34 //
35 // FIRM: MEEK followed by uniting
36 //
37 // STRONG: FIRM followed by rowing, widening or voiding
38 //
39 // Furthermore you will see in this file next switches:
40 //
41 // (1) FORCE_DEFLEXING allows assignment compatibility between FLEX and non FLEX
42 // rows. This can only be the case when there is no danger of altering bounds of a
43 // non FLEX row.
44 //
45 // (2) ALIAS_DEFLEXING prohibits aliasing a FLEX row to a non FLEX row (vice versa
46 // is no problem) so that one cannot alter the bounds of a non FLEX row by
47 // aliasing it to a FLEX row. This is particularly the case when passing names as
48 // parameters to procedures:
49 //
50 // PROC x = (REF STRING s) VOID: ..., PROC y = (REF [] CHAR c) VOID: ...;
51 //
52 // x (LOC STRING); # OK #
53 //
54 // x (LOC [10] CHAR); # Not OK, suppose x changes bounds of s! #
55 //
56 // y (LOC STRING); # OK #
57 //
58 // y (LOC [10] CHAR); # OK #
59 //
60 // (3) SAFE_DEFLEXING sets FLEX row apart from non FLEX row. This holds for names,
61 // not for values, so common things are not rejected, for instance
62 //
63 // STRING x = read string;
64 //
65 // [] CHAR y = read string
66 //
67 // (4) NO_DEFLEXING sets FLEX row apart from non FLEX row.
68 //
69 // Finally, a static scope checker inspects the source. Note that Algol 68 also
70 // needs dynamic scope checking. This phase concludes the parser.
71
72 #include "a68g.h"
73 #include "a68g-parser.h"
74 #include "a68g-moids.h"
75
76 //! @brief Driver for mode checker.
77
78 void mode_checker (NODE_T * p)
79 {
80 if (IS (p, PARTICULAR_PROGRAM)) {
81 A68 (top_soid_list) = NO_SOID;
82 SOID_T x, y;
83 MOID (&y) = NO_MOID;
84 make_soid (&x, STRONG, M_VOID, 0);
85 mode_check_enclosed (SUB (p), &x, &y);
86 MOID (p) = MOID (&y);
87 }
88 }
89
90 //! @brief Mode check on bounds.
91
92 void mode_check_bounds (NODE_T * p)
93 {
94 if (p == NO_NODE) {
95 return;
96 } else if (IS (p, UNIT)) {
97 SOID_T x, y;
98 make_soid (&x, STRONG, M_INT, 0);
99 mode_check_unit (p, &x, &y);
100 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
101 cannot_coerce (p, MOID (&y), M_INT, MEEK, SAFE_DEFLEXING, UNIT);
102 }
103 mode_check_bounds (NEXT (p));
104 } else {
105 mode_check_bounds (SUB (p));
106 mode_check_bounds (NEXT (p));
107 }
108 }
109
110 //! @brief Mode check declarer.
111
112 void mode_check_declarer (NODE_T * p)
113 {
114 if (p == NO_NODE) {
115 return;
116 } else if (IS (p, BOUNDS)) {
117 mode_check_bounds (SUB (p));
118 mode_check_declarer (NEXT (p));
119 } else {
120 mode_check_declarer (SUB (p));
121 mode_check_declarer (NEXT (p));
122 }
123 }
124
125 //! @brief Mode check identity declaration.
126
127 void mode_check_identity_declaration (NODE_T * p)
128 {
129 if (p != NO_NODE) {
130 switch (ATTRIBUTE (p)) {
131 case DECLARER: {
132 mode_check_declarer (SUB (p));
133 mode_check_identity_declaration (NEXT (p));
134 break;
135 }
136 case DEFINING_IDENTIFIER: {
137 SOID_T x, y;
138 make_soid (&x, STRONG, MOID (p), 0);
139 mode_check_unit (NEXT_NEXT (p), &x, &y);
140 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
141 cannot_coerce (NEXT_NEXT (p), MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, UNIT);
142 } else if (MOID (&x) != MOID (&y)) {
143 // Check for instance, REF INT i = LOC REF INT.
144 semantic_pitfall (NEXT_NEXT (p), MOID (&x), IDENTITY_DECLARATION, GENERATOR);
145 }
146 break;
147 }
148 default: {
149 mode_check_identity_declaration (SUB (p));
150 mode_check_identity_declaration (NEXT (p));
151 break;
152 }
153 }
154 }
155 }
156
157 //! @brief Mode check variable declaration.
158
159 void mode_check_variable_declaration (NODE_T * p)
160 {
161 if (p != NO_NODE) {
162 switch (ATTRIBUTE (p)) {
163 case DECLARER: {
164 mode_check_declarer (SUB (p));
165 mode_check_variable_declaration (NEXT (p));
166 break;
167 }
168 case DEFINING_IDENTIFIER: {
169 if (whether (p, DEFINING_IDENTIFIER, ASSIGN_SYMBOL, UNIT, STOP)) {
170 SOID_T x, y;
171 make_soid (&x, STRONG, SUB_MOID (p), 0);
172 mode_check_unit (NEXT_NEXT (p), &x, &y);
173 if (!is_coercible_in_context (&y, &x, FORCE_DEFLEXING)) {
174 cannot_coerce (p, MOID (&y), MOID (&x), STRONG, FORCE_DEFLEXING, UNIT);
175 } else if (SUB_MOID (&x) != MOID (&y)) {
176 // Check for instance, REF INT i = LOC REF INT.
177 semantic_pitfall (NEXT_NEXT (p), MOID (&x), VARIABLE_DECLARATION, GENERATOR);
178 }
179 }
180 break;
181 }
182 default: {
183 mode_check_variable_declaration (SUB (p));
184 mode_check_variable_declaration (NEXT (p));
185 break;
186 }
187 }
188 }
189 }
190
191 //! @brief Mode check routine text.
192
193 void mode_check_routine_text (NODE_T * p, SOID_T * y)
194 {
195 SOID_T w;
196 if (IS (p, PARAMETER_PACK)) {
197 mode_check_declarer (SUB (p));
198 FORWARD (p);
199 }
200 mode_check_declarer (SUB (p));
201 make_soid (&w, STRONG, MOID (p), 0);
202 mode_check_unit (NEXT_NEXT (p), &w, y);
203 if (!is_coercible_in_context (y, &w, FORCE_DEFLEXING)) {
204 cannot_coerce (NEXT_NEXT (p), MOID (y), MOID (&w), STRONG, FORCE_DEFLEXING, UNIT);
205 }
206 }
207
208 //! @brief Mode check proc declaration.
209
210 void mode_check_proc_declaration (NODE_T * p)
211 {
212 if (p == NO_NODE) {
213 return;
214 } else if (IS (p, ROUTINE_TEXT)) {
215 SOID_T x, y;
216 make_soid (&x, STRONG, NO_MOID, 0);
217 mode_check_routine_text (SUB (p), &y);
218 } else {
219 mode_check_proc_declaration (SUB (p));
220 mode_check_proc_declaration (NEXT (p));
221 }
222 }
223
224 //! @brief Mode check brief op declaration.
225
226 void mode_check_brief_op_declaration (NODE_T * p)
227 {
228 if (p == NO_NODE) {
229 return;
230 } else if (IS (p, DEFINING_OPERATOR)) {
231 SOID_T y;
232 if (MOID (p) != MOID (NEXT_NEXT (p))) {
233 SOID_T y2, x;
234 make_soid (&y2, NO_SORT, MOID (NEXT_NEXT (p)), 0);
235 make_soid (&x, NO_SORT, MOID (p), 0);
236 cannot_coerce (NEXT_NEXT (p), MOID (&y2), MOID (&x), STRONG, SKIP_DEFLEXING, ROUTINE_TEXT);
237 }
238 mode_check_routine_text (SUB (NEXT_NEXT (p)), &y);
239 } else {
240 mode_check_brief_op_declaration (SUB (p));
241 mode_check_brief_op_declaration (NEXT (p));
242 }
243 }
244
245 //! @brief Mode check op declaration.
246
247 void mode_check_op_declaration (NODE_T * p)
248 {
249 if (p == NO_NODE) {
250 return;
251 } else if (IS (p, DEFINING_OPERATOR)) {
252 SOID_T y, x;
253 make_soid (&x, STRONG, MOID (p), 0);
254 mode_check_unit (NEXT_NEXT (p), &x, &y);
255 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
256 cannot_coerce (NEXT_NEXT (p), MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, UNIT);
257 }
258 } else {
259 mode_check_op_declaration (SUB (p));
260 mode_check_op_declaration (NEXT (p));
261 }
262 }
263
264 //! @brief Mode check declaration list.
265
266 void mode_check_declaration_list (NODE_T * p)
267 {
268 if (p != NO_NODE) {
269 switch (ATTRIBUTE (p)) {
270 case IDENTITY_DECLARATION: {
271 mode_check_identity_declaration (SUB (p));
272 break;
273 }
274 case VARIABLE_DECLARATION: {
275 mode_check_variable_declaration (SUB (p));
276 break;
277 }
278 case MODE_DECLARATION: {
279 mode_check_declarer (SUB (p));
280 break;
281 }
282 case PROCEDURE_DECLARATION:
283 case PROCEDURE_VARIABLE_DECLARATION: {
284 mode_check_proc_declaration (SUB (p));
285 break;
286 }
287 case BRIEF_OPERATOR_DECLARATION: {
288 mode_check_brief_op_declaration (SUB (p));
289 break;
290 }
291 case OPERATOR_DECLARATION: {
292 mode_check_op_declaration (SUB (p));
293 break;
294 }
295 default: {
296 mode_check_declaration_list (SUB (p));
297 mode_check_declaration_list (NEXT (p));
298 break;
299 }
300 }
301 }
302 }
303
304 //! @brief Mode check serial clause.
305
306 void mode_check_serial (SOID_T ** r, NODE_T * p, SOID_T * x, BOOL_T k)
307 {
308 if (p == NO_NODE) {
309 return;
310 } else if (IS (p, INITIALISER_SERIES)) {
311 mode_check_serial (r, SUB (p), x, A68_FALSE);
312 mode_check_serial (r, NEXT (p), x, k);
313 } else if (IS (p, DECLARATION_LIST)) {
314 mode_check_declaration_list (SUB (p));
315 } else if (is_one_of (p, LABEL, SEMI_SYMBOL, EXIT_SYMBOL, STOP)) {
316 mode_check_serial (r, NEXT (p), x, k);
317 } else if (is_one_of (p, SERIAL_CLAUSE, ENQUIRY_CLAUSE, STOP)) {
318 if (NEXT (p) != NO_NODE) {
319 if (IS (NEXT (p), EXIT_SYMBOL) || IS (NEXT (p), END_SYMBOL) || IS (NEXT (p), CLOSE_SYMBOL)) {
320 mode_check_serial (r, SUB (p), x, A68_TRUE);
321 } else {
322 mode_check_serial (r, SUB (p), x, A68_FALSE);
323 }
324 mode_check_serial (r, NEXT (p), x, k);
325 } else {
326 mode_check_serial (r, SUB (p), x, A68_TRUE);
327 }
328 } else if (IS (p, LABELED_UNIT)) {
329 mode_check_serial (r, SUB (p), x, k);
330 } else if (IS (p, UNIT)) {
331 SOID_T y;
332 if (k) {
333 mode_check_unit (p, x, &y);
334 } else {
335 SOID_T w;
336 make_soid (&w, STRONG, M_VOID, 0);
337 mode_check_unit (p, &w, &y);
338 }
339 if (NEXT (p) != NO_NODE) {
340 mode_check_serial (r, NEXT (p), x, k);
341 } else {
342 if (k) {
343 add_to_soid_list (r, p, &y);
344 }
345 }
346 }
347 }
348
349 //! @brief Mode check serial clause units.
350
351 void mode_check_serial_units (NODE_T * p, SOID_T * x, SOID_T * y, int att)
352 {
353 SOID_T *top_sl = NO_SOID;
354 (void) att;
355 mode_check_serial (&top_sl, SUB (p), x, A68_TRUE);
356 if (is_balanced (p, top_sl, SORT (x))) {
357 MOID_T *result = pack_soids_in_moid (top_sl, SERIES_MODE);
358 make_soid (y, SORT (x), result, SERIAL_CLAUSE);
359 } else {
360 make_soid (y, SORT (x), (MOID (x) != NO_MOID ? MOID (x) : M_ERROR), 0);
361 }
362 free_soid_list (top_sl);
363 }
364
365 //! @brief Mode check unit list.
366
367 void mode_check_unit_list (SOID_T ** r, NODE_T * p, SOID_T * x)
368 {
369 if (p == NO_NODE) {
370 return;
371 } else if (IS (p, UNIT_LIST)) {
372 mode_check_unit_list (r, SUB (p), x);
373 mode_check_unit_list (r, NEXT (p), x);
374 } else if (IS (p, COMMA_SYMBOL)) {
375 mode_check_unit_list (r, NEXT (p), x);
376 } else if (IS (p, UNIT)) {
377 SOID_T y;
378 mode_check_unit (p, x, &y);
379 add_to_soid_list (r, p, &y);
380 mode_check_unit_list (r, NEXT (p), x);
381 }
382 }
383
384 //! @brief Mode check struct display.
385
386 void mode_check_struct_display (SOID_T ** r, NODE_T * p, PACK_T ** fields)
387 {
388 if (p == NO_NODE) {
389 return;
390 } else if (IS (p, UNIT_LIST)) {
391 mode_check_struct_display (r, SUB (p), fields);
392 mode_check_struct_display (r, NEXT (p), fields);
393 } else if (IS (p, COMMA_SYMBOL)) {
394 mode_check_struct_display (r, NEXT (p), fields);
395 } else if (IS (p, UNIT)) {
396 SOID_T x, y;
397 if (*fields != NO_PACK) {
398 make_soid (&x, STRONG, MOID (*fields), 0);
399 FORWARD (*fields);
400 } else {
401 make_soid (&x, STRONG, NO_MOID, 0);
402 }
403 mode_check_unit (p, &x, &y);
404 add_to_soid_list (r, p, &y);
405 mode_check_struct_display (r, NEXT (p), fields);
406 }
407 }
408
409 //! @brief Mode check get specified moids.
410
411 void mode_check_get_specified_moids (NODE_T * p, MOID_T * u)
412 {
413 for (; p != NO_NODE; FORWARD (p)) {
414 if (is_one_of (p, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT, STOP)) {
415 mode_check_get_specified_moids (SUB (p), u);
416 } else if (IS (p, SPECIFIER)) {
417 MOID_T *m = MOID (NEXT_SUB (p));
418 add_mode_to_pack (&(PACK (u)), m, NO_TEXT, NODE (m));
419 }
420 }
421 }
422
423 //! @brief Mode check specified unit list.
424
425 void mode_check_specified_unit_list (SOID_T ** r, NODE_T * p, SOID_T * x, MOID_T * u)
426 {
427 for (; p != NO_NODE; FORWARD (p)) {
428 if (is_one_of (p, SPECIFIED_UNIT_LIST, SPECIFIED_UNIT, STOP)) {
429 mode_check_specified_unit_list (r, SUB (p), x, u);
430 } else if (IS (p, SPECIFIER)) {
431 MOID_T *m = MOID (NEXT_SUB (p));
432 if (u != NO_MOID && !is_unitable (m, u, SAFE_DEFLEXING)) {
433 diagnostic (A68_ERROR, p, ERROR_NO_COMPONENT, m, u);
434 }
435 } else if (IS (p, UNIT)) {
436 SOID_T y;
437 mode_check_unit (p, x, &y);
438 add_to_soid_list (r, p, &y);
439 }
440 }
441 }
442
443 //! @brief Mode check united case parts.
444
445 void mode_check_united_case_parts (SOID_T ** ry, NODE_T * p, SOID_T * x)
446 {
447 SOID_T enq_expct, enq_yield;
448 MOID_T *u = NO_MOID, *v = NO_MOID, *w = NO_MOID;
449 // Check the CASE part and deduce the united mode.
450 make_soid (&enq_expct, MEEK, NO_MOID, 0);
451 mode_check_serial_units (NEXT_SUB (p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
452 // Deduce the united mode from the enquiry clause.
453 u = depref_completely (MOID (&enq_yield));
454 u = make_united_mode (u);
455 u = depref_completely (u);
456 // Also deduce the united mode from the specifiers.
457 v = new_moid ();
458 ATTRIBUTE (v) = SERIES_MODE;
459 mode_check_get_specified_moids (NEXT_SUB (NEXT (p)), v);
460 v = make_united_mode (v);
461 // Determine a resulting union.
462 if (u == M_HIP) {
463 w = v;
464 } else {
465 if (IS (u, UNION_SYMBOL)) {
466 BOOL_T uv, vu, some;
467 investigate_firm_relations (PACK (u), PACK (v), &uv, &some);
468 investigate_firm_relations (PACK (v), PACK (u), &vu, &some);
469 if (uv && vu) {
470 // Every component has a specifier.
471 w = u;
472 } else if (!uv && !vu) {
473 // Hmmmm ... let the coercer sort it out.
474 w = u;
475 } else {
476 // This is all the balancing we allow here for the moment. Firmly related
477 // subsets are not valid so we absorb them. If this doesn't solve it then we
478 // get a coercion-error later.
479 w = absorb_related_subsets (u);
480 }
481 } else {
482 diagnostic (A68_ERROR, NEXT_SUB (p), ERROR_NO_UNION, u);
483 return;
484 }
485 }
486 MOID (SUB (p)) = w;
487 FORWARD (p);
488 // Check the IN part.
489 mode_check_specified_unit_list (ry, NEXT_SUB (p), x, w);
490 // OUSE, OUT, ESAC.
491 if ((FORWARD (p)) != NO_NODE) {
492 if (is_one_of (p, OUT_PART, CHOICE, STOP)) {
493 mode_check_serial (ry, NEXT_SUB (p), x, A68_TRUE);
494 } else if (is_one_of (p, CONFORMITY_OUSE_PART, BRIEF_CONFORMITY_OUSE_PART, STOP)) {
495 mode_check_united_case_parts (ry, SUB (p), x);
496 }
497 }
498 }
499
500 //! @brief Mode check united case.
501
502 void mode_check_united_case (NODE_T * p, SOID_T * x, SOID_T * y)
503 {
504 SOID_T *top_sl = NO_SOID;
505 mode_check_united_case_parts (&top_sl, p, x);
506 if (!is_balanced (p, top_sl, SORT (x))) {
507 if (MOID (x) != NO_MOID) {
508 make_soid (y, SORT (x), MOID (x), CONFORMITY_CLAUSE);
509
510 } else {
511 make_soid (y, SORT (x), M_ERROR, 0);
512 }
513 } else {
514 MOID_T *z = pack_soids_in_moid (top_sl, SERIES_MODE);
515 make_soid (y, SORT (x), z, CONFORMITY_CLAUSE);
516 }
517 free_soid_list (top_sl);
518 }
519
520 //! @brief Mode check unit list 2.
521
522 void mode_check_unit_list_2 (NODE_T * p, SOID_T * x, SOID_T * y)
523 {
524 SOID_T *top_sl = NO_SOID;
525 if (MOID (x) != NO_MOID) {
526 if (IS_FLEX (MOID (x))) {
527 SOID_T y2;
528 make_soid (&y2, SORT (x), SLICE (SUB_MOID (x)), 0);
529 mode_check_unit_list (&top_sl, SUB (p), &y2);
530 } else if (IS_ROW (MOID (x))) {
531 SOID_T y2;
532 make_soid (&y2, SORT (x), SLICE (MOID (x)), 0);
533 mode_check_unit_list (&top_sl, SUB (p), &y2);
534 } else if (IS (MOID (x), STRUCT_SYMBOL)) {
535 PACK_T *y2 = PACK (MOID (x));
536 mode_check_struct_display (&top_sl, SUB (p), &y2);
537 } else {
538 mode_check_unit_list (&top_sl, SUB (p), x);
539 }
540 } else {
541 mode_check_unit_list (&top_sl, SUB (p), x);
542 }
543 make_soid (y, STRONG, pack_soids_in_moid (top_sl, STOWED_MODE), 0);
544 free_soid_list (top_sl);
545 }
546
547 //! @brief Mode check closed.
548
549 void mode_check_closed (NODE_T * p, SOID_T * x, SOID_T * y)
550 {
551 if (p == NO_NODE) {
552 return;
553 } else if (IS (p, SERIAL_CLAUSE)) {
554 mode_check_serial_units (p, x, y, SERIAL_CLAUSE);
555 } else if (is_one_of (p, OPEN_SYMBOL, BEGIN_SYMBOL, STOP)) {
556 mode_check_closed (NEXT (p), x, y);
557 }
558 MOID (p) = MOID (y);
559 }
560
561 //! @brief Mode check collateral.
562
563 void mode_check_collateral (NODE_T * p, SOID_T * x, SOID_T * y)
564 {
565 if (p == NO_NODE) {
566 return;
567 } else if (whether (p, BEGIN_SYMBOL, END_SYMBOL, STOP) || whether (p, OPEN_SYMBOL, CLOSE_SYMBOL, STOP)) {
568 if (SORT (x) == STRONG) {
569 if (MOID (x) == NO_MOID) {
570 diagnostic (A68_ERROR, p, ERROR_VACUUM, "REF MODE");
571 } else {
572 make_soid (y, STRONG, M_VACUUM, 0);
573 }
574 } else {
575 make_soid (y, STRONG, M_UNDEFINED, 0);
576 }
577 } else {
578 if (IS (p, UNIT_LIST)) {
579 mode_check_unit_list_2 (p, x, y);
580 } else if (is_one_of (p, OPEN_SYMBOL, BEGIN_SYMBOL, STOP)) {
581 mode_check_collateral (NEXT (p), x, y);
582 }
583 MOID (p) = MOID (y);
584 }
585 }
586
587 //! @brief Mode check conditional 2.
588
589 void mode_check_conditional_2 (SOID_T ** ry, NODE_T * p, SOID_T * x)
590 {
591 SOID_T enq_expct, enq_yield;
592 make_soid (&enq_expct, MEEK, M_BOOL, 0);
593 mode_check_serial_units (NEXT_SUB (p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
594 if (!is_coercible_in_context (&enq_yield, &enq_expct, SAFE_DEFLEXING)) {
595 cannot_coerce (p, MOID (&enq_yield), MOID (&enq_expct), MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
596 }
597 FORWARD (p);
598 mode_check_serial (ry, NEXT_SUB (p), x, A68_TRUE);
599 if ((FORWARD (p)) != NO_NODE) {
600 if (is_one_of (p, ELSE_PART, CHOICE, STOP)) {
601 mode_check_serial (ry, NEXT_SUB (p), x, A68_TRUE);
602 } else if (is_one_of (p, ELIF_PART, BRIEF_ELIF_PART, STOP)) {
603 mode_check_conditional_2 (ry, SUB (p), x);
604 }
605 }
606 }
607
608 //! @brief Mode check conditional.
609
610 void mode_check_conditional (NODE_T * p, SOID_T * x, SOID_T * y)
611 {
612 SOID_T *top_sl = NO_SOID;
613 mode_check_conditional_2 (&top_sl, p, x);
614 if (!is_balanced (p, top_sl, SORT (x))) {
615 if (MOID (x) != NO_MOID) {
616 make_soid (y, SORT (x), MOID (x), CONDITIONAL_CLAUSE);
617 } else {
618 make_soid (y, SORT (x), M_ERROR, 0);
619 }
620 } else {
621 MOID_T *z = pack_soids_in_moid (top_sl, SERIES_MODE);
622 make_soid (y, SORT (x), z, CONDITIONAL_CLAUSE);
623 }
624 free_soid_list (top_sl);
625 }
626
627 //! @brief Mode check int case 2.
628
629 void mode_check_int_case_2 (SOID_T ** ry, NODE_T * p, SOID_T * x)
630 {
631 SOID_T enq_expct, enq_yield;
632 make_soid (&enq_expct, MEEK, M_INT, 0);
633 mode_check_serial_units (NEXT_SUB (p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
634 if (!is_coercible_in_context (&enq_yield, &enq_expct, SAFE_DEFLEXING)) {
635 cannot_coerce (p, MOID (&enq_yield), MOID (&enq_expct), MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
636 }
637 FORWARD (p);
638 mode_check_unit_list (ry, NEXT_SUB (p), x);
639 if ((FORWARD (p)) != NO_NODE) {
640 if (is_one_of (p, OUT_PART, CHOICE, STOP)) {
641 mode_check_serial (ry, NEXT_SUB (p), x, A68_TRUE);
642 } else if (is_one_of (p, CASE_OUSE_PART, BRIEF_OUSE_PART, STOP)) {
643 mode_check_int_case_2 (ry, SUB (p), x);
644 }
645 }
646 }
647
648 //! @brief Mode check int case.
649
650 void mode_check_int_case (NODE_T * p, SOID_T * x, SOID_T * y)
651 {
652 SOID_T *top_sl = NO_SOID;
653 mode_check_int_case_2 (&top_sl, p, x);
654 if (!is_balanced (p, top_sl, SORT (x))) {
655 if (MOID (x) != NO_MOID) {
656 make_soid (y, SORT (x), MOID (x), CASE_CLAUSE);
657 } else {
658 make_soid (y, SORT (x), M_ERROR, 0);
659 }
660 } else {
661 MOID_T *z = pack_soids_in_moid (top_sl, SERIES_MODE);
662 make_soid (y, SORT (x), z, CASE_CLAUSE);
663 }
664 free_soid_list (top_sl);
665 }
666
667 //! @brief Mode check loop 2.
668
669 void mode_check_loop_2 (NODE_T * p, SOID_T * y)
670 {
671 if (p == NO_NODE) {
672 return;
673 } else if (IS (p, FOR_PART)) {
674 mode_check_loop_2 (NEXT (p), y);
675 } else if (is_one_of (p, FROM_PART, BY_PART, TO_PART, STOP)) {
676 SOID_T ix, iy;
677 make_soid (&ix, STRONG, M_INT, 0);
678 mode_check_unit (NEXT_SUB (p), &ix, &iy);
679 if (!is_coercible_in_context (&iy, &ix, SAFE_DEFLEXING)) {
680 cannot_coerce (NEXT_SUB (p), MOID (&iy), M_INT, MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
681 }
682 mode_check_loop_2 (NEXT (p), y);
683 } else if (IS (p, WHILE_PART)) {
684 SOID_T enq_expct, enq_yield;
685 make_soid (&enq_expct, MEEK, M_BOOL, 0);
686 mode_check_serial_units (NEXT_SUB (p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
687 if (!is_coercible_in_context (&enq_yield, &enq_expct, SAFE_DEFLEXING)) {
688 cannot_coerce (p, MOID (&enq_yield), MOID (&enq_expct), MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
689 }
690 mode_check_loop_2 (NEXT (p), y);
691 } else if (is_one_of (p, DO_PART, ALT_DO_PART, STOP)) {
692 SOID_T *z = NO_SOID;
693 NODE_T *do_p = NEXT_SUB (p), *un_p;
694 SOID_T ix;
695 make_soid (&ix, STRONG, M_VOID, 0);
696 if (IS (do_p, SERIAL_CLAUSE)) {
697 mode_check_serial (&z, do_p, &ix, A68_TRUE);
698 un_p = NEXT (do_p);
699 } else {
700 un_p = do_p;
701 }
702 if (un_p != NO_NODE && IS (un_p, UNTIL_PART)) {
703 SOID_T enq_expct, enq_yield;
704 make_soid (&enq_expct, STRONG, M_BOOL, 0);
705 mode_check_serial_units (NEXT_SUB (un_p), &enq_expct, &enq_yield, ENQUIRY_CLAUSE);
706 if (!is_coercible_in_context (&enq_yield, &enq_expct, SAFE_DEFLEXING)) {
707 cannot_coerce (un_p, MOID (&enq_yield), MOID (&enq_expct), MEEK, SAFE_DEFLEXING, ENQUIRY_CLAUSE);
708 }
709 }
710 free_soid_list (z);
711 }
712 }
713
714 //! @brief Mode check loop.
715
716 void mode_check_loop (NODE_T * p, SOID_T * y)
717 {
718 SOID_T *z = NO_SOID;
719 mode_check_loop_2 (p, z);
720 make_soid (y, STRONG, M_VOID, 0);
721 }
722
723 //! @brief Mode check enclosed.
724
725 void mode_check_enclosed (NODE_T * p, SOID_T * x, SOID_T * y)
726 {
727 if (p == NO_NODE) {
728 return;
729 } else if (IS (p, ENCLOSED_CLAUSE)) {
730 mode_check_enclosed (SUB (p), x, y);
731 } else if (IS (p, CLOSED_CLAUSE)) {
732 mode_check_closed (SUB (p), x, y);
733 } else if (IS (p, PARALLEL_CLAUSE)) {
734 mode_check_collateral (SUB (NEXT_SUB (p)), x, y);
735 make_soid (y, STRONG, M_VOID, 0);
736 MOID (NEXT_SUB (p)) = M_VOID;
737 } else if (IS (p, COLLATERAL_CLAUSE)) {
738 mode_check_collateral (SUB (p), x, y);
739 } else if (IS (p, CONDITIONAL_CLAUSE)) {
740 mode_check_conditional (SUB (p), x, y);
741 } else if (IS (p, CASE_CLAUSE)) {
742 mode_check_int_case (SUB (p), x, y);
743 } else if (IS (p, CONFORMITY_CLAUSE)) {
744 mode_check_united_case (SUB (p), x, y);
745 } else if (IS (p, LOOP_CLAUSE)) {
746 mode_check_loop (SUB (p), y);
747 }
748 MOID (p) = MOID (y);
749 }
750
751 //! @brief Search table for operator.
752
753 TAG_T *search_table_for_operator (TAG_T * t, const char *n, MOID_T * x, MOID_T * y)
754 {
755 if (is_mode_isnt_well (x)) {
756 return A68_PARSER (error_tag);
757 } else if (y != NO_MOID && is_mode_isnt_well (y)) {
758 return A68_PARSER (error_tag);
759 }
760 for (; t != NO_TAG; FORWARD (t)) {
761 if (NSYMBOL (NODE (t)) == n) {
762 PACK_T *p = PACK (MOID (t));
763 if (is_coercible (x, MOID (p), FIRM, ALIAS_DEFLEXING)) {
764 FORWARD (p);
765 if (p == NO_PACK && y == NO_MOID) {
766 // Matched in case of a monadic.
767 return t;
768 } else if (p != NO_PACK && y != NO_MOID && is_coercible (y, MOID (p), FIRM, ALIAS_DEFLEXING)) {
769 // Matched in case of a dyadic.
770 return t;
771 }
772 }
773 }
774 }
775 return NO_TAG;
776 }
777
778 //! @brief Search chain of symbol tables and return matching operator "x n y" or "n x".
779
780 TAG_T *search_table_chain_for_operator (TABLE_T * s, char *n, MOID_T * x, MOID_T * y)
781 {
782 if (is_mode_isnt_well (x)) {
783 return A68_PARSER (error_tag);
784 } else if (y != NO_MOID && is_mode_isnt_well (y)) {
785 return A68_PARSER (error_tag);
786 }
787 while (s != NO_TABLE) {
788 TAG_T *z = search_table_for_operator (OPERATORS (s), n, x, y);
789 if (z != NO_TAG) {
790 return z;
791 }
792 BACKWARD (s);
793 }
794 return NO_TAG;
795 }
796
797 //! @brief Return a matching operator "x n y".
798
799 TAG_T *find_operator (TABLE_T * s, char *n, MOID_T * x, MOID_T * y)
800 {
801 // Coercions to operand modes are FIRM.
802 MOID_T *u, *v; TAG_T *z;
803 // (A) Catch exceptions first.
804 if (x == NO_MOID && y == NO_MOID) {
805 return NO_TAG;
806 } else if (is_mode_isnt_well (x)) {
807 return A68_PARSER (error_tag);
808 } else if (y != NO_MOID && is_mode_isnt_well (y)) {
809 return A68_PARSER (error_tag);
810 }
811 // (B) MONADs.
812 if (x != NO_MOID && y == NO_MOID) {
813 z = search_table_chain_for_operator (s, n, x, NO_MOID);
814 if (z != NO_TAG) {
815 return z;
816 } else {
817 // (B.2) A little trick to allow - (0, 1) or ABS (1, long pi).
818 if (is_coercible (x, M_COMPLEX, STRONG, SAFE_DEFLEXING)) {
819 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_COMPLEX, NO_MOID);
820 if (z != NO_TAG) {
821 return z;
822 }
823 }
824 if (is_coercible (x, M_LONG_COMPLEX, STRONG, SAFE_DEFLEXING)) {
825 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_LONG_COMPLEX, NO_MOID);
826 if (z != NO_TAG) {
827 return z;
828 }
829 }
830 if (is_coercible (x, M_LONG_LONG_COMPLEX, STRONG, SAFE_DEFLEXING)) {
831 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_LONG_LONG_COMPLEX, NO_MOID);
832 }
833 }
834 return NO_TAG;
835 }
836 // (C) DYADs.
837 z = search_table_chain_for_operator (s, n, x, y);
838 if (z != NO_TAG) {
839 return z;
840 }
841 // (C.2) Vector and matrix "strong coercions" in standard environ.
842 u = DEFLEX (depref_completely (x));
843 v = DEFLEX (depref_completely (y));
844 if ((u == M_ROW_REAL || u == M_ROW_ROW_REAL)
845 || (v == M_ROW_REAL || v == M_ROW_ROW_REAL)
846 || (u == M_ROW_COMPLEX || u == M_ROW_ROW_COMPLEX)
847 || (v == M_ROW_COMPLEX || v == M_ROW_ROW_COMPLEX)) {
848 if (u == M_INT) {
849 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_REAL, y);
850 if (z != NO_TAG) {
851 return z;
852 }
853 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_COMPLEX, y);
854 if (z != NO_TAG) {
855 return z;
856 }
857 } else if (v == M_INT) {
858 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, x, M_REAL);
859 if (z != NO_TAG) {
860 return z;
861 }
862 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, x, M_COMPLEX);
863 if (z != NO_TAG) {
864 return z;
865 }
866 } else if (u == M_REAL) {
867 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_COMPLEX, y);
868 if (z != NO_TAG) {
869 return z;
870 }
871 } else if (v == M_REAL) {
872 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, x, M_COMPLEX);
873 if (z != NO_TAG) {
874 return z;
875 }
876 }
877 }
878 // (C.3) Look in standenv for an appropriate cross-term.
879 u = make_series_from_moids (x, y);
880 u = make_united_mode (u);
881 v = get_balanced_mode (u, STRONG, NO_DEPREF, SAFE_DEFLEXING);
882 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, v, v);
883 if (z != NO_TAG) {
884 return z;
885 }
886 if (is_coercible_series (u, M_REAL, STRONG, SAFE_DEFLEXING)) {
887 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_REAL, M_REAL);
888 if (z != NO_TAG) {
889 return z;
890 }
891 }
892 if (is_coercible_series (u, M_LONG_REAL, STRONG, SAFE_DEFLEXING)) {
893 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_LONG_REAL, M_LONG_REAL);
894 if (z != NO_TAG) {
895 return z;
896 }
897 }
898 if (is_coercible_series (u, M_LONG_LONG_REAL, STRONG, SAFE_DEFLEXING)) {
899 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_LONG_LONG_REAL, M_LONG_LONG_REAL);
900 if (z != NO_TAG) {
901 return z;
902 }
903 }
904 if (is_coercible_series (u, M_COMPLEX, STRONG, SAFE_DEFLEXING)) {
905 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_COMPLEX, M_COMPLEX);
906 if (z != NO_TAG) {
907 return z;
908 }
909 }
910 if (is_coercible_series (u, M_LONG_COMPLEX, STRONG, SAFE_DEFLEXING)) {
911 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_LONG_COMPLEX, M_LONG_COMPLEX);
912 if (z != NO_TAG) {
913 return z;
914 }
915 }
916 if (is_coercible_series (u, M_LONG_LONG_COMPLEX, STRONG, SAFE_DEFLEXING)) {
917 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, M_LONG_LONG_COMPLEX, M_LONG_LONG_COMPLEX);
918 if (z != NO_TAG) {
919 return z;
920 }
921 }
922 // (C.4) Now allow for depreffing for REF REAL +:= INT and alike.
923 v = get_balanced_mode (u, STRONG, DEPREF, SAFE_DEFLEXING);
924 z = search_table_for_operator (OPERATORS (A68_STANDENV), n, v, v);
925 if (z != NO_TAG) {
926 return z;
927 }
928 return NO_TAG;
929 }
930
931 //! @brief Mode check monadic operator.
932
933 void mode_check_monadic_operator (NODE_T * p, SOID_T * x, SOID_T * y)
934 {
935 if (p != NO_NODE) {
936 TAG_T *t;
937 MOID_T *u = determine_unique_mode (y, SAFE_DEFLEXING);
938 if (is_mode_isnt_well (u)) {
939 make_soid (y, SORT (x), M_ERROR, 0);
940 } else if (u == M_HIP) {
941 diagnostic (A68_ERROR, NEXT (p), ERROR_INVALID_OPERAND, u);
942 make_soid (y, SORT (x), M_ERROR, 0);
943 } else {
944 if (strchr (NOMADS, *(NSYMBOL (p))) != NO_TEXT) {
945 t = NO_TAG;
946 diagnostic (A68_SYNTAX_ERROR, p, ERROR_OPERATOR_INVALID, NOMADS);
947 make_soid (y, SORT (x), M_ERROR, 0);
948 } else {
949 t = find_operator (TABLE (p), NSYMBOL (p), u, NO_MOID);
950 if (t == NO_TAG) {
951 diagnostic (A68_ERROR, p, ERROR_NO_MONADIC, u);
952 make_soid (y, SORT (x), M_ERROR, 0);
953 }
954 }
955 if (t != NO_TAG) {
956 MOID (p) = MOID (t);
957 }
958 TAX (p) = t;
959 if (t != NO_TAG && t != A68_PARSER (error_tag)) {
960 MOID (p) = MOID (t);
961 make_soid (y, SORT (x), SUB_MOID (t), 0);
962 } else {
963 MOID (p) = M_ERROR;
964 make_soid (y, SORT (x), M_ERROR, 0);
965 }
966 }
967 }
968 }
969
970 //! @brief Mode check monadic formula.
971
972 void mode_check_monadic_formula (NODE_T * p, SOID_T * x, SOID_T * y)
973 {
974 SOID_T e;
975 make_soid (&e, FIRM, NO_MOID, 0);
976 mode_check_formula (NEXT (p), &e, y);
977 mode_check_monadic_operator (p, &e, y);
978 make_soid (y, SORT (x), MOID (y), 0);
979 }
980
981 //! @brief Mode check formula.
982
983 void mode_check_formula (NODE_T * p, SOID_T * x, SOID_T * y)
984 {
985 SOID_T ls;
986 if (IS (p, MONADIC_FORMULA)) {
987 mode_check_monadic_formula (SUB (p), x, &ls);
988 } else if (IS (p, FORMULA)) {
989 mode_check_formula (SUB (p), x, &ls);
990 } else if (IS (p, SECONDARY)) {
991 SOID_T e;
992 make_soid (&e, FIRM, NO_MOID, 0);
993 mode_check_unit (SUB (p), &e, &ls);
994 }
995 MOID_T *u = determine_unique_mode (&ls, SAFE_DEFLEXING);
996 MOID (p) = u;
997 SOID_T rs;
998 if (NEXT (p) == NO_NODE) {
999 make_soid (y, SORT (x), u, 0);
1000 } else {
1001 NODE_T *q = NEXT_NEXT (p);
1002 if (IS (q, MONADIC_FORMULA)) {
1003 mode_check_monadic_formula (SUB (NEXT_NEXT (p)), x, &rs);
1004 } else if (IS (q, FORMULA)) {
1005 mode_check_formula (SUB (NEXT_NEXT (p)), x, &rs);
1006 } else if (IS (q, SECONDARY)) {
1007 SOID_T e;
1008 make_soid (&e, FIRM, NO_MOID, 0);
1009 mode_check_unit (SUB (q), &e, &rs);
1010 }
1011 MOID_T *v = determine_unique_mode (&rs, SAFE_DEFLEXING);
1012 MOID (q) = v;
1013 if (is_mode_isnt_well (u) || is_mode_isnt_well (v)) {
1014 make_soid (y, SORT (x), M_ERROR, 0);
1015 } else if (u == M_HIP) {
1016 diagnostic (A68_ERROR, p, ERROR_INVALID_OPERAND, u);
1017 make_soid (y, SORT (x), M_ERROR, 0);
1018 } else if (v == M_HIP) {
1019 diagnostic (A68_ERROR, q, ERROR_INVALID_OPERAND, u);
1020 make_soid (y, SORT (x), M_ERROR, 0);
1021 } else {
1022 TAG_T *op = find_operator (TABLE (NEXT (p)), NSYMBOL (NEXT (p)), u, v);
1023 if (op == NO_TAG) {
1024 diagnostic (A68_ERROR, NEXT (p), ERROR_NO_DYADIC, u, v);
1025 make_soid (y, SORT (x), M_ERROR, 0);
1026 }
1027 if (op != NO_TAG) {
1028 MOID (NEXT (p)) = MOID (op);
1029 }
1030 TAX (NEXT (p)) = op;
1031 if (op != NO_TAG && op != A68_PARSER (error_tag)) {
1032 make_soid (y, SORT (x), SUB_MOID (op), 0);
1033 } else {
1034 make_soid (y, SORT (x), M_ERROR, 0);
1035 }
1036 }
1037 }
1038 }
1039
1040 //! @brief Mode check assignation.
1041
1042 void mode_check_assignation (NODE_T * p, SOID_T * x, SOID_T * y)
1043 {
1044 // Get destination mode.
1045 SOID_T name, tmp, value;
1046 make_soid (&name, SOFT, NO_MOID, 0);
1047 mode_check_unit (SUB (p), &name, &tmp);
1048 // SOFT coercion.
1049 MOID_T *ori = determine_unique_mode (&tmp, SAFE_DEFLEXING);
1050 MOID_T *name_moid = deproc_completely (ori);
1051 if (ATTRIBUTE (name_moid) != REF_SYMBOL) {
1052 if (IF_MODE_IS_WELL (name_moid)) {
1053 diagnostic (A68_ERROR, p, ERROR_NO_NAME, ori, ATTRIBUTE (SUB (p)));
1054 }
1055 make_soid (y, SORT (x), M_ERROR, 0);
1056 return;
1057 }
1058 MOID (p) = name_moid;
1059 // Get source mode.
1060 make_soid (&name, STRONG, SUB (name_moid), 0);
1061 mode_check_unit (NEXT_NEXT (p), &name, &value);
1062 if (!is_coercible_in_context (&value, &name, FORCE_DEFLEXING)) {
1063 cannot_coerce (p, MOID (&value), MOID (&name), STRONG, FORCE_DEFLEXING, UNIT);
1064 make_soid (y, SORT (x), M_ERROR, 0);
1065 } else {
1066 make_soid (y, SORT (x), name_moid, 0);
1067 }
1068 }
1069
1070 //! @brief Mode check identity relation.
1071
1072 void mode_check_identity_relation (NODE_T * p, SOID_T * x, SOID_T * y)
1073 {
1074 NODE_T *ln = p, *rn = NEXT_NEXT (p);
1075 SOID_T e, l, r;
1076 make_soid (&e, SOFT, NO_MOID, 0);
1077 mode_check_unit (SUB (ln), &e, &l);
1078 mode_check_unit (SUB (rn), &e, &r);
1079 // SOFT coercion.
1080 MOID_T *oril = determine_unique_mode (&l, SAFE_DEFLEXING);
1081 MOID_T *orir = determine_unique_mode (&r, SAFE_DEFLEXING);
1082 MOID_T *lhs = deproc_completely (oril);
1083 MOID_T *rhs = deproc_completely (orir);
1084 if (IF_MODE_IS_WELL (lhs) && lhs != M_HIP && ATTRIBUTE (lhs) != REF_SYMBOL) {
1085 diagnostic (A68_ERROR, ln, ERROR_NO_NAME, oril, ATTRIBUTE (SUB (ln)));
1086 lhs = M_ERROR;
1087 }
1088 if (IF_MODE_IS_WELL (rhs) && rhs != M_HIP && ATTRIBUTE (rhs) != REF_SYMBOL) {
1089 diagnostic (A68_ERROR, rn, ERROR_NO_NAME, orir, ATTRIBUTE (SUB (rn)));
1090 rhs = M_ERROR;
1091 }
1092 if (lhs == M_HIP && rhs == M_HIP) {
1093 diagnostic (A68_ERROR, p, ERROR_NO_UNIQUE_MODE);
1094 }
1095 if (is_coercible (lhs, rhs, STRONG, SAFE_DEFLEXING)) {
1096 lhs = rhs;
1097 } else if (is_coercible (rhs, lhs, STRONG, SAFE_DEFLEXING)) {
1098 rhs = lhs;
1099 } else {
1100 cannot_coerce (NEXT (p), rhs, lhs, SOFT, SKIP_DEFLEXING, TERTIARY);
1101 lhs = rhs = M_ERROR;
1102 }
1103 MOID (ln) = lhs;
1104 MOID (rn) = rhs;
1105 make_soid (y, SORT (x), M_BOOL, 0);
1106 }
1107
1108 //! @brief Mode check bool functions ANDF and ORF.
1109
1110 void mode_check_bool_function (NODE_T * p, SOID_T * x, SOID_T * y)
1111 {
1112 SOID_T e, l, r;
1113 NODE_T *ln = p, *rn = NEXT_NEXT (p);
1114 make_soid (&e, STRONG, M_BOOL, 0);
1115 mode_check_unit (SUB (ln), &e, &l);
1116 if (!is_coercible_in_context (&l, &e, SAFE_DEFLEXING)) {
1117 cannot_coerce (ln, MOID (&l), MOID (&e), MEEK, SAFE_DEFLEXING, TERTIARY);
1118 }
1119 mode_check_unit (SUB (rn), &e, &r);
1120 if (!is_coercible_in_context (&r, &e, SAFE_DEFLEXING)) {
1121 cannot_coerce (rn, MOID (&r), MOID (&e), MEEK, SAFE_DEFLEXING, TERTIARY);
1122 }
1123 MOID (ln) = M_BOOL;
1124 MOID (rn) = M_BOOL;
1125 make_soid (y, SORT (x), M_BOOL, 0);
1126 }
1127
1128 //! @brief Mode check cast.
1129
1130 void mode_check_cast (NODE_T * p, SOID_T * x, SOID_T * y)
1131 {
1132 SOID_T w;
1133 mode_check_declarer (p);
1134 make_soid (&w, STRONG, MOID (p), 0);
1135 CAST (&w) = A68_TRUE;
1136 mode_check_enclosed (SUB_NEXT (p), &w, y);
1137 if (!is_coercible_in_context (y, &w, SAFE_DEFLEXING)) {
1138 cannot_coerce (NEXT (p), MOID (y), MOID (&w), STRONG, SAFE_DEFLEXING, ENCLOSED_CLAUSE);
1139 }
1140 make_soid (y, SORT (x), MOID (p), 0);
1141 }
1142
1143 //! @brief Mode check assertion.
1144
1145 void mode_check_assertion (NODE_T * p)
1146 {
1147 SOID_T w, y;
1148 make_soid (&w, STRONG, M_BOOL, 0);
1149 mode_check_enclosed (SUB_NEXT (p), &w, &y);
1150 SORT (&y) = SORT (&w);
1151 if (!is_coercible_in_context (&y, &w, NO_DEFLEXING)) {
1152 cannot_coerce (NEXT (p), MOID (&y), MOID (&w), MEEK, NO_DEFLEXING, ENCLOSED_CLAUSE);
1153 }
1154 }
1155
1156 //! @brief Mode check argument list.
1157
1158 void mode_check_argument_list (SOID_T ** r, NODE_T * p, PACK_T ** x, PACK_T ** v, PACK_T ** w)
1159 {
1160 for (; p != NO_NODE; FORWARD (p)) {
1161 if (IS (p, GENERIC_ARGUMENT_LIST)) {
1162 ATTRIBUTE (p) = ARGUMENT_LIST;
1163 }
1164 if (IS (p, ARGUMENT_LIST)) {
1165 mode_check_argument_list (r, SUB (p), x, v, w);
1166 } else if (IS (p, UNIT)) {
1167 SOID_T y, z;
1168 if (*x != NO_PACK) {
1169 make_soid (&z, STRONG, MOID (*x), 0);
1170 add_mode_to_pack_end (v, MOID (*x), NO_TEXT, p);
1171 FORWARD (*x);
1172 } else {
1173 make_soid (&z, STRONG, NO_MOID, 0);
1174 }
1175 mode_check_unit (p, &z, &y);
1176 add_to_soid_list (r, p, &y);
1177 } else if (IS (p, TRIMMER)) {
1178 SOID_T z;
1179 if (SUB (p) != NO_NODE) {
1180 diagnostic (A68_SYNTAX_ERROR, p, ERROR_SYNTAX, ARGUMENT);
1181 make_soid (&z, STRONG, M_ERROR, 0);
1182 add_mode_to_pack_end (v, M_VOID, NO_TEXT, p);
1183 add_mode_to_pack_end (w, MOID (*x), NO_TEXT, p);
1184 FORWARD (*x);
1185 } else if (*x != NO_PACK) {
1186 make_soid (&z, STRONG, MOID (*x), 0);
1187 add_mode_to_pack_end (v, M_VOID, NO_TEXT, p);
1188 add_mode_to_pack_end (w, MOID (*x), NO_TEXT, p);
1189 FORWARD (*x);
1190 } else {
1191 make_soid (&z, STRONG, NO_MOID, 0);
1192 }
1193 add_to_soid_list (r, p, &z);
1194 } else if (IS (p, SUB_SYMBOL) && !OPTION_BRACKETS (&A68_JOB)) {
1195 diagnostic (A68_SYNTAX_ERROR, p, ERROR_SYNTAX, CALL);
1196 }
1197 }
1198 }
1199
1200 //! @brief Mode check argument list 2.
1201
1202 void mode_check_argument_list_2 (NODE_T * p, PACK_T * x, SOID_T * y, PACK_T ** v, PACK_T ** w)
1203 {
1204 SOID_T *top_sl = NO_SOID;
1205 mode_check_argument_list (&top_sl, SUB (p), &x, v, w);
1206 make_soid (y, STRONG, pack_soids_in_moid (top_sl, STOWED_MODE), 0);
1207 free_soid_list (top_sl);
1208 }
1209
1210 //! @brief Mode check meek int.
1211
1212 void mode_check_meek_int (NODE_T * p)
1213 {
1214 SOID_T x, y;
1215 make_soid (&x, MEEK, M_INT, 0);
1216 mode_check_unit (p, &x, &y);
1217 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
1218 cannot_coerce (p, MOID (&y), MOID (&x), MEEK, SAFE_DEFLEXING, 0);
1219 }
1220 }
1221
1222 //! @brief Mode check trimmer.
1223
1224 void mode_check_trimmer (NODE_T * p)
1225 {
1226 if (p == NO_NODE) {
1227 return;
1228 } else if (IS (p, TRIMMER)) {
1229 mode_check_trimmer (SUB (p));
1230 } else if (IS (p, UNIT)) {
1231 mode_check_meek_int (p);
1232 mode_check_trimmer (NEXT (p));
1233 } else {
1234 mode_check_trimmer (NEXT (p));
1235 }
1236 }
1237
1238 //! @brief Mode check indexer.
1239
1240 void mode_check_indexer (NODE_T * p, int *subs, int *trims)
1241 {
1242 if (p == NO_NODE) {
1243 return;
1244 } else if (IS (p, TRIMMER)) {
1245 (*trims)++;
1246 mode_check_trimmer (SUB (p));
1247 } else if (IS (p, UNIT)) {
1248 (*subs)++;
1249 mode_check_meek_int (p);
1250 } else {
1251 mode_check_indexer (SUB (p), subs, trims);
1252 mode_check_indexer (NEXT (p), subs, trims);
1253 }
1254 }
1255
1256 //! @brief Mode check call.
1257
1258 void mode_check_call (NODE_T * p, MOID_T * n, SOID_T * x, SOID_T * y)
1259 {
1260 MOID (p) = n;
1261 // "partial_locale" is the mode of the locale.
1262 PARTIAL_LOCALE (GINFO (p)) = new_moid ();
1263 ATTRIBUTE (PARTIAL_LOCALE (GINFO (p))) = PROC_SYMBOL;
1264 PACK (PARTIAL_LOCALE (GINFO (p))) = NO_PACK;
1265 SUB (PARTIAL_LOCALE (GINFO (p))) = SUB (n);
1266 // "partial_proc" is the mode of the resulting proc.
1267 PARTIAL_PROC (GINFO (p)) = new_moid ();
1268 ATTRIBUTE (PARTIAL_PROC (GINFO (p))) = PROC_SYMBOL;
1269 PACK (PARTIAL_PROC (GINFO (p))) = NO_PACK;
1270 SUB (PARTIAL_PROC (GINFO (p))) = SUB (n);
1271 // Check arguments and construct modes.
1272 SOID_T d;
1273 mode_check_argument_list_2 (NEXT (p), PACK (n), &d, &PACK (PARTIAL_LOCALE (GINFO (p))), &PACK (PARTIAL_PROC (GINFO (p))));
1274 DIM (PARTIAL_PROC (GINFO (p))) = count_pack_members (PACK (PARTIAL_PROC (GINFO (p))));
1275 DIM (PARTIAL_LOCALE (GINFO (p))) = count_pack_members (PACK (PARTIAL_LOCALE (GINFO (p))));
1276 PARTIAL_PROC (GINFO (p)) = register_extra_mode (&TOP_MOID (&A68_JOB), PARTIAL_PROC (GINFO (p)));
1277 PARTIAL_LOCALE (GINFO (p)) = register_extra_mode (&TOP_MOID (&A68_JOB), PARTIAL_LOCALE (GINFO (p)));
1278 if (DIM (MOID (&d)) != DIM (n)) {
1279 diagnostic (A68_ERROR, p, ERROR_ARGUMENT_NUMBER, n);
1280 make_soid (y, SORT (x), SUB (n), 0);
1281 // make_soid (y, SORT (x), M_ERROR, 0);.
1282 } else {
1283 if (!is_coercible (MOID (&d), n, STRONG, ALIAS_DEFLEXING)) {
1284 cannot_coerce (p, MOID (&d), n, STRONG, ALIAS_DEFLEXING, ARGUMENT);
1285 }
1286 if (DIM (PARTIAL_PROC (GINFO (p))) == 0) {
1287 make_soid (y, SORT (x), SUB (n), 0);
1288 } else {
1289 if (OPTION_PORTCHECK (&A68_JOB)) {
1290 diagnostic (A68_WARNING | A68_FORCE_DIAGNOSTICS, NEXT (p), WARNING_EXTENSION);
1291 }
1292 make_soid (y, SORT (x), PARTIAL_PROC (GINFO (p)), 0);
1293 }
1294 }
1295 }
1296
1297 //! @brief Mode check slice.
1298
1299 void mode_check_slice (NODE_T * p, MOID_T * ori, SOID_T * x, SOID_T * y)
1300 {
1301 MOID_T *n = ori;
1302 // WEAK coercion.
1303 while ((IS_REF (n) && !is_ref_row (n)) || (IS (n, PROC_SYMBOL) && PACK (n) == NO_PACK)) {
1304 n = depref_once (n);
1305 }
1306 if (n == NO_MOID || !(SLICE (DEFLEX (n)) != NO_MOID || is_ref_row (n))) {
1307 if (IF_MODE_IS_WELL (n)) {
1308 diagnostic (A68_ERROR, p, ERROR_NO_ROW_OR_PROC, n, ATTRIBUTE (SUB (p)));
1309 }
1310 make_soid (y, SORT (x), M_ERROR, 0);
1311 }
1312
1313 MOID (p) = n;
1314 int dim = 0, subs = 0, trims = 0;
1315 mode_check_indexer (SUB_NEXT (p), &subs, &trims);
1316 BOOL_T is_ref;
1317 if ((is_ref = is_ref_row (n)) != 0) {
1318 dim = DIM (DEFLEX (SUB (n)));
1319 } else {
1320 dim = DIM (DEFLEX (n));
1321 }
1322 if ((subs + trims) != dim) {
1323 diagnostic (A68_ERROR, p, ERROR_INDEXER_NUMBER, n);
1324 make_soid (y, SORT (x), M_ERROR, 0);
1325 } else {
1326 MOID_T *m;
1327 if (subs > 0 && trims == 0) {
1328 ANNOTATION (NEXT (p)) = SLICE;
1329 m = n;
1330 } else {
1331 ANNOTATION (NEXT (p)) = TRIMMER;
1332 m = n;
1333 }
1334 while (subs > 0) {
1335 if (is_ref) {
1336 m = NAME (m);
1337 } else {
1338 if (IS_FLEX (m)) {
1339 m = SUB (m);
1340 }
1341 m = SLICE (m);
1342 }
1343 ABEND (m == NO_MOID, ERROR_INTERNAL_CONSISTENCY, __func__);
1344 subs--;
1345 }
1346 // A trim cannot be but deflexed.
1347 if (ANNOTATION (NEXT (p)) == TRIMMER && TRIM (m) != NO_MOID) {
1348 ABEND (TRIM (m) == NO_MOID, ERROR_INTERNAL_CONSISTENCY, __func__);
1349 make_soid (y, SORT (x), TRIM (m), 0);
1350 } else {
1351 make_soid (y, SORT (x), m, 0);
1352 }
1353 }
1354 }
1355
1356 //! @brief Mode check specification.
1357
1358 int mode_check_specification (NODE_T * p, SOID_T * x, SOID_T * y)
1359 {
1360 SOID_T w, d;
1361 make_soid (&w, WEAK, NO_MOID, 0);
1362 mode_check_unit (SUB (p), &w, &d);
1363 MOID_T *ori = determine_unique_mode (&d, SAFE_DEFLEXING);
1364 MOID_T *m = depref_completely (ori);
1365 if (IS (m, PROC_SYMBOL)) {
1366 // Assume CALL.
1367 mode_check_call (p, m, x, y);
1368 return CALL;
1369 } else if (IS_ROW (m) || IS_FLEX (m)) {
1370 // Assume SLICE.
1371 mode_check_slice (p, ori, x, y);
1372 return SLICE;
1373 } else {
1374 if (m != M_ERROR) {
1375 diagnostic (A68_SYNTAX_ERROR, p, ERROR_MODE_SPECIFICATION, m);
1376 }
1377 make_soid (y, SORT (x), M_ERROR, 0);
1378 return PRIMARY;
1379 }
1380 }
1381
1382 //! @brief Mode check selection.
1383
1384 void mode_check_selection (NODE_T * p, SOID_T * x, SOID_T * y)
1385 {
1386 BOOL_T deflex = A68_FALSE;
1387 NODE_T *secondary = SUB_NEXT (p);
1388 SOID_T w, d;
1389 make_soid (&w, WEAK, NO_MOID, 0);
1390 mode_check_unit (secondary, &w, &d);
1391 MOID_T *n, *ori;
1392 n = ori = determine_unique_mode (&d, SAFE_DEFLEXING);
1393 PACK_T *t = NO_PACK, *t_2 = NO_PACK;
1394 BOOL_T coerce = A68_TRUE;
1395 while (coerce) {
1396 if (IS (n, STRUCT_SYMBOL)) {
1397 coerce = A68_FALSE;
1398 t = PACK (n);
1399 } else if (IS_REF (n) && (IS_ROW (SUB (n)) || IS_FLEX (SUB (n))) && MULTIPLE (n) != NO_MOID) {
1400 coerce = A68_FALSE;
1401 deflex = A68_TRUE;
1402 t = PACK (MULTIPLE (n));
1403 } else if ((IS_ROW (n) || IS_FLEX (n)) && MULTIPLE (n) != NO_MOID) {
1404 coerce = A68_FALSE;
1405 deflex = A68_TRUE;
1406 t = PACK (MULTIPLE (n));
1407 } else if (IS_REF (n) && is_name_struct (n)) {
1408 coerce = A68_FALSE;
1409 t = PACK (NAME (n));
1410 } else if (is_deprefable (n)) {
1411 coerce = A68_TRUE;
1412 n = SUB (n);
1413 t = NO_PACK;
1414 } else {
1415 coerce = A68_FALSE;
1416 t = NO_PACK;
1417 }
1418 }
1419 if (t == NO_PACK) {
1420 if (IF_MODE_IS_WELL (MOID (&d))) {
1421 diagnostic (A68_ERROR, secondary, ERROR_NO_STRUCT, ori, ATTRIBUTE (secondary));
1422 }
1423 make_soid (y, SORT (x), M_ERROR, 0);
1424 return;
1425 }
1426 MOID (NEXT (p)) = n;
1427 char *fs = NSYMBOL (SUB (p));
1428 MOID_T *str = n;
1429 while (IS_REF (str)) {
1430 str = SUB (str);
1431 }
1432 if (IS_FLEX (str)) {
1433 str = SUB (str);
1434 }
1435 if (IS_ROW (str)) {
1436 str = SUB (str);
1437 }
1438 t_2 = PACK (str);
1439 while (t != NO_PACK && t_2 != NO_PACK) {
1440 if (TEXT (t) == fs) {
1441 MOID_T *ret = MOID (t);
1442 if (deflex && TRIM (ret) != NO_MOID) {
1443 ret = TRIM (ret);
1444 }
1445 make_soid (y, SORT (x), ret, 0);
1446 MOID (p) = ret;
1447 NODE_PACK (SUB (p)) = t_2;
1448 return;
1449 }
1450 FORWARD (t);
1451 FORWARD (t_2);
1452 }
1453 make_soid (&d, NO_SORT, n, 0);
1454 diagnostic (A68_ERROR, p, ERROR_NO_FIELD, str, fs);
1455 make_soid (y, SORT (x), M_ERROR, 0);
1456 }
1457
1458 //! @brief Mode check diagonal.
1459
1460 void mode_check_diagonal (NODE_T * p, SOID_T * x, SOID_T * y)
1461 {
1462 SOID_T w, d;
1463 NODE_T *tert;
1464 if (IS (p, TERTIARY)) {
1465 make_soid (&w, STRONG, M_INT, 0);
1466 mode_check_unit (p, &w, &d);
1467 if (!is_coercible_in_context (&d, &w, SAFE_DEFLEXING)) {
1468 cannot_coerce (p, MOID (&d), MOID (&w), MEEK, SAFE_DEFLEXING, 0);
1469 }
1470 tert = NEXT_NEXT (p);
1471 } else {
1472 tert = NEXT (p);
1473 }
1474 make_soid (&w, WEAK, NO_MOID, 0);
1475 mode_check_unit (tert, &w, &d);
1476 MOID_T *n, *ori;
1477 n = ori = determine_unique_mode (&d, SAFE_DEFLEXING);
1478 while (IS_REF (n) && !is_ref_row (n)) {
1479 n = depref_once (n);
1480 }
1481 if (n != NO_MOID && (IS_FLEX (n) || IS_REF_FLEX (n))) {
1482 if (IF_MODE_IS_WELL (n)) {
1483 diagnostic (A68_ERROR, p, ERROR_NO_FLEX_ARGUMENT, ori, TERTIARY);
1484 }
1485 make_soid (y, SORT (x), M_ERROR, 0);
1486 return;
1487 }
1488 if (n == NO_MOID || !(SLICE (DEFLEX (n)) != NO_MOID || is_ref_row (n))) {
1489 if (IF_MODE_IS_WELL (n)) {
1490 diagnostic (A68_ERROR, p, ERROR_NO_MATRIX, ori, TERTIARY);
1491 }
1492 make_soid (y, SORT (x), M_ERROR, 0);
1493 return;
1494 }
1495 BOOL_T is_ref; int dim;
1496 if ((is_ref = is_ref_row (n)) != A68_FALSE) {
1497 dim = DIM (DEFLEX (SUB (n)));
1498 } else {
1499 dim = DIM (DEFLEX (n));
1500 }
1501 if (dim != 2) {
1502 diagnostic (A68_ERROR, p, ERROR_NO_MATRIX, ori, TERTIARY);
1503 make_soid (y, SORT (x), M_ERROR, 0);
1504 return;
1505 }
1506 MOID (tert) = n;
1507 if (is_ref) {
1508 n = NAME (n);
1509 ABEND (!IS_REF (n), ERROR_INTERNAL_CONSISTENCY, PM (n));
1510 } else {
1511 n = SLICE (n);
1512 }
1513 ABEND (n == NO_MOID, ERROR_INTERNAL_CONSISTENCY, __func__);
1514 make_soid (y, SORT (x), n, 0);
1515 }
1516
1517 //! @brief Mode check transpose.
1518
1519 void mode_check_transpose (NODE_T * p, SOID_T * x, SOID_T * y)
1520 {
1521 SOID_T w, d;
1522 make_soid (&w, WEAK, NO_MOID, 0);
1523 NODE_T *tert = NEXT (p);
1524 mode_check_unit (tert, &w, &d);
1525 MOID_T *n, *ori;
1526 n = ori = determine_unique_mode (&d, SAFE_DEFLEXING);
1527 while (IS_REF (n) && !is_ref_row (n)) {
1528 n = depref_once (n);
1529 }
1530 if (n != NO_MOID && (IS_FLEX (n) || IS_REF_FLEX (n))) {
1531 if (IF_MODE_IS_WELL (n)) {
1532 diagnostic (A68_ERROR, p, ERROR_NO_FLEX_ARGUMENT, ori, TERTIARY);
1533 }
1534 make_soid (y, SORT (x), M_ERROR, 0);
1535 return;
1536 }
1537 if (n == NO_MOID || !(SLICE (DEFLEX (n)) != NO_MOID || is_ref_row (n))) {
1538 if (IF_MODE_IS_WELL (n)) {
1539 diagnostic (A68_ERROR, p, ERROR_NO_MATRIX, ori, TERTIARY);
1540 }
1541 make_soid (y, SORT (x), M_ERROR, 0);
1542 return;
1543 }
1544 int dim;
1545 if (is_ref_row (n) != A68_FALSE) {
1546 dim = DIM (DEFLEX (SUB (n)));
1547 } else {
1548 dim = DIM (DEFLEX (n));
1549 }
1550 if (dim != 2) {
1551 diagnostic (A68_ERROR, p, ERROR_NO_MATRIX, ori, TERTIARY);
1552 make_soid (y, SORT (x), M_ERROR, 0);
1553 return;
1554 }
1555 MOID (tert) = n;
1556 ABEND (n == NO_MOID, ERROR_INTERNAL_CONSISTENCY, __func__);
1557 make_soid (y, SORT (x), n, 0);
1558 }
1559
1560 //! @brief Mode check row or column function.
1561
1562 void mode_check_row_column_function (NODE_T * p, SOID_T * x, SOID_T * y)
1563 {
1564 SOID_T w, d;
1565 NODE_T *tert;
1566 if (IS (p, TERTIARY)) {
1567 make_soid (&w, STRONG, M_INT, 0);
1568 mode_check_unit (p, &w, &d);
1569 if (!is_coercible_in_context (&d, &w, SAFE_DEFLEXING)) {
1570 cannot_coerce (p, MOID (&d), MOID (&w), MEEK, SAFE_DEFLEXING, 0);
1571 }
1572 tert = NEXT_NEXT (p);
1573 } else {
1574 tert = NEXT (p);
1575 }
1576 make_soid (&w, WEAK, NO_MOID, 0);
1577 mode_check_unit (tert, &w, &d);
1578 MOID_T *n, *ori;
1579 n = ori = determine_unique_mode (&d, SAFE_DEFLEXING);
1580 while (IS_REF (n) && !is_ref_row (n)) {
1581 n = depref_once (n);
1582 }
1583 if (n != NO_MOID && (IS_FLEX (n) || IS_REF_FLEX (n))) {
1584 if (IF_MODE_IS_WELL (n)) {
1585 diagnostic (A68_ERROR, p, ERROR_NO_FLEX_ARGUMENT, ori, TERTIARY);
1586 }
1587 make_soid (y, SORT (x), M_ERROR, 0);
1588 return;
1589 }
1590 if (n == NO_MOID || !(SLICE (DEFLEX (n)) != NO_MOID || is_ref_row (n))) {
1591 if (IF_MODE_IS_WELL (n)) {
1592 diagnostic (A68_ERROR, p, ERROR_NO_VECTOR, ori, TERTIARY);
1593 }
1594 make_soid (y, SORT (x), M_ERROR, 0);
1595 return;
1596 }
1597 int dim;
1598 if (is_ref_row (n) != A68_FALSE) {
1599 dim = DIM (DEFLEX (SUB (n)));
1600 } else {
1601 dim = DIM (DEFLEX (n));
1602 }
1603 if (dim != 1) {
1604 diagnostic (A68_ERROR, p, ERROR_NO_VECTOR, ori, TERTIARY);
1605 make_soid (y, SORT (x), M_ERROR, 0);
1606 return;
1607 }
1608 MOID (tert) = n;
1609 ABEND (n == NO_MOID, ERROR_INTERNAL_CONSISTENCY, __func__);
1610 make_soid (y, SORT (x), ROWED (n), 0);
1611 }
1612
1613 //! @brief Mode check format text.
1614
1615 void mode_check_format_text (NODE_T * p)
1616 {
1617 for (; p != NO_NODE; FORWARD (p)) {
1618 mode_check_format_text (SUB (p));
1619 if (IS (p, FORMAT_PATTERN)) {
1620 SOID_T x, y;
1621 make_soid (&x, STRONG, M_FORMAT, 0);
1622 mode_check_enclosed (SUB (NEXT_SUB (p)), &x, &y);
1623 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
1624 cannot_coerce (p, MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, ENCLOSED_CLAUSE);
1625 }
1626 } else if (IS (p, GENERAL_PATTERN) && NEXT_SUB (p) != NO_NODE) {
1627 SOID_T x, y;
1628 make_soid (&x, STRONG, M_ROW_INT, 0);
1629 mode_check_enclosed (SUB (NEXT_SUB (p)), &x, &y);
1630 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
1631 cannot_coerce (p, MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, ENCLOSED_CLAUSE);
1632 }
1633 } else if (IS (p, DYNAMIC_REPLICATOR)) {
1634 SOID_T x, y;
1635 make_soid (&x, STRONG, M_INT, 0);
1636 mode_check_enclosed (SUB (NEXT_SUB (p)), &x, &y);
1637 if (!is_coercible_in_context (&y, &x, SAFE_DEFLEXING)) {
1638 cannot_coerce (p, MOID (&y), MOID (&x), STRONG, SAFE_DEFLEXING, ENCLOSED_CLAUSE);
1639 }
1640 }
1641 }
1642 }
1643
1644 //! @brief Mode check unit.
1645
1646 void mode_check_unit (NODE_T * p, SOID_T * x, SOID_T * y)
1647 {
1648 if (p == NO_NODE) {
1649 return;
1650 } else if (is_one_of (p, UNIT, TERTIARY, SECONDARY, PRIMARY, STOP)) {
1651 mode_check_unit (SUB (p), x, y);
1652 // Ex primary.
1653 } else if (IS (p, SPECIFICATION)) {
1654 ATTRIBUTE (p) = mode_check_specification (SUB (p), x, y);
1655 warn_for_voiding (p, x, y, ATTRIBUTE (p));
1656 } else if (IS (p, CAST)) {
1657 mode_check_cast (SUB (p), x, y);
1658 warn_for_voiding (p, x, y, CAST);
1659 } else if (IS (p, DENOTATION)) {
1660 make_soid (y, SORT (x), MOID (SUB (p)), 0);
1661 warn_for_voiding (p, x, y, DENOTATION);
1662 } else if (IS (p, IDENTIFIER)) {
1663 if ((TAX (p) == NO_TAG) && (MOID (p) == NO_MOID)) {
1664 int att = first_tag_global (TABLE (p), NSYMBOL (p));
1665 if (att == STOP) {
1666 (void) add_tag (TABLE (p), IDENTIFIER, p, M_ERROR, NORMAL_IDENTIFIER);
1667 diagnostic (A68_ERROR, p, ERROR_UNDECLARED_TAG);
1668 MOID (p) = M_ERROR;
1669 } else {
1670 TAG_T *z = find_tag_global (TABLE (p), att, NSYMBOL (p));
1671 if (att == IDENTIFIER && z != NO_TAG) {
1672 MOID (p) = MOID (z);
1673 } else {
1674 (void) add_tag (TABLE (p), IDENTIFIER, p, M_ERROR, NORMAL_IDENTIFIER);
1675 diagnostic (A68_ERROR, p, ERROR_UNDECLARED_TAG);
1676 MOID (p) = M_ERROR;
1677 }
1678 }
1679 }
1680 make_soid (y, SORT (x), MOID (p), 0);
1681 warn_for_voiding (p, x, y, IDENTIFIER);
1682 } else if (IS (p, ENCLOSED_CLAUSE)) {
1683 mode_check_enclosed (SUB (p), x, y);
1684 } else if (IS (p, FORMAT_TEXT)) {
1685 mode_check_format_text (p);
1686 make_soid (y, SORT (x), M_FORMAT, 0);
1687 warn_for_voiding (p, x, y, FORMAT_TEXT);
1688 // Ex secondary.
1689 } else if (IS (p, GENERATOR)) {
1690 mode_check_declarer (SUB (p));
1691 make_soid (y, SORT (x), MOID (SUB (p)), 0);
1692 warn_for_voiding (p, x, y, GENERATOR);
1693 } else if (IS (p, SELECTION)) {
1694 mode_check_selection (SUB (p), x, y);
1695 warn_for_voiding (p, x, y, SELECTION);
1696 // Ex tertiary.
1697 } else if (IS (p, NIHIL)) {
1698 make_soid (y, STRONG, M_HIP, 0);
1699 } else if (IS (p, FORMULA)) {
1700 mode_check_formula (p, x, y);
1701 if (!IS_REF (MOID (y))) {
1702 warn_for_voiding (p, x, y, FORMULA);
1703 }
1704 } else if (IS (p, DIAGONAL_FUNCTION)) {
1705 mode_check_diagonal (SUB (p), x, y);
1706 warn_for_voiding (p, x, y, DIAGONAL_FUNCTION);
1707 } else if (IS (p, TRANSPOSE_FUNCTION)) {
1708 mode_check_transpose (SUB (p), x, y);
1709 warn_for_voiding (p, x, y, TRANSPOSE_FUNCTION);
1710 } else if (IS (p, ROW_FUNCTION)) {
1711 mode_check_row_column_function (SUB (p), x, y);
1712 warn_for_voiding (p, x, y, ROW_FUNCTION);
1713 } else if (IS (p, COLUMN_FUNCTION)) {
1714 mode_check_row_column_function (SUB (p), x, y);
1715 warn_for_voiding (p, x, y, COLUMN_FUNCTION);
1716 // Ex unit.
1717 } else if (is_one_of (p, JUMP, SKIP, STOP)) {
1718 if (SORT (x) != STRONG) {
1719 diagnostic (A68_WARNING, p, WARNING_HIP, SORT (x));
1720 }
1721 // make_soid (y, STRONG, M_HIP, 0);
1722 make_soid (y, SORT (x), M_HIP, 0);
1723 } else if (IS (p, ASSIGNATION)) {
1724 mode_check_assignation (SUB (p), x, y);
1725 } else if (IS (p, IDENTITY_RELATION)) {
1726 mode_check_identity_relation (SUB (p), x, y);
1727 warn_for_voiding (p, x, y, IDENTITY_RELATION);
1728 } else if (IS (p, ROUTINE_TEXT)) {
1729 mode_check_routine_text (SUB (p), y);
1730 make_soid (y, SORT (x), MOID (p), 0);
1731 warn_for_voiding (p, x, y, ROUTINE_TEXT);
1732 } else if (IS (p, ASSERTION)) {
1733 mode_check_assertion (SUB (p));
1734 make_soid (y, STRONG, M_VOID, 0);
1735 } else if (IS (p, AND_FUNCTION)) {
1736 mode_check_bool_function (SUB (p), x, y);
1737 warn_for_voiding (p, x, y, AND_FUNCTION);
1738 } else if (IS (p, OR_FUNCTION)) {
1739 mode_check_bool_function (SUB (p), x, y);
1740 warn_for_voiding (p, x, y, OR_FUNCTION);
1741 } else if (IS (p, CODE_CLAUSE)) {
1742 make_soid (y, STRONG, M_HIP, 0);
1743 }
1744 MOID (p) = MOID (y);
1745 }
1746
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|