parser-taxes.c
1 //! @file parser-taxes.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 //! Symbol table management.
25
26 #include "a68g.h"
27 #include "a68g-parser.h"
28
29 // Symbol table handling, managing TAGS.
30
31 //! @brief Set level for procedures.
32
33 void set_proc_level (NODE_T * p, int n)
34 {
35 for (; p != NO_NODE; FORWARD (p)) {
36 PROCEDURE_LEVEL (INFO (p)) = n;
37 if (IS (p, ROUTINE_TEXT)) {
38 set_proc_level (SUB (p), n + 1);
39 } else {
40 set_proc_level (SUB (p), n);
41 }
42 }
43 }
44
45 //! @brief Set nests for diagnostics.
46
47 void set_nest (NODE_T * p, NODE_T * s)
48 {
49 for (; p != NO_NODE; FORWARD (p)) {
50 NEST (p) = s;
51 if (IS (p, PARTICULAR_PROGRAM)) {
52 set_nest (SUB (p), p);
53 } else if (IS (p, CLOSED_CLAUSE) && LINE_NUMBER (p) != 0) {
54 set_nest (SUB (p), p);
55 } else if (IS (p, COLLATERAL_CLAUSE) && LINE_NUMBER (p) != 0) {
56 set_nest (SUB (p), p);
57 } else if (IS (p, CONDITIONAL_CLAUSE) && LINE_NUMBER (p) != 0) {
58 set_nest (SUB (p), p);
59 } else if (IS (p, CASE_CLAUSE) && LINE_NUMBER (p) != 0) {
60 set_nest (SUB (p), p);
61 } else if (IS (p, CONFORMITY_CLAUSE) && LINE_NUMBER (p) != 0) {
62 set_nest (SUB (p), p);
63 } else if (IS (p, LOOP_CLAUSE) && LINE_NUMBER (p) != 0) {
64 set_nest (SUB (p), p);
65 } else {
66 set_nest (SUB (p), s);
67 }
68 }
69 }
70
71 // Routines that work with tags and symbol tables.
72
73 void tax_tags (NODE_T *);
74 void tax_specifier_list (NODE_T *);
75 void tax_parameter_list (NODE_T *);
76 void tax_format_texts (NODE_T *);
77
78 //! @brief Find a tag, searching symbol tables towards the root.
79
80 int first_tag_global (TABLE_T * table, char *name)
81 {
82 if (table != NO_TABLE) {
83 for (TAG_T *s = IDENTIFIERS (table); s != NO_TAG; FORWARD (s)) {
84 if (NSYMBOL (NODE (s)) == name) {
85 return IDENTIFIER;
86 }
87 }
88 for (TAG_T *s = INDICANTS (table); s != NO_TAG; FORWARD (s)) {
89 if (NSYMBOL (NODE (s)) == name) {
90 return INDICANT;
91 }
92 }
93 for (TAG_T *s = LABELS (table); s != NO_TAG; FORWARD (s)) {
94 if (NSYMBOL (NODE (s)) == name) {
95 return LABEL;
96 }
97 }
98 for (TAG_T *s = OPERATORS (table); s != NO_TAG; FORWARD (s)) {
99 if (NSYMBOL (NODE (s)) == name) {
100 return OP_SYMBOL;
101 }
102 }
103 for (TAG_T *s = PRIO (table); s != NO_TAG; FORWARD (s)) {
104 if (NSYMBOL (NODE (s)) == name) {
105 return PRIO_SYMBOL;
106 }
107 }
108 return first_tag_global (PREVIOUS (table), name);
109 } else {
110 return STOP;
111 }
112 }
113
114 #define PORTCHECK_TAX(p, q) {\
115 if (q == A68_FALSE) {\
116 diagnostic (A68_WARNING | A68_FORCE_DIAGNOSTICS, p, WARNING_TAG_NOT_PORTABLE);\
117 }}
118
119 //! @brief Check portability of sub tree.
120
121 void portcheck (NODE_T * p)
122 {
123 for (; p != NO_NODE; FORWARD (p)) {
124 portcheck (SUB (p));
125 if (OPTION_PORTCHECK (&A68_JOB)) {
126 if (IS (p, INDICANT) && MOID (p) != NO_MOID) {
127 PORTCHECK_TAX (p, PORTABLE (MOID (p)));
128 PORTABLE (MOID (p)) = A68_TRUE;
129 } else if (IS (p, IDENTIFIER)) {
130 PORTCHECK_TAX (p, PORTABLE (TAX (p)));
131 PORTABLE (TAX (p)) = A68_TRUE;
132 } else if (IS (p, OPERATOR)) {
133 PORTCHECK_TAX (p, PORTABLE (TAX (p)));
134 PORTABLE (TAX (p)) = A68_TRUE;
135 } else if (IS (p, ASSERTION)) {
136 diagnostic (A68_WARNING | A68_FORCE_DIAGNOSTICS, p, WARNING_TAG_NOT_PORTABLE);
137 }
138 }
139 }
140 }
141
142 //! @brief Whether routine can be "lengthety-mapped".
143
144 BOOL_T is_mappable_routine (char *z)
145 {
146 #define ACCEPT(u, v) {\
147 if (strlen (u) >= strlen (v)) {\
148 if (strcmp (&u[strlen (u) - strlen (v)], v) == 0) {\
149 return A68_TRUE;\
150 }}}
151 // Math routines.
152 ACCEPT (z, "arccos");
153 ACCEPT (z, "arccosdg");
154 ACCEPT (z, "arccot");
155 ACCEPT (z, "arccotdg");
156 ACCEPT (z, "arcsin");
157 ACCEPT (z, "arcsindg");
158 ACCEPT (z, "arctan");
159 ACCEPT (z, "arctandg");
160 ACCEPT (z, "beta");
161 ACCEPT (z, "betainc");
162 ACCEPT (z, "cbrt");
163 ACCEPT (z, "cos");
164 ACCEPT (z, "cosdg");
165 ACCEPT (z, "cospi");
166 ACCEPT (z, "cot");
167 ACCEPT (z, "cot");
168 ACCEPT (z, "cotdg");
169 ACCEPT (z, "cotpi");
170 ACCEPT (z, "curt");
171 ACCEPT (z, "erf");
172 ACCEPT (z, "erfc");
173 ACCEPT (z, "exp");
174 ACCEPT (z, "gamma");
175 ACCEPT (z, "gammainc");
176 ACCEPT (z, "gammaincg");
177 ACCEPT (z, "gammaincgf");
178 ACCEPT (z, "ln");
179 ACCEPT (z, "log");
180 ACCEPT (z, "pi");
181 ACCEPT (z, "sin");
182 ACCEPT (z, "sindg");
183 ACCEPT (z, "sinpi");
184 ACCEPT (z, "sqrt");
185 ACCEPT (z, "tan");
186 ACCEPT (z, "tandg");
187 ACCEPT (z, "tanpi");
188 // Random generator.
189 ACCEPT (z, "nextrandom");
190 ACCEPT (z, "random");
191 // BITS.
192 ACCEPT (z, "bitspack");
193 // Enquiries.
194 ACCEPT (z, "maxint");
195 ACCEPT (z, "intwidth");
196 ACCEPT (z, "maxreal");
197 ACCEPT (z, "realwidth");
198 ACCEPT (z, "expwidth");
199 ACCEPT (z, "maxbits");
200 ACCEPT (z, "bitswidth");
201 ACCEPT (z, "byteswidth");
202 ACCEPT (z, "smallreal");
203 return A68_FALSE;
204 #undef ACCEPT
205 }
206
207 //! @brief Map "short sqrt" onto "sqrt" etcetera.
208
209 TAG_T *bind_lengthety_identifier (char *u)
210 {
211 #define CAR(u, v) (strncmp (u, v, strlen(v)) == 0)
212 // We can only map routines blessed by "is_mappable_routine", so there is no
213 // "short print" or "long char in string".
214 if (CAR (u, "short")) {
215 do {
216 u = &u[strlen ("short")];
217 char *v = TEXT (add_token (&A68 (top_token), u));
218 TAG_T *w = find_tag_local (A68_STANDENV, IDENTIFIER, v);
219 if (w != NO_TAG && is_mappable_routine (v)) {
220 return w;
221 }
222 } while (CAR (u, "short"));
223 } else if (CAR (u, "long")) {
224 do {
225 u = &u[strlen ("long")];
226 char *v = TEXT (add_token (&A68 (top_token), u));
227 TAG_T *w = find_tag_local (A68_STANDENV, IDENTIFIER, v);
228 if (w != NO_TAG && is_mappable_routine (v)) {
229 return w;
230 }
231 } while (CAR (u, "long"));
232 }
233 return NO_TAG;
234 #undef CAR
235 }
236
237 //! @brief Bind identifier tags to the symbol table.
238
239 void bind_identifier_tag_to_symbol_table (NODE_T * p)
240 {
241 for (; p != NO_NODE; FORWARD (p)) {
242 bind_identifier_tag_to_symbol_table (SUB (p));
243 if (is_one_of (p, IDENTIFIER, DEFINING_IDENTIFIER, STOP)) {
244 int att = first_tag_global (TABLE (p), NSYMBOL (p));
245 if (att == STOP) {
246 TAG_T *z = bind_lengthety_identifier (NSYMBOL (p));
247 if (z != NO_TAG) {
248 MOID (p) = MOID (z);
249 }
250 TAX (p) = z;
251 } else {
252 TAG_T *z = find_tag_global (TABLE (p), att, NSYMBOL (p));
253 if (att == IDENTIFIER && z != NO_TAG) {
254 MOID (p) = MOID (z);
255 } else if (att == LABEL && z != NO_TAG) {
256 ;
257 } else if ((z = bind_lengthety_identifier (NSYMBOL (p))) != NO_TAG) {
258 MOID (p) = MOID (z);
259 } else {
260 diagnostic (A68_ERROR, p, ERROR_UNDECLARED_TAG);
261 z = add_tag (TABLE (p), IDENTIFIER, p, M_ERROR, NORMAL_IDENTIFIER);
262 MOID (p) = M_ERROR;
263 }
264 TAX (p) = z;
265 if (IS (p, DEFINING_IDENTIFIER)) {
266 NODE (z) = p;
267 }
268 }
269 }
270 }
271 }
272
273 //! @brief Bind indicant tags to the symbol table.
274
275 void bind_indicant_tag_to_symbol_table (NODE_T * p)
276 {
277 for (; p != NO_NODE; FORWARD (p)) {
278 bind_indicant_tag_to_symbol_table (SUB (p));
279 if (is_one_of (p, INDICANT, DEFINING_INDICANT, STOP)) {
280 TAG_T *z = find_tag_global (TABLE (p), INDICANT, NSYMBOL (p));
281 if (z != NO_TAG) {
282 MOID (p) = MOID (z);
283 TAX (p) = z;
284 if (IS (p, DEFINING_INDICANT)) {
285 NODE (z) = p;
286 }
287 }
288 }
289 }
290 }
291
292 //! @brief Enter specifier identifiers in the symbol table.
293
294 void tax_specifiers (NODE_T * p)
295 {
296 for (; p != NO_NODE; FORWARD (p)) {
297 tax_specifiers (SUB (p));
298 if (SUB (p) != NO_NODE && IS (p, SPECIFIER)) {
299 tax_specifier_list (SUB (p));
300 }
301 }
302 }
303
304 //! @brief Enter specifier identifiers in the symbol table.
305
306 void tax_specifier_list (NODE_T * p)
307 {
308 if (p != NO_NODE) {
309 if (IS (p, OPEN_SYMBOL)) {
310 tax_specifier_list (NEXT (p));
311 } else if (is_one_of (p, CLOSE_SYMBOL, VOID_SYMBOL, STOP)) {
312 ;
313 } else if (IS (p, IDENTIFIER)) {
314 TAG_T *z = add_tag (TABLE (p), IDENTIFIER, p, NO_MOID, SPECIFIER_IDENTIFIER);
315 HEAP (z) = LOC_SYMBOL;
316 } else if (IS (p, DECLARER)) {
317 tax_specifiers (SUB (p));
318 tax_specifier_list (NEXT (p));
319 // last identifier entry is identifier with this declarer.
320 if (IDENTIFIERS (TABLE (p)) != NO_TAG && PRIO (IDENTIFIERS (TABLE (p))) == SPECIFIER_IDENTIFIER)
321 MOID (IDENTIFIERS (TABLE (p))) = MOID (p);
322 }
323 }
324 }
325
326 //! @brief Enter parameter identifiers in the symbol table.
327
328 void tax_parameters (NODE_T * p)
329 {
330 for (; p != NO_NODE; FORWARD (p)) {
331 if (SUB (p) != NO_NODE) {
332 tax_parameters (SUB (p));
333 if (IS (p, PARAMETER_PACK)) {
334 tax_parameter_list (SUB (p));
335 }
336 }
337 }
338 }
339
340 //! @brief Enter parameter identifiers in the symbol table.
341
342 void tax_parameter_list (NODE_T * p)
343 {
344 if (p != NO_NODE) {
345 if (is_one_of (p, OPEN_SYMBOL, COMMA_SYMBOL, STOP)) {
346 tax_parameter_list (NEXT (p));
347 } else if (IS (p, CLOSE_SYMBOL)) {
348 ;
349 } else if (is_one_of (p, PARAMETER_LIST, PARAMETER, STOP)) {
350 tax_parameter_list (NEXT (p));
351 tax_parameter_list (SUB (p));
352 } else if (IS (p, IDENTIFIER)) {
353 // parameters are always local.
354 HEAP (add_tag (TABLE (p), IDENTIFIER, p, NO_MOID, PARAMETER_IDENTIFIER)) = LOC_SYMBOL;
355 } else if (IS (p, DECLARER)) {
356 tax_parameter_list (NEXT (p));
357 // last identifier entries are identifiers with this declarer.
358 for (TAG_T *s = IDENTIFIERS (TABLE (p)); s != NO_TAG && MOID (s) == NO_MOID; FORWARD (s)) {
359 MOID (s) = MOID (p);
360 }
361 tax_parameters (SUB (p));
362 }
363 }
364 }
365
366 //! @brief Enter FOR identifiers in the symbol table.
367
368 void tax_for_identifiers (NODE_T * p)
369 {
370 for (; p != NO_NODE; FORWARD (p)) {
371 tax_for_identifiers (SUB (p));
372 if (IS (p, FOR_SYMBOL)) {
373 if ((FORWARD (p)) != NO_NODE) {
374 (void) add_tag (TABLE (p), IDENTIFIER, p, M_INT, LOOP_IDENTIFIER);
375 }
376 }
377 }
378 }
379
380 //! @brief Enter routine texts in the symbol table.
381
382 void tax_routine_texts (NODE_T * p)
383 {
384 for (; p != NO_NODE; FORWARD (p)) {
385 tax_routine_texts (SUB (p));
386 if (IS (p, ROUTINE_TEXT)) {
387 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, MOID (p), ROUTINE_TEXT);
388 TAX (p) = z;
389 HEAP (z) = LOC_SYMBOL;
390 USE (z) = A68_TRUE;
391 }
392 }
393 }
394
395 //! @brief Enter format texts in the symbol table.
396
397 void tax_format_texts (NODE_T * p)
398 {
399 for (; p != NO_NODE; FORWARD (p)) {
400 tax_format_texts (SUB (p));
401 if (IS (p, FORMAT_TEXT)) {
402 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, M_FORMAT, FORMAT_TEXT);
403 TAX (p) = z;
404 USE (z) = A68_TRUE;
405 } else if (IS (p, FORMAT_DELIMITER_SYMBOL) && NEXT (p) != NO_NODE) {
406 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, M_FORMAT, FORMAT_IDENTIFIER);
407 TAX (p) = z;
408 USE (z) = A68_TRUE;
409 }
410 }
411 }
412
413 //! @brief Enter FORMAT pictures in the symbol table.
414
415 void tax_pictures (NODE_T * p)
416 {
417 for (; p != NO_NODE; FORWARD (p)) {
418 tax_pictures (SUB (p));
419 if (IS (p, PICTURE)) {
420 TAX (p) = add_tag (TABLE (p), ANONYMOUS, p, M_COLLITEM, FORMAT_IDENTIFIER);
421 }
422 }
423 }
424
425 //! @brief Enter generators in the symbol table.
426
427 void tax_generators (NODE_T * p)
428 {
429 for (; p != NO_NODE; FORWARD (p)) {
430 tax_generators (SUB (p));
431 if (IS (p, GENERATOR)) {
432 if (IS (SUB (p), LOC_SYMBOL)) {
433 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, SUB_MOID (SUB (p)), GENERATOR);
434 HEAP (z) = LOC_SYMBOL;
435 USE (z) = A68_TRUE;
436 TAX (p) = z;
437 }
438 }
439 }
440 }
441
442 //! @brief Find a firmly related operator for operands.
443
444 TAG_T *find_firmly_related_op (TABLE_T * c, const char *n, MOID_T * l, MOID_T * r, const TAG_T * self)
445 {
446 if (c != NO_TABLE) {
447 TAG_T *s = OPERATORS (c);
448 for (; s != NO_TAG; FORWARD (s)) {
449 if (s != self && NSYMBOL (NODE (s)) == n) {
450 PACK_T *t = PACK (MOID (s));
451 if (t != NO_PACK && is_firm (MOID (t), l)) {
452 // catch monadic operator.
453 if ((FORWARD (t)) == NO_PACK) {
454 if (r == NO_MOID) {
455 return s;
456 }
457 } else {
458 // catch dyadic operator.
459 if (r != NO_MOID && is_firm (MOID (t), r)) {
460 return s;
461 }
462 }
463 }
464 }
465 }
466 }
467 return NO_TAG;
468 }
469
470 //! @brief Check for firmly related operators in this range.
471
472 void test_firmly_related_ops_local (NODE_T * p, TAG_T * s)
473 {
474 if (s != NO_TAG) {
475 PACK_T *u = PACK (MOID (s));
476 if (u != NO_PACK) {
477 MOID_T *l = MOID (u);
478 MOID_T *r = (NEXT (u) != NO_PACK ? MOID (NEXT (u)) : NO_MOID);
479 TAG_T *t = find_firmly_related_op (TAG_TABLE (s), NSYMBOL (NODE (s)), l, r, s);
480 if (t != NO_TAG) {
481 if (TAG_TABLE (t) == A68_STANDENV) {
482 diagnostic (A68_ERROR, p, ERROR_OPERATOR_RELATED, MOID (s), NSYMBOL (NODE (s)), MOID (t), NSYMBOL (NODE (t)));
483 ABEND (A68_TRUE, ERROR_INTERNAL_CONSISTENCY, __func__);
484 } else {
485 diagnostic (A68_ERROR, p, ERROR_OPERATOR_RELATED, MOID (s), NSYMBOL (NODE (s)), MOID (t), NSYMBOL (NODE (t)));
486 }
487 }
488 }
489 if (NEXT (s) != NO_TAG) {
490 test_firmly_related_ops_local ((p == NO_NODE ? NO_NODE : NODE (NEXT (s))), NEXT (s));
491 }
492 }
493 }
494
495 //! @brief Find firmly related operators in this program.
496
497 void test_firmly_related_ops (NODE_T * p)
498 {
499 for (; p != NO_NODE; FORWARD (p)) {
500 if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
501 TAG_T *oops = OPERATORS (TABLE (SUB (p)));
502 if (oops != NO_TAG) {
503 test_firmly_related_ops_local (NODE (oops), oops);
504 }
505 }
506 test_firmly_related_ops (SUB (p));
507 }
508 }
509
510 //! @brief Driver for the processing of TAXes.
511
512 void collect_taxes (NODE_T * p)
513 {
514 tax_tags (p);
515 tax_specifiers (p);
516 tax_parameters (p);
517 tax_for_identifiers (p);
518 tax_routine_texts (p);
519 tax_pictures (p);
520 tax_format_texts (p);
521 tax_generators (p);
522 bind_identifier_tag_to_symbol_table (p);
523 bind_indicant_tag_to_symbol_table (p);
524 test_firmly_related_ops (p);
525 test_firmly_related_ops_local (NO_NODE, OPERATORS (A68_STANDENV));
526 }
527
528 //! @brief Whether tag has already been declared in this range.
529
530 void already_declared (NODE_T * n, int a)
531 {
532 if (find_tag_local (TABLE (n), a, NSYMBOL (n)) != NO_TAG) {
533 diagnostic (A68_ERROR, n, ERROR_MULTIPLE_TAG);
534 }
535 }
536
537 //! @brief Whether tag has already been declared in this range.
538
539 void already_declared_hidden (NODE_T * n, int a)
540 {
541 if (find_tag_local (TABLE (n), a, NSYMBOL (n)) != NO_TAG) {
542 diagnostic (A68_ERROR, n, ERROR_MULTIPLE_TAG);
543 }
544 TAG_T *s = find_tag_global (PREVIOUS (TABLE (n)), a, NSYMBOL (n));
545 if (s != NO_TAG) {
546 if (TAG_TABLE (s) == A68_STANDENV) {
547 diagnostic (A68_WARNING, n, WARNING_HIDES_PRELUDE, MOID (s), NSYMBOL (n));
548 } else {
549 diagnostic (A68_WARNING, n, WARNING_HIDES, NSYMBOL (n));
550 }
551 }
552 }
553
554 //! @brief Add tag to local symbol table.
555
556 TAG_T *add_tag (TABLE_T * s, int a, NODE_T * n, MOID_T * m, int p)
557 {
558 #define INSERT_TAG(l, n) {NEXT (n) = *(l); *(l) = (n);}
559 if (s != NO_TABLE) {
560 TAG_T *z = new_tag ();
561 TAG_TABLE (z) = s;
562 PRIO (z) = p;
563 MOID (z) = m;
564 NODE (z) = n;
565 // TAX (n) = z;.
566 switch (a) {
567 case IDENTIFIER: {
568 already_declared_hidden (n, IDENTIFIER);
569 already_declared_hidden (n, LABEL);
570 INSERT_TAG (&IDENTIFIERS (s), z);
571 break;
572 }
573 case INDICANT: {
574 already_declared_hidden (n, INDICANT);
575 already_declared (n, OP_SYMBOL);
576 already_declared (n, PRIO_SYMBOL);
577 INSERT_TAG (&INDICANTS (s), z);
578 break;
579 }
580 case LABEL: {
581 already_declared_hidden (n, LABEL);
582 already_declared_hidden (n, IDENTIFIER);
583 INSERT_TAG (&LABELS (s), z);
584 break;
585 }
586 case OP_SYMBOL: {
587 already_declared (n, INDICANT);
588 INSERT_TAG (&OPERATORS (s), z);
589 break;
590 }
591 case PRIO_SYMBOL: {
592 already_declared (n, PRIO_SYMBOL);
593 already_declared (n, INDICANT);
594 INSERT_TAG (&PRIO (s), z);
595 break;
596 }
597 case ANONYMOUS: {
598 INSERT_TAG (&ANONYMOUS (s), z);
599 break;
600 }
601 default: {
602 ABEND (A68_TRUE, ERROR_INTERNAL_CONSISTENCY, __func__);
603 }
604 }
605 return z;
606 } else {
607 return NO_TAG;
608 }
609 }
610
611 //! @brief Find a tag, searching symbol tables towards the root.
612
613 TAG_T *find_tag_global (TABLE_T * table, int a, char *name)
614 {
615 if (table != NO_TABLE) {
616 TAG_T *s = NO_TAG;
617 switch (a) {
618 case IDENTIFIER: {
619 s = IDENTIFIERS (table);
620 break;
621 }
622 case INDICANT: {
623 s = INDICANTS (table);
624 break;
625 }
626 case LABEL: {
627 s = LABELS (table);
628 break;
629 }
630 case OP_SYMBOL: {
631 s = OPERATORS (table);
632 break;
633 }
634 case PRIO_SYMBOL: {
635 s = PRIO (table);
636 break;
637 }
638 default: {
639 ABEND (A68_TRUE, ERROR_INTERNAL_CONSISTENCY, __func__);
640 break;
641 }
642 }
643 for (; s != NO_TAG; FORWARD (s)) {
644 if (NSYMBOL (NODE (s)) == name) {
645 return s;
646 }
647 }
648 return find_tag_global (PREVIOUS (table), a, name);
649 } else {
650 return NO_TAG;
651 }
652 }
653
654 //! @brief Whether identifier or label global.
655
656 int is_identifier_or_label_global (TABLE_T * table, char *name)
657 {
658 if (table != NO_TABLE) {
659 for (TAG_T *s = IDENTIFIERS (table); s != NO_TAG; FORWARD (s)) {
660 if (NSYMBOL (NODE (s)) == name) {
661 return IDENTIFIER;
662 }
663 }
664 for (TAG_T *s = LABELS (table); s != NO_TAG; FORWARD (s)) {
665 if (NSYMBOL (NODE (s)) == name) {
666 return LABEL;
667 }
668 }
669 return is_identifier_or_label_global (PREVIOUS (table), name);
670 } else {
671 return 0;
672 }
673 }
674
675 //! @brief Find a tag, searching only local symbol table.
676
677 TAG_T *find_tag_local (TABLE_T * table, int a, const char *name)
678 {
679 if (table != NO_TABLE) {
680 TAG_T *s = NO_TAG;
681 if (a == OP_SYMBOL) {
682 s = OPERATORS (table);
683 } else if (a == PRIO_SYMBOL) {
684 s = PRIO (table);
685 } else if (a == IDENTIFIER) {
686 s = IDENTIFIERS (table);
687 } else if (a == INDICANT) {
688 s = INDICANTS (table);
689 } else if (a == LABEL) {
690 s = LABELS (table);
691 } else {
692 ABEND (A68_TRUE, ERROR_INTERNAL_CONSISTENCY, __func__);
693 }
694 for (; s != NO_TAG; FORWARD (s)) {
695 if (NSYMBOL (NODE (s)) == name) {
696 return s;
697 }
698 }
699 }
700 return NO_TAG;
701 }
702
703 //! @brief Whether context specifies HEAP or LOC for an identifier.
704
705 int tab_qualifier (NODE_T * p)
706 {
707 if (p != NO_NODE) {
708 if (is_one_of (p, UNIT, ASSIGNATION, TERTIARY, SECONDARY, GENERATOR, STOP)) {
709 return tab_qualifier (SUB (p));
710 } else if (is_one_of (p, LOC_SYMBOL, HEAP_SYMBOL, NEW_SYMBOL, STOP)) {
711 return ATTRIBUTE (p) == LOC_SYMBOL ? LOC_SYMBOL : HEAP_SYMBOL;
712 } else {
713 return LOC_SYMBOL;
714 }
715 } else {
716 return LOC_SYMBOL;
717 }
718 }
719
720 //! @brief Enter identity declarations in the symbol table.
721
722 void tax_identity_dec (NODE_T * p, MOID_T ** m)
723 {
724 if (p != NO_NODE) {
725 if (IS (p, IDENTITY_DECLARATION)) {
726 tax_identity_dec (SUB (p), m);
727 tax_identity_dec (NEXT (p), m);
728 } else if (IS (p, DECLARER)) {
729 tax_tags (SUB (p));
730 *m = MOID (p);
731 tax_identity_dec (NEXT (p), m);
732 } else if (IS (p, COMMA_SYMBOL)) {
733 tax_identity_dec (NEXT (p), m);
734 } else if (IS (p, DEFINING_IDENTIFIER)) {
735 TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
736 MOID (p) = *m;
737 HEAP (entry) = LOC_SYMBOL;
738 TAX (p) = entry;
739 MOID (entry) = *m;
740 if (ATTRIBUTE (*m) == REF_SYMBOL) {
741 HEAP (entry) = tab_qualifier (NEXT_NEXT (p));
742 }
743 tax_identity_dec (NEXT_NEXT (p), m);
744 } else {
745 tax_tags (p);
746 }
747 }
748 }
749
750 //! @brief Enter variable declarations in the symbol table.
751
752 void tax_variable_dec (NODE_T * p, int *q, MOID_T ** m)
753 {
754 if (p != NO_NODE) {
755 if (IS (p, VARIABLE_DECLARATION)) {
756 tax_variable_dec (SUB (p), q, m);
757 tax_variable_dec (NEXT (p), q, m);
758 } else if (IS (p, DECLARER)) {
759 tax_tags (SUB (p));
760 *m = MOID (p);
761 tax_variable_dec (NEXT (p), q, m);
762 } else if (IS (p, QUALIFIER)) {
763 *q = ATTRIBUTE (SUB (p));
764 tax_variable_dec (NEXT (p), q, m);
765 } else if (IS (p, COMMA_SYMBOL)) {
766 tax_variable_dec (NEXT (p), q, m);
767 } else if (IS (p, DEFINING_IDENTIFIER)) {
768 TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
769 MOID (p) = *m;
770 TAX (p) = entry;
771 HEAP (entry) = *q;
772 if (*q == LOC_SYMBOL) {
773 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, SUB (*m), GENERATOR);
774 HEAP (z) = LOC_SYMBOL;
775 USE (z) = A68_TRUE;
776 BODY (entry) = z;
777 } else {
778 BODY (entry) = NO_TAG;
779 }
780 MOID (entry) = *m;
781 tax_variable_dec (NEXT (p), q, m);
782 } else {
783 tax_tags (p);
784 }
785 }
786 }
787
788 //! @brief Enter procedure variable declarations in the symbol table.
789
790 void tax_proc_variable_dec (NODE_T * p, int *q)
791 {
792 if (p != NO_NODE) {
793 if (IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
794 tax_proc_variable_dec (SUB (p), q);
795 tax_proc_variable_dec (NEXT (p), q);
796 } else if (IS (p, QUALIFIER)) {
797 *q = ATTRIBUTE (SUB (p));
798 tax_proc_variable_dec (NEXT (p), q);
799 } else if (is_one_of (p, PROC_SYMBOL, COMMA_SYMBOL, STOP)) {
800 tax_proc_variable_dec (NEXT (p), q);
801 } else if (IS (p, DEFINING_IDENTIFIER)) {
802 TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
803 TAX (p) = entry;
804 HEAP (entry) = *q;
805 MOID (entry) = MOID (p);
806 if (*q == LOC_SYMBOL) {
807 TAG_T *z = add_tag (TABLE (p), ANONYMOUS, p, SUB_MOID (p), GENERATOR);
808 HEAP (z) = LOC_SYMBOL;
809 USE (z) = A68_TRUE;
810 BODY (entry) = z;
811 } else {
812 BODY (entry) = NO_TAG;
813 }
814 tax_proc_variable_dec (NEXT (p), q);
815 } else {
816 tax_tags (p);
817 }
818 }
819 }
820
821 //! @brief Enter procedure declarations in the symbol table.
822
823 void tax_proc_dec (NODE_T * p)
824 {
825 if (p != NO_NODE) {
826 if (IS (p, PROCEDURE_DECLARATION)) {
827 tax_proc_dec (SUB (p));
828 tax_proc_dec (NEXT (p));
829 } else if (is_one_of (p, PROC_SYMBOL, COMMA_SYMBOL, STOP)) {
830 tax_proc_dec (NEXT (p));
831 } else if (IS (p, DEFINING_IDENTIFIER)) {
832 TAG_T *entry = find_tag_local (TABLE (p), IDENTIFIER, NSYMBOL (p));
833 MOID_T *m = MOID (NEXT_NEXT (p));
834 MOID (p) = m;
835 TAX (p) = entry;
836 CODEX (entry) |= PROC_DECLARATION_MASK;
837 HEAP (entry) = LOC_SYMBOL;
838 MOID (entry) = m;
839 tax_proc_dec (NEXT (p));
840 } else {
841 tax_tags (p);
842 }
843 }
844 }
845
846 //! @brief Check validity of operator declaration.
847
848 void check_operator_dec (NODE_T * p, MOID_T * u)
849 {
850 int k = 0;
851 if (u == NO_MOID) {
852 NODE_T *pack = SUB_SUB (NEXT_NEXT (p)); // Where the parameter pack is
853 if (ATTRIBUTE (NEXT_NEXT (p)) != ROUTINE_TEXT) {
854 pack = SUB (pack);
855 }
856 k = 1 + count_operands (pack);
857 } else {
858 k = count_pack_members (PACK (u));
859 }
860 if (k < 1 || k > 2) {
861 diagnostic (A68_SYNTAX_ERROR, p, ERROR_OPERAND_NUMBER);
862 k = 0;
863 }
864 if (k == 1 && strchr (NOMADS, NSYMBOL (p)[0]) != NO_TEXT) {
865 diagnostic (A68_SYNTAX_ERROR, p, ERROR_OPERATOR_INVALID, NOMADS);
866 } else if (k == 2 && !find_tag_global (TABLE (p), PRIO_SYMBOL, NSYMBOL (p))) {
867 diagnostic (A68_SYNTAX_ERROR, p, ERROR_DYADIC_PRIORITY);
868 }
869 }
870
871 //! @brief Enter operator declarations in the symbol table.
872
873 void tax_op_dec (NODE_T * p, MOID_T ** m)
874 {
875 if (p != NO_NODE) {
876 if (IS (p, OPERATOR_DECLARATION)) {
877 tax_op_dec (SUB (p), m);
878 tax_op_dec (NEXT (p), m);
879 } else if (IS (p, OPERATOR_PLAN)) {
880 tax_tags (SUB (p));
881 *m = MOID (p);
882 tax_op_dec (NEXT (p), m);
883 } else if (IS (p, OP_SYMBOL)) {
884 tax_op_dec (NEXT (p), m);
885 } else if (IS (p, COMMA_SYMBOL)) {
886 tax_op_dec (NEXT (p), m);
887 } else if (IS (p, DEFINING_OPERATOR)) {
888 TAG_T *entry = OPERATORS (TABLE (p));
889 check_operator_dec (p, *m);
890 while (entry != NO_TAG && NODE (entry) != p) {
891 FORWARD (entry);
892 }
893 MOID (p) = *m;
894 TAX (p) = entry;
895 HEAP (entry) = LOC_SYMBOL;
896 MOID (entry) = *m;
897 tax_op_dec (NEXT (p), m);
898 } else {
899 tax_tags (p);
900 }
901 }
902 }
903
904 //! @brief Enter brief operator declarations in the symbol table.
905
906 void tax_brief_op_dec (NODE_T * p)
907 {
908 if (p != NO_NODE) {
909 if (IS (p, BRIEF_OPERATOR_DECLARATION)) {
910 tax_brief_op_dec (SUB (p));
911 tax_brief_op_dec (NEXT (p));
912 } else if (is_one_of (p, OP_SYMBOL, COMMA_SYMBOL, STOP)) {
913 tax_brief_op_dec (NEXT (p));
914 } else if (IS (p, DEFINING_OPERATOR)) {
915 TAG_T *entry = OPERATORS (TABLE (p));
916 MOID_T *m = MOID (NEXT_NEXT (p));
917 check_operator_dec (p, NO_MOID);
918 while (entry != NO_TAG && NODE (entry) != p) {
919 FORWARD (entry);
920 }
921 MOID (p) = m;
922 TAX (p) = entry;
923 HEAP (entry) = LOC_SYMBOL;
924 MOID (entry) = m;
925 tax_brief_op_dec (NEXT (p));
926 } else {
927 tax_tags (p);
928 }
929 }
930 }
931
932 //! @brief Enter priority declarations in the symbol table.
933
934 void tax_prio_dec (NODE_T * p)
935 {
936 if (p != NO_NODE) {
937 if (IS (p, PRIORITY_DECLARATION)) {
938 tax_prio_dec (SUB (p));
939 tax_prio_dec (NEXT (p));
940 } else if (is_one_of (p, PRIO_SYMBOL, COMMA_SYMBOL, STOP)) {
941 tax_prio_dec (NEXT (p));
942 } else if (IS (p, DEFINING_OPERATOR)) {
943 TAG_T *entry = PRIO (TABLE (p));
944 while (entry != NO_TAG && NODE (entry) != p) {
945 FORWARD (entry);
946 }
947 MOID (p) = NO_MOID;
948 TAX (p) = entry;
949 HEAP (entry) = LOC_SYMBOL;
950 tax_prio_dec (NEXT (p));
951 } else {
952 tax_tags (p);
953 }
954 }
955 }
956
957 //! @brief Enter TAXes in the symbol table.
958
959 void tax_tags (NODE_T * p)
960 {
961 for (; p != NO_NODE; FORWARD (p)) {
962 int heap = LOC_SYMBOL;
963 MOID_T *m = NO_MOID;
964 if (IS (p, IDENTITY_DECLARATION)) {
965 tax_identity_dec (p, &m);
966 } else if (IS (p, VARIABLE_DECLARATION)) {
967 tax_variable_dec (p, &heap, &m);
968 } else if (IS (p, PROCEDURE_DECLARATION)) {
969 tax_proc_dec (p);
970 } else if (IS (p, PROCEDURE_VARIABLE_DECLARATION)) {
971 tax_proc_variable_dec (p, &heap);
972 } else if (IS (p, OPERATOR_DECLARATION)) {
973 tax_op_dec (p, &m);
974 } else if (IS (p, BRIEF_OPERATOR_DECLARATION)) {
975 tax_brief_op_dec (p);
976 } else if (IS (p, PRIORITY_DECLARATION)) {
977 tax_prio_dec (p);
978 } else {
979 tax_tags (SUB (p));
980 }
981 }
982 }
983
984 //! @brief Reset symbol table nest count.
985
986 void reset_symbol_table_nest_count (NODE_T * p)
987 {
988 for (; p != NO_NODE; FORWARD (p)) {
989 if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
990 NEST (TABLE (SUB (p))) = A68 (symbol_table_count)++;
991 }
992 reset_symbol_table_nest_count (SUB (p));
993 }
994 }
995
996 //! @brief Bind routines in symbol table to the tree.
997
998 void bind_routine_tags_to_tree (NODE_T * p)
999 {
1000 // By inserting coercions etc. some may have shifted.
1001 for (; p != NO_NODE; FORWARD (p)) {
1002 if (IS (p, ROUTINE_TEXT) && TAX (p) != NO_TAG) {
1003 NODE (TAX (p)) = p;
1004 }
1005 bind_routine_tags_to_tree (SUB (p));
1006 }
1007 }
1008
1009 //! @brief Bind formats in symbol table to tree.
1010
1011 void bind_format_tags_to_tree (NODE_T * p)
1012 {
1013 // By inserting coercions etc. some may have shifted.
1014 for (; p != NO_NODE; FORWARD (p)) {
1015 if (IS (p, FORMAT_TEXT) && TAX (p) != NO_TAG) {
1016 NODE (TAX (p)) = p;
1017 } else if (IS (p, FORMAT_DELIMITER_SYMBOL) && NEXT (p) != NO_NODE && TAX (p) != NO_TAG) {
1018 NODE (TAX (p)) = p;
1019 }
1020 bind_format_tags_to_tree (SUB (p));
1021 }
1022 }
1023
1024 //! @brief Fill outer level of symbol table.
1025
1026 void fill_symbol_table_outer (NODE_T * p, TABLE_T * s)
1027 {
1028 for (; p != NO_NODE; FORWARD (p)) {
1029 if (TABLE (p) != NO_TABLE) {
1030 OUTER (TABLE (p)) = s;
1031 }
1032 if (SUB (p) != NO_NODE && IS (p, ROUTINE_TEXT)) {
1033 fill_symbol_table_outer (SUB (p), TABLE (SUB (p)));
1034 } else if (SUB (p) != NO_NODE && IS (p, FORMAT_TEXT)) {
1035 fill_symbol_table_outer (SUB (p), TABLE (SUB (p)));
1036 } else {
1037 fill_symbol_table_outer (SUB (p), s);
1038 }
1039 }
1040 }
1041
1042 //! @brief Flood branch in tree with local symbol table "s".
1043
1044 void flood_with_symbol_table_restricted (NODE_T * p, TABLE_T * s)
1045 {
1046 for (; p != NO_NODE; FORWARD (p)) {
1047 TABLE (p) = s;
1048 if (ATTRIBUTE (p) != ROUTINE_TEXT && ATTRIBUTE (p) != SPECIFIED_UNIT) {
1049 if (is_new_lexical_level (p)) {
1050 PREVIOUS (TABLE (SUB (p))) = s;
1051 } else {
1052 flood_with_symbol_table_restricted (SUB (p), s);
1053 }
1054 }
1055 }
1056 }
1057
1058 //! @brief Final structure of symbol table after parsing.
1059
1060 void finalise_symbol_table_setup (NODE_T * p, int l)
1061 {
1062 TABLE_T *s = TABLE (p);
1063 NODE_T *q = p;
1064 while (q != NO_NODE) {
1065 // routine texts are ranges.
1066 if (IS (q, ROUTINE_TEXT)) {
1067 flood_with_symbol_table_restricted (SUB (q), new_symbol_table (s));
1068 }
1069 // specifiers are ranges.
1070 else if (IS (q, SPECIFIED_UNIT)) {
1071 flood_with_symbol_table_restricted (SUB (q), new_symbol_table (s));
1072 }
1073 // level count and recursion.
1074 if (SUB (q) != NO_NODE) {
1075 if (is_new_lexical_level (q)) {
1076 LEX_LEVEL (SUB (q)) = l + 1;
1077 PREVIOUS (TABLE (SUB (q))) = s;
1078 finalise_symbol_table_setup (SUB (q), l + 1);
1079 if (IS (q, WHILE_PART)) {
1080 // This was a bug that went unnoticed for 15 years!.
1081 TABLE_T *s2 = TABLE (SUB (q));
1082 if ((FORWARD (q)) == NO_NODE) {
1083 return;
1084 }
1085 if (IS (q, ALT_DO_PART)) {
1086 PREVIOUS (TABLE (SUB (q))) = s2;
1087 LEX_LEVEL (SUB (q)) = l + 2;
1088 finalise_symbol_table_setup (SUB (q), l + 2);
1089 }
1090 }
1091 } else {
1092 TABLE (SUB (q)) = s;
1093 finalise_symbol_table_setup (SUB (q), l);
1094 }
1095 }
1096 TABLE (q) = s;
1097 if (IS (q, FOR_SYMBOL)) {
1098 FORWARD (q);
1099 }
1100 FORWARD (q);
1101 }
1102 // FOR identifiers are in the DO ... OD range.
1103 for (q = p; q != NO_NODE; FORWARD (q)) {
1104 if (IS (q, FOR_SYMBOL)) {
1105 TABLE (NEXT (q)) = TABLE (SEQUENCE (NEXT (q)));
1106 }
1107 }
1108 }
1109
1110 //! @brief First structure of symbol table for parsing.
1111
1112 void preliminary_symbol_table_setup (NODE_T * p)
1113 {
1114 TABLE_T *s = TABLE (p);
1115 BOOL_T not_a_for_range = A68_FALSE;
1116 // let the tree point to the current symbol table.
1117 for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1118 TABLE (q) = s;
1119 }
1120 // insert new tables when required.
1121 for (NODE_T *q = p; q != NO_NODE && !not_a_for_range; FORWARD (q)) {
1122 if (SUB (q) != NO_NODE) {
1123 // BEGIN ... END, CODE ... EDOC, DEF ... FED, DO ... OD, $ ... $, { ... } are ranges.
1124 if (is_one_of (q, BEGIN_SYMBOL, DO_SYMBOL, ALT_DO_SYMBOL, FORMAT_DELIMITER_SYMBOL, ACCO_SYMBOL, STOP)) {
1125 TABLE (SUB (q)) = new_symbol_table (s);
1126 preliminary_symbol_table_setup (SUB (q));
1127 }
1128 // ( ... ) is a range.
1129 else if (IS (q, OPEN_SYMBOL)) {
1130 if (whether (q, OPEN_SYMBOL, THEN_BAR_SYMBOL, STOP)) {
1131 TABLE (SUB (q)) = s;
1132 preliminary_symbol_table_setup (SUB (q));
1133 FORWARD (q);
1134 TABLE (SUB (q)) = new_symbol_table (s);
1135 preliminary_symbol_table_setup (SUB (q));
1136 if ((FORWARD (q)) == NO_NODE) {
1137 not_a_for_range = A68_TRUE;
1138 } else {
1139 if (IS (q, THEN_BAR_SYMBOL)) {
1140 TABLE (SUB (q)) = new_symbol_table (s);
1141 preliminary_symbol_table_setup (SUB (q));
1142 }
1143 if (IS (q, OPEN_SYMBOL)) {
1144 TABLE (SUB (q)) = new_symbol_table (s);
1145 preliminary_symbol_table_setup (SUB (q));
1146 }
1147 }
1148 } else {
1149 // don't worry about STRUCT (...), UNION (...), PROC (...) yet.
1150 TABLE (SUB (q)) = new_symbol_table (s);
1151 preliminary_symbol_table_setup (SUB (q));
1152 }
1153 }
1154 // IF ... THEN ... ELSE ... FI are ranges.
1155 else if (IS (q, IF_SYMBOL)) {
1156 if (whether (q, IF_SYMBOL, THEN_SYMBOL, STOP)) {
1157 TABLE (SUB (q)) = s;
1158 preliminary_symbol_table_setup (SUB (q));
1159 FORWARD (q);
1160 TABLE (SUB (q)) = new_symbol_table (s);
1161 preliminary_symbol_table_setup (SUB (q));
1162 if ((FORWARD (q)) == NO_NODE) {
1163 not_a_for_range = A68_TRUE;
1164 } else {
1165 if (IS (q, ELSE_SYMBOL)) {
1166 TABLE (SUB (q)) = new_symbol_table (s);
1167 preliminary_symbol_table_setup (SUB (q));
1168 }
1169 if (IS (q, IF_SYMBOL)) {
1170 TABLE (SUB (q)) = new_symbol_table (s);
1171 preliminary_symbol_table_setup (SUB (q));
1172 }
1173 }
1174 } else {
1175 TABLE (SUB (q)) = new_symbol_table (s);
1176 preliminary_symbol_table_setup (SUB (q));
1177 }
1178 }
1179 // CASE ... IN ... OUT ... ESAC are ranges.
1180 else if (IS (q, CASE_SYMBOL)) {
1181 if (whether (q, CASE_SYMBOL, IN_SYMBOL, STOP)) {
1182 TABLE (SUB (q)) = s;
1183 preliminary_symbol_table_setup (SUB (q));
1184 FORWARD (q);
1185 TABLE (SUB (q)) = new_symbol_table (s);
1186 preliminary_symbol_table_setup (SUB (q));
1187 if ((FORWARD (q)) == NO_NODE) {
1188 not_a_for_range = A68_TRUE;
1189 } else {
1190 if (IS (q, OUT_SYMBOL)) {
1191 TABLE (SUB (q)) = new_symbol_table (s);
1192 preliminary_symbol_table_setup (SUB (q));
1193 }
1194 if (IS (q, CASE_SYMBOL)) {
1195 TABLE (SUB (q)) = new_symbol_table (s);
1196 preliminary_symbol_table_setup (SUB (q));
1197 }
1198 }
1199 } else {
1200 TABLE (SUB (q)) = new_symbol_table (s);
1201 preliminary_symbol_table_setup (SUB (q));
1202 }
1203 }
1204 // UNTIL ... OD is a range.
1205 else if (IS (q, UNTIL_SYMBOL) && SUB (q) != NO_NODE) {
1206 TABLE (SUB (q)) = new_symbol_table (s);
1207 preliminary_symbol_table_setup (SUB (q));
1208 // WHILE ... DO ... OD are ranges.
1209 } else if (IS (q, WHILE_SYMBOL)) {
1210 TABLE_T *u = new_symbol_table (s);
1211 TABLE (SUB (q)) = u;
1212 preliminary_symbol_table_setup (SUB (q));
1213 if ((FORWARD (q)) == NO_NODE) {
1214 not_a_for_range = A68_TRUE;
1215 } else if (IS (q, ALT_DO_SYMBOL)) {
1216 TABLE (SUB (q)) = new_symbol_table (u);
1217 preliminary_symbol_table_setup (SUB (q));
1218 }
1219 } else {
1220 TABLE (SUB (q)) = s;
1221 preliminary_symbol_table_setup (SUB (q));
1222 }
1223 }
1224 }
1225 // FOR identifiers will go to the DO ... OD range.
1226 if (!not_a_for_range) {
1227 for (NODE_T *q = p; q != NO_NODE; FORWARD (q)) {
1228 if (IS (q, FOR_SYMBOL)) {
1229 NODE_T *r = q;
1230 TABLE (NEXT (q)) = NO_TABLE;
1231 for (; r != NO_NODE && TABLE (NEXT (q)) == NO_TABLE; FORWARD (r)) {
1232 if ((is_one_of (r, WHILE_SYMBOL, ALT_DO_SYMBOL, STOP)) && (NEXT (q) != NO_NODE && SUB (r) != NO_NODE)) {
1233 TABLE (NEXT (q)) = TABLE (SUB (r));
1234 SEQUENCE (NEXT (q)) = SUB (r);
1235 }
1236 }
1237 }
1238 }
1239 }
1240 }
1241
1242 //! @brief Mark a mode as in use.
1243
1244 void mark_mode (MOID_T * m)
1245 {
1246 if (m != NO_MOID && USE (m) == A68_FALSE) {
1247 PACK_T *p = PACK (m);
1248 USE (m) = A68_TRUE;
1249 for (; p != NO_PACK; FORWARD (p)) {
1250 mark_mode (MOID (p));
1251 mark_mode (SUB (m));
1252 mark_mode (SLICE (m));
1253 }
1254 }
1255 }
1256
1257 //! @brief Traverse tree and mark modes as used.
1258
1259 void mark_moids (NODE_T * p)
1260 {
1261 for (; p != NO_NODE; FORWARD (p)) {
1262 mark_moids (SUB (p));
1263 if (MOID (p) != NO_MOID) {
1264 mark_mode (MOID (p));
1265 }
1266 }
1267 }
1268
1269 //! @brief Mark various tags as used.
1270
1271 void mark_auxilliary (NODE_T * p)
1272 {
1273 for (; p != NO_NODE; FORWARD (p)) {
1274 if (SUB (p) != NO_NODE) {
1275 // You get no warnings on unused PROC parameters. That is ok since A68 has some
1276 // parameters that you may not use at all - think of PROC (REF FILE) BOOL event
1277 // routines in transput.
1278 mark_auxilliary (SUB (p));
1279 } else if (IS (p, OPERATOR)) {
1280 TAG_T *z;
1281 if (TAX (p) != NO_TAG) {
1282 USE (TAX (p)) = A68_TRUE;
1283 }
1284 if ((z = find_tag_global (TABLE (p), PRIO_SYMBOL, NSYMBOL (p))) != NO_TAG) {
1285 USE (z) = A68_TRUE;
1286 }
1287 } else if (IS (p, INDICANT)) {
1288 TAG_T *z = find_tag_global (TABLE (p), INDICANT, NSYMBOL (p));
1289 if (z != NO_TAG) {
1290 TAX (p) = z;
1291 USE (z) = A68_TRUE;
1292 }
1293 } else if (IS (p, IDENTIFIER)) {
1294 if (TAX (p) != NO_TAG) {
1295 USE (TAX (p)) = A68_TRUE;
1296 }
1297 }
1298 }
1299 }
1300
1301 //! @brief Check a single tag.
1302
1303 void unused (TAG_T * s)
1304 {
1305 for (; s != NO_TAG; FORWARD (s)) {
1306 if (LINE_NUMBER (NODE (s)) > 0 && !USE (s)) {
1307 diagnostic (A68_WARNING, NODE (s), WARNING_TAG_UNUSED, NODE (s));
1308 }
1309 }
1310 }
1311
1312 //! @brief Driver for traversing tree and warn for unused tags.
1313
1314 void warn_for_unused_tags (NODE_T * p)
1315 {
1316 for (; p != NO_NODE; FORWARD (p)) {
1317 if (SUB (p) != NO_NODE) {
1318 if (is_new_lexical_level (p) && ATTRIBUTE (TABLE (SUB (p))) != ENVIRON_SYMBOL) {
1319 unused (OPERATORS (TABLE (SUB (p))));
1320 unused (PRIO (TABLE (SUB (p))));
1321 unused (IDENTIFIERS (TABLE (SUB (p))));
1322 unused (LABELS (TABLE (SUB (p))));
1323 unused (INDICANTS (TABLE (SUB (p))));
1324 }
1325 }
1326 warn_for_unused_tags (SUB (p));
1327 }
1328 }
1329
1330 //! @brief Mark jumps and procedured jumps.
1331
1332 void jumps_from_procs (NODE_T * p)
1333 {
1334 for (; p != NO_NODE; FORWARD (p)) {
1335 if (IS (p, PROCEDURING)) {
1336 NODE_T *u = SUB_SUB (p);
1337 if (IS (u, GOTO_SYMBOL)) {
1338 FORWARD (u);
1339 }
1340 USE (TAX (u)) = A68_TRUE;
1341 } else if (IS (p, JUMP)) {
1342 NODE_T *u = SUB (p);
1343 if (IS (u, GOTO_SYMBOL)) {
1344 FORWARD (u);
1345 }
1346 if ((TAX (u) == NO_TAG) && (MOID (u) == NO_MOID) && (find_tag_global (TABLE (u), LABEL, NSYMBOL (u)) == NO_TAG)) {
1347 (void) add_tag (TABLE (u), LABEL, u, NO_MOID, LOCAL_LABEL);
1348 diagnostic (A68_ERROR, u, ERROR_UNDECLARED_TAG);
1349 } else {
1350 USE (TAX (u)) = A68_TRUE;
1351 }
1352 } else {
1353 jumps_from_procs (SUB (p));
1354 }
1355 }
1356 }
1357
1358 //! @brief Assign offset tags.
1359
1360 ADDR_T assign_offset_tags (TAG_T * t, ADDR_T base)
1361 {
1362 ADDR_T sum = base;
1363 for (; t != NO_TAG; FORWARD (t)) {
1364 ABEND (MOID (t) == NO_MOID, ERROR_INTERNAL_CONSISTENCY, NSYMBOL (NODE (t)));
1365 SIZE (t) = moid_size (MOID (t));
1366 if (VALUE (t) == NO_TEXT) {
1367 OFFSET (t) = sum;
1368 sum += SIZE (t);
1369 }
1370 }
1371 return sum;
1372 }
1373
1374 //! @brief Assign offsets table.
1375
1376 void assign_offsets_table (TABLE_T * c)
1377 {
1378 AP_INCREMENT (c) = assign_offset_tags (IDENTIFIERS (c), 0);
1379 AP_INCREMENT (c) = assign_offset_tags (OPERATORS (c), AP_INCREMENT (c));
1380 AP_INCREMENT (c) = assign_offset_tags (ANONYMOUS (c), AP_INCREMENT (c));
1381 AP_INCREMENT (c) = A68_ALIGN (AP_INCREMENT (c));
1382 }
1383
1384 //! @brief Assign offsets.
1385
1386 void assign_offsets (NODE_T * p)
1387 {
1388 for (; p != NO_NODE; FORWARD (p)) {
1389 if (SUB (p) != NO_NODE && is_new_lexical_level (p)) {
1390 assign_offsets_table (TABLE (SUB (p)));
1391 }
1392 assign_offsets (SUB (p));
1393 }
1394 }
1395
1396 //! @brief Assign offsets packs in moid list.
1397
1398 void assign_offsets_packs (MOID_T * q)
1399 {
1400 for (; q != NO_MOID; FORWARD (q)) {
1401 if (EQUIVALENT (q) == NO_MOID && IS (q, STRUCT_SYMBOL)) {
1402 PACK_T *p = PACK (q);
1403 ADDR_T offset = 0;
1404 for (; p != NO_PACK; FORWARD (p)) {
1405 SIZE (p) = moid_size (MOID (p));
1406 OFFSET (p) = offset;
1407 offset += SIZE (p);
1408 }
1409 }
1410 }
1411 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|