genie.c
1 //! @file genie.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-2025 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 //! Interpreter driver.
25
26 // This file contains interpreter ("genie") routines related to executing primitive
27 // A68 actions.
28 //
29 // The genie is self-optimising as when it traverses the tree, it stores terminals
30 // it ends up in at the root where traversing for that terminal started.
31 // Such piece of information is called a PROP.
32
33 #include "a68g.h"
34 #include "a68g-genie.h"
35 #include "a68g-frames.h"
36 #include "a68g-prelude.h"
37 #include "a68g-mp.h"
38 #include "a68g-parser.h"
39 #include "a68g-transput.h"
40
41 //! @brief Set flags throughout tree.
42
43 void change_masks (NODE_T * p, unt mask, BOOL_T set)
44 {
45 for (; p != NO_NODE; FORWARD (p)) {
46 change_masks (SUB (p), mask, set);
47 if (LINE_NUMBER (p) > 0) {
48 if (set == A68G_TRUE) {
49 STATUS_SET (p, mask);
50 } else {
51 STATUS_CLEAR (p, mask);
52 }
53 }
54 }
55 }
56
57 //! @brief Set flags throughout tree.
58
59 void change_gc_masks (NODE_T * p, BOOL_T set)
60 {
61 for (; p != NO_NODE; FORWARD (p)) {
62 switch (ATTRIBUTE (p)) {
63 case CALL: {
64 change_gc_masks (SUB (p), A68G_TRUE);
65 break;
66 }
67 case SLICE: {
68 change_gc_masks (SUB (p), A68G_TRUE);
69 break;
70 }
71 default: {
72 change_gc_masks (SUB (p), set);
73 break;
74 }
75 }
76 if (LINE_NUMBER (p) > 0) {
77 if (set == A68G_TRUE) {
78 STATUS_SET (p, BLOCK_GC_MASK);
79 } else {
80 STATUS_CLEAR (p, BLOCK_GC_MASK);
81 }
82 }
83 }
84 }
85
86 //! @brief Leave interpretation.
87
88 void exit_genie (NODE_T * p, int ret)
89 {
90 #if defined (HAVE_CURSES)
91 genie_curses_end (p);
92 #endif
93 A68G (close_tty_on_exit) = A68G_TRUE;
94 if (!A68G (in_execution)) {
95 return;
96 }
97 if (ret == A68G_RUNTIME_ERROR && A68G (in_monitor)) {
98 return;
99 } else if (ret == A68G_RUNTIME_ERROR && OPTION_DEBUG (&A68G_JOB)) {
100 diagnostics_to_terminal (TOP_LINE (&A68G_JOB), A68G_RUNTIME_ERROR);
101 single_step (p, (unt) BREAKPOINT_ERROR_MASK);
102 A68G (in_execution) = A68G_FALSE;
103 A68G (ret_line_number) = LINE_NUMBER (p);
104 A68G (ret_code) = ret;
105 longjmp (A68G (genie_exit_label), 1);
106 } else {
107 if ((ret & A68G_FORCE_QUIT) != NULL_MASK) {
108 ret &= ~A68G_FORCE_QUIT;
109 }
110 #if defined (BUILD_PARALLEL_CLAUSE)
111 if (!is_main_thread ()) {
112 genie_set_exit_from_threads (ret);
113 } else {
114 A68G (in_execution) = A68G_FALSE;
115 A68G (ret_line_number) = LINE_NUMBER (p);
116 A68G (ret_code) = ret;
117 longjmp (A68G (genie_exit_label), 1);
118 }
119 #else
120 A68G (in_execution) = A68G_FALSE;
121 A68G (ret_line_number) = LINE_NUMBER (p);
122 A68G (ret_code) = ret;
123 longjmp (A68G (genie_exit_label), 1);
124 #endif
125 }
126 }
127
128 //! @brief Genie init rng.
129
130 void genie_init_rng (void)
131 {
132 time_t t;
133 if (time (&t) != -1) {
134 init_rng ((unt) t);
135 }
136 }
137
138 //! @brief Tie label to the clause it is defined in.
139
140 void tie_label_to_serial (NODE_T * p)
141 {
142 for (; p != NO_NODE; FORWARD (p)) {
143 if (IS (p, SERIAL_CLAUSE)) {
144 BOOL_T valid_follow;
145 if (NEXT (p) == NO_NODE) {
146 valid_follow = A68G_TRUE;
147 } else if (IS (NEXT (p), CLOSE_SYMBOL)) {
148 valid_follow = A68G_TRUE;
149 } else if (IS (NEXT (p), END_SYMBOL)) {
150 valid_follow = A68G_TRUE;
151 } else if (IS (NEXT (p), EDOC_SYMBOL)) {
152 valid_follow = A68G_TRUE;
153 } else if (IS (NEXT (p), OD_SYMBOL)) {
154 valid_follow = A68G_TRUE;
155 } else {
156 valid_follow = A68G_FALSE;
157 }
158 if (valid_follow) {
159 JUMP_TO (TABLE (SUB (p))) = NO_NODE;
160 }
161 }
162 tie_label_to_serial (SUB (p));
163 }
164 }
165
166 //! @brief Tie label to the clause it is defined in.
167
168 void tie_label (NODE_T * p, NODE_T * unit)
169 {
170 for (; p != NO_NODE; FORWARD (p)) {
171 if (IS (p, DEFINING_IDENTIFIER)) {
172 UNIT (TAX (p)) = unit;
173 }
174 tie_label (SUB (p), unit);
175 }
176 }
177
178 //! @brief Tie label to the clause it is defined in.
179
180 void tie_label_to_unit (NODE_T * p)
181 {
182 for (; p != NO_NODE; FORWARD (p)) {
183 if (IS (p, LABELED_UNIT)) {
184 tie_label (SUB_SUB (p), NEXT_SUB (p));
185 }
186 tie_label_to_unit (SUB (p));
187 }
188 }
189
190 //! @brief Fast way to indicate a mode.
191
192 int mode_attribute (MOID_T * p)
193 {
194 if (IS_REF (p)) {
195 return REF_SYMBOL;
196 } else if (IS (p, PROC_SYMBOL)) {
197 return PROC_SYMBOL;
198 } else if (IS_UNION (p)) {
199 return UNION_SYMBOL;
200 } else if (p == M_INT) {
201 return MODE_INT;
202 } else if (p == M_LONG_INT) {
203 return MODE_LONG_INT;
204 } else if (p == M_LONG_LONG_INT) {
205 return MODE_LONG_LONG_INT;
206 } else if (p == M_REAL) {
207 return MODE_REAL;
208 } else if (p == M_LONG_REAL) {
209 return MODE_LONG_REAL;
210 } else if (p == M_LONG_LONG_REAL) {
211 return MODE_LONG_LONG_REAL;
212 } else if (p == M_COMPLEX) {
213 return MODE_COMPLEX;
214 } else if (p == M_LONG_COMPLEX) {
215 return MODE_LONG_COMPLEX;
216 } else if (p == M_LONG_LONG_COMPLEX) {
217 return MODE_LONG_LONG_COMPLEX;
218 } else if (p == M_BOOL) {
219 return MODE_BOOL;
220 } else if (p == M_CHAR) {
221 return MODE_CHAR;
222 } else if (p == M_BITS) {
223 return MODE_BITS;
224 } else if (p == M_LONG_BITS) {
225 return MODE_LONG_BITS;
226 } else if (p == M_LONG_LONG_BITS) {
227 return MODE_LONG_LONG_BITS;
228 } else if (p == M_BYTES) {
229 return MODE_BYTES;
230 } else if (p == M_LONG_BYTES) {
231 return MODE_LONG_BYTES;
232 } else if (p == M_FILE) {
233 return MODE_FILE;
234 } else if (p == M_FORMAT) {
235 return MODE_FORMAT;
236 } else if (p == M_PIPE) {
237 return MODE_PIPE;
238 } else if (p == M_SOUND) {
239 return MODE_SOUND;
240 } else {
241 return MODE_NO_CHECK;
242 }
243 }
244
245 //! @brief Perform tasks before interpretation.
246
247 void genie_preprocess (NODE_T * p, int *max_lev, void *compile_plugin)
248 {
249 #if defined (BUILD_A68G_COMPILER)
250 static char *last_compile_name = NO_TEXT;
251 static PROP_PROC *last_compile_unit = NO_PPROC;
252 #endif
253 for (; p != NO_NODE; FORWARD (p)) {
254 if (STATUS_TEST (p, BREAKPOINT_MASK)) {
255 if (!(STATUS_TEST (p, INTERRUPTIBLE_MASK))) {
256 STATUS_CLEAR (p, BREAKPOINT_MASK);
257 }
258 }
259 if (GINFO (p) != NO_GINFO) {
260 IS_COERCION (GINFO (p)) = is_coercion (p);
261 IS_NEW_LEXICAL_LEVEL (GINFO (p)) = is_new_lexical_level (p);
262 // The default.
263 UNIT (&GPROP (p)) = genie_unit;
264 SOURCE (&GPROP (p)) = p;
265 #if defined (BUILD_A68G_COMPILER)
266 if (OPTION_OPT_LEVEL (&A68G_JOB) > 0 && COMPILE_NAME (GINFO (p)) != NO_TEXT && compile_plugin != NULL) {
267 if (COMPILE_NAME (GINFO (p)) == last_compile_name) {
268 // We copy.
269 UNIT (&GPROP (p)) = last_compile_unit;
270 } else {
271 // We look up.
272 // Next line may provoke a warning even with this POSIX workaround. Tant pis.
273 *(void **) &(UNIT (&GPROP (p))) = dlsym (compile_plugin, COMPILE_NAME (GINFO (p)));
274 ABEND (UNIT (&GPROP (p)) == NULL, ERROR_INTERNAL_CONSISTENCY, dlerror ());
275 last_compile_name = COMPILE_NAME (GINFO (p));
276 last_compile_unit = UNIT (&GPROP (p));
277 }
278 }
279 #endif
280 }
281 if (MOID (p) != NO_MOID) {
282 SIZE (MOID (p)) = moid_size (MOID (p));
283 DIGITS (MOID (p)) = moid_digits (MOID (p));
284 SHORT_ID (MOID (p)) = mode_attribute (MOID (p));
285 if (GINFO (p) != NO_GINFO) {
286 NEED_DNS (GINFO (p)) = A68G_FALSE;
287 if (IS_REF (MOID (p))) {
288 NEED_DNS (GINFO (p)) = A68G_TRUE;
289 } else if (IS (MOID (p), PROC_SYMBOL)) {
290 NEED_DNS (GINFO (p)) = A68G_TRUE;
291 } else if (IS (MOID (p), FORMAT_SYMBOL)) {
292 NEED_DNS (GINFO (p)) = A68G_TRUE;
293 }
294 }
295 }
296 if (TABLE (p) != NO_TABLE) {
297 if (LEX_LEVEL (p) > *max_lev) {
298 *max_lev = LEX_LEVEL (p);
299 }
300 }
301 if (IS (p, FORMAT_TEXT)) {
302 TAG_T *q = TAX (p);
303 if (q != NO_TAG && NODE (q) != NO_NODE) {
304 NODE (q) = p;
305 }
306 } else if (IS (p, DEFINING_IDENTIFIER)) {
307 TAG_T *q = TAX (p);
308 if (q != NO_TAG && NODE (q) != NO_NODE && TABLE (NODE (q)) != NO_TABLE) {
309 LEVEL (GINFO (p)) = LEX_LEVEL (NODE (q));
310 }
311 } else if (IS (p, IDENTIFIER)) {
312 TAG_T *q = TAX (p);
313 if (q != NO_TAG && NODE (q) != NO_NODE && TABLE (NODE (q)) != NO_TABLE) {
314 LEVEL (GINFO (p)) = LEX_LEVEL (NODE (q));
315 OFFSET (GINFO (p)) = &(A68G_STACK[FRAME_INFO_SIZE + OFFSET (q)]);
316 }
317 } else if (IS (p, OPERATOR)) {
318 TAG_T *q = TAX (p);
319 if (q != NO_TAG && NODE (q) != NO_NODE && TABLE (NODE (q)) != NO_TABLE) {
320 LEVEL (GINFO (p)) = LEX_LEVEL (NODE (q));
321 OFFSET (GINFO (p)) = &(A68G_STACK[FRAME_INFO_SIZE + OFFSET (q)]);
322 }
323 }
324 if (SUB (p) != NO_NODE) {
325 if (GINFO (p) != NO_GINFO) {
326 GPARENT (SUB (p)) = p;
327 }
328 genie_preprocess (SUB (p), max_lev, compile_plugin);
329 }
330 }
331 }
332
333 //! @brief Get outermost lexical level in the user program.
334
335 void get_global_level (NODE_T * p)
336 {
337 for (; p != NO_NODE; FORWARD (p)) {
338 if (LINE_NUMBER (p) != 0 && IS (p, UNIT)) {
339 if (LEX_LEVEL (p) < A68G (global_level)) {
340 A68G (global_level) = LEX_LEVEL (p);
341 }
342 }
343 get_global_level (SUB (p));
344 }
345 }
346
347 //! @brief Driver for the interpreter.
348
349 void genie (void *compile_plugin)
350 {
351 // Fill in final info for modes.
352 for (MOID_T *m = TOP_MOID (&A68G_JOB); m != NO_MOID; FORWARD (m)) {
353 SIZE (m) = moid_size (m);
354 DIGITS (m) = moid_digits (m);
355 SHORT_ID (m) = mode_attribute (m);
356 }
357 // Preprocessing.
358 A68G (max_lex_lvl) = 0;
359 // genie_lex_levels (TOP_NODE (&A68G_JOB), 1);.
360 genie_preprocess (TOP_NODE (&A68G_JOB), &A68G (max_lex_lvl), compile_plugin);
361 change_masks (TOP_NODE (&A68G_JOB), BREAKPOINT_INTERRUPT_MASK, A68G_FALSE);
362 change_gc_masks (TOP_NODE (&A68G_JOB), A68G_FALSE);
363 A68G_MON (watchpoint_expression) = NO_TEXT;
364 A68G (frame_stack_limit) = A68G (frame_end) - A68G (storage_overhead);
365 A68G (expr_stack_limit) = A68G (stack_end) - A68G (storage_overhead);
366 if (OPTION_REGRESSION_TEST (&A68G_JOB)) {
367 init_rng (1);
368 } else {
369 genie_init_rng ();
370 }
371 io_close_tty_line ();
372 if (OPTION_TRACE (&A68G_JOB)) {
373 ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "genie: frame stack %uk, expression stack %uk, heap %uk, handles %uk\n", A68G (frame_stack_size) / KILOBYTE, A68G (expr_stack_size) / KILOBYTE, A68G (heap_size) / KILOBYTE, A68G (handle_pool_size) / KILOBYTE) >= 0);
374 WRITE (A68G_STDOUT, A68G (output_line));
375 }
376 install_signal_handlers ();
377 set_default_event_procedure (&A68G (on_gc_event));
378 A68G (do_confirm_exit) = A68G_TRUE;
379 #if defined (BUILD_PARALLEL_CLAUSE)
380 ASSERT (pthread_mutex_init (&A68G_PAR (unit_sema), NULL) == 0);
381 #endif
382 // Dive into the program.
383 if (setjmp (A68G (genie_exit_label)) == 0) {
384 NODE_T *p = SUB (TOP_NODE (&A68G_JOB));
385 // If we are to stop in the monitor, set a breakpoint on the first unit.
386 if (OPTION_DEBUG (&A68G_JOB)) {
387 change_masks (TOP_NODE (&A68G_JOB), BREAKPOINT_TEMPORARY_MASK, A68G_TRUE);
388 WRITE (A68G_STDOUT, "Execution begins ...");
389 }
390 errno = 0;
391 A68G (ret_code) = 0;
392 A68G (global_level) = INT_MAX;
393 A68G_GLOBALS = 0;
394 get_global_level (p);
395 A68G_FP = A68G (frame_start);
396 A68G_SP = A68G (stack_start);
397 FRAME_DYNAMIC_LINK (A68G_FP) = 0;
398 FRAME_DNS (A68G_FP) = 0;
399 FRAME_STATIC_LINK (A68G_FP) = 0;
400 FRAME_NUMBER (A68G_FP) = 0;
401 FRAME_TREE (A68G_FP) = (NODE_T *) p;
402 FRAME_LEXICAL_LEVEL (A68G_FP) = LEX_LEVEL (p);
403 FRAME_PARAMETER_LEVEL (A68G_FP) = LEX_LEVEL (p);
404 FRAME_PARAMETERS (A68G_FP) = A68G_FP;
405 initialise_frame (p);
406 genie_init_heap (p);
407 genie_init_transput (TOP_NODE (&A68G_JOB));
408 A68G (cputime_0) = seconds ();
409 A68G (walltime_0) = wall_seconds ();
410 A68G_GC (sema) = 0;
411 // Here we go ...
412 A68G (in_execution) = A68G_TRUE;
413 A68G (f_entry) = TOP_NODE (&A68G_JOB);
414 #if defined (BUILD_UNIX)
415 (void) a68g_alarm (INTERRUPT_INTERVAL);
416 #endif
417 if (OPTION_TRACE (&A68G_JOB)) {
418 WIS (TOP_NODE (&A68G_JOB));
419 }
420 (void) genie_enclosed (TOP_NODE (&A68G_JOB));
421 } else {
422 // Here we have jumped out of the interpreter. What happened?.
423 if (OPTION_DEBUG (&A68G_JOB)) {
424 WRITE (A68G_STDOUT, "Execution discontinued");
425 }
426 if (A68G (ret_code) == A68G_RERUN) {
427 diagnostics_to_terminal (TOP_LINE (&A68G_JOB), A68G_RUNTIME_ERROR);
428 genie (compile_plugin);
429 } else if (A68G (ret_code) == A68G_RUNTIME_ERROR) {
430 if (OPTION_BACKTRACE (&A68G_JOB)) {
431 int printed = 0;
432 ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "\nStack backtrace") >= 0);
433 WRITE (A68G_STDOUT, A68G (output_line));
434 stack_dump (A68G_STDOUT, A68G_FP, 16, &printed);
435 WRITE (A68G_STDOUT, NEWLINE_STRING);
436 }
437 if (FILE_LISTING_OPENED (&A68G_JOB)) {
438 int printed = 0;
439 ASSERT (a68g_bufprt (A68G (output_line), SNPRINTF_SIZE, "\nStack backtrace") >= 0);
440 WRITE (FILE_LISTING_FD (&A68G_JOB), A68G (output_line));
441 stack_dump (FILE_LISTING_FD (&A68G_JOB), A68G_FP, 32, &printed);
442 }
443 }
444 }
445 A68G (in_execution) = A68G_FALSE;
446 }
447
448 //! @brief Shows line where 'p' is at and draws a '-' beneath the position.
449
450 void where_in_source (FILE_T f, NODE_T * p)
451 {
452 write_source_line (f, LINE (INFO (p)), p, A68G_NO_DIAGNOSTICS);
453 }
454
455 // Since Algol 68 can pass procedures as parameters, we use static links rather
456 // than a display.
457
458 //! @brief Initialise PROC and OP identities.
459
460 void genie_init_proc_op (NODE_T * p, NODE_T ** seq, int *count)
461 {
462 for (; p != NO_NODE; FORWARD (p)) {
463 switch (ATTRIBUTE (p)) {
464 case OP_SYMBOL:
465 case PROC_SYMBOL:
466 case OPERATOR_PLAN:
467 case DECLARER: {
468 break;
469 }
470 case DEFINING_IDENTIFIER:
471 case DEFINING_OPERATOR: {
472 // Store position so we need not search again.
473 NODE_T *save = *seq;
474 (*seq) = p;
475 SEQUENCE (*seq) = save;
476 (*count)++;
477 return;
478 }
479 default: {
480 genie_init_proc_op (SUB (p), seq, count);
481 break;
482 }
483 }
484 }
485 }
486
487 //! @brief Initialise PROC and OP identity declarations.
488
489 void genie_find_proc_op (NODE_T * p, int *count)
490 {
491 for (; p != NO_NODE; FORWARD (p)) {
492 if (GINFO (p) != NO_GINFO && IS_NEW_LEXICAL_LEVEL (GINFO (p))) {
493 // Don't enter a new lexical level - it will have its own initialisation.
494 return;
495 } else if (IS (p, PROCEDURE_DECLARATION) || IS (p, BRIEF_OPERATOR_DECLARATION)) {
496 genie_init_proc_op (SUB (p), &(SEQUENCE (TABLE (p))), count);
497 return;
498 } else {
499 genie_find_proc_op (SUB (p), count);
500 }
501 }
502 }
503
504 //! @brief Initialise stack frame.
505
506 void initialise_frame (NODE_T * p)
507 {
508 if (INITIALISE_ANON (TABLE (p))) {
509 TAG_T *_a_;
510 INITIALISE_ANON (TABLE (p)) = A68G_FALSE;
511 for (_a_ = ANONYMOUS (TABLE (p)); _a_ != NO_TAG; FORWARD (_a_)) {
512 if (PRIO (_a_) == ROUTINE_TEXT) {
513 int youngest = YOUNGEST_ENVIRON (TAX (NODE (_a_)));
514 A68G_PROCEDURE *_z_ = (A68G_PROCEDURE *) (FRAME_OBJECT (OFFSET (_a_)));
515 STATUS (_z_) = INIT_MASK;
516 NODE (&(BODY (_z_))) = NODE (_a_);
517 if (youngest > 0) {
518 STATIC_LINK_FOR_FRAME (ENVIRON (_z_), 1 + youngest);
519 } else {
520 ENVIRON (_z_) = 0;
521 }
522 LOCALE (_z_) = NO_HANDLE;
523 MOID (_z_) = MOID (_a_);
524 INITIALISE_ANON (TABLE (p)) = A68G_TRUE;
525 } else if (PRIO (_a_) == FORMAT_TEXT) {
526 int youngest = YOUNGEST_ENVIRON (TAX (NODE (_a_)));
527 A68G_FORMAT *_z_ = (A68G_FORMAT *) (FRAME_OBJECT (OFFSET (_a_)));
528 STATUS (_z_) = INIT_MASK;
529 BODY (_z_) = NODE (_a_);
530 if (youngest > 0) {
531 STATIC_LINK_FOR_FRAME (ENVIRON (_z_), 1 + youngest);
532 } else {
533 ENVIRON (_z_) = 0;
534 }
535 INITIALISE_ANON (TABLE (p)) = A68G_TRUE;
536 }
537 }
538 }
539 if (PROC_OPS (TABLE (p))) {
540 NODE_T *_q_;
541 if (SEQUENCE (TABLE (p)) == NO_NODE) {
542 int count = 0;
543 genie_find_proc_op (p, &count);
544 PROC_OPS (TABLE (p)) = (BOOL_T) (count > 0);
545 }
546 for (_q_ = SEQUENCE (TABLE (p)); _q_ != NO_NODE; _q_ = SEQUENCE (_q_)) {
547 NODE_T *u = NEXT_NEXT (_q_);
548 if (IS (u, ROUTINE_TEXT)) {
549 NODE_T *src = SOURCE (&(GPROP (u)));
550 *(A68G_PROCEDURE *) FRAME_OBJECT (OFFSET (TAX (_q_))) = *(A68G_PROCEDURE *) (FRAME_OBJECT (OFFSET (TAX (src))));
551 } else if ((IS (u, UNIT) && IS (SUB (u), ROUTINE_TEXT))) {
552 NODE_T *src = SOURCE (&(GPROP (SUB (u))));
553 *(A68G_PROCEDURE *) FRAME_OBJECT (OFFSET (TAX (_q_))) = *(A68G_PROCEDURE *) (FRAME_OBJECT (OFFSET (TAX (src))));
554 }
555 }
556 }
557 INITIALISE_FRAME (TABLE (p)) = (BOOL_T) (INITIALISE_ANON (TABLE (p)) || PROC_OPS (TABLE (p)));
558 }
559
560 //! @brief Whether item at "w" of mode "q" is initialised.
561
562 void genie_check_initialisation (NODE_T * p, BYTE_T * w, MOID_T * q)
563 {
564 switch (SHORT_ID (q)) {
565 case REF_SYMBOL: {
566 A68G_REF *z = (A68G_REF *) w;
567 CHECK_INIT (p, INITIALISED (z), q);
568 return;
569 }
570 case PROC_SYMBOL: {
571 A68G_PROCEDURE *z = (A68G_PROCEDURE *) w;
572 CHECK_INIT (p, INITIALISED (z), q);
573 return;
574 }
575 case MODE_INT: {
576 A68G_INT *z = (A68G_INT *) w;
577 CHECK_INIT (p, INITIALISED (z), q);
578 return;
579 }
580 case MODE_REAL: {
581 A68G_REAL *z = (A68G_REAL *) w;
582 CHECK_INIT (p, INITIALISED (z), q);
583 return;
584 }
585 case MODE_COMPLEX: {
586 A68G_REAL *r = (A68G_REAL *) w;
587 A68G_REAL *i = (A68G_REAL *) (w + SIZE_ALIGNED (A68G_REAL));
588 CHECK_INIT (p, INITIALISED (r), q);
589 CHECK_INIT (p, INITIALISED (i), q);
590 return;
591 }
592 #if (A68G_LEVEL >= 3)
593 case MODE_LONG_INT:
594 case MODE_LONG_REAL:
595 case MODE_LONG_BITS: {
596 A68G_DOUBLE *z = (A68G_DOUBLE *) w;
597 CHECK_INIT (p, INITIALISED (z), q);
598 return;
599 }
600 case MODE_LONG_COMPLEX: {
601 A68G_LONG_REAL *r = (A68G_LONG_REAL *) w;
602 A68G_LONG_REAL *i = (A68G_LONG_REAL *) (w + SIZE_ALIGNED (A68G_LONG_REAL));
603 CHECK_INIT (p, INITIALISED (r), q);
604 CHECK_INIT (p, INITIALISED (i), q);
605 return;
606 }
607 case MODE_LONG_LONG_INT:
608 case MODE_LONG_LONG_REAL:
609 case MODE_LONG_LONG_BITS: {
610 MP_T *z = (MP_T *) w;
611 CHECK_INIT (p, (unt) MP_STATUS (z) & INIT_MASK, q);
612 return;
613 }
614 #else
615 case MODE_LONG_INT:
616 case MODE_LONG_LONG_INT:
617 case MODE_LONG_REAL:
618 case MODE_LONG_LONG_REAL:
619 case MODE_LONG_BITS:
620 case MODE_LONG_LONG_BITS: {
621 MP_T *z = (MP_T *) w;
622 CHECK_INIT (p, (unt) MP_STATUS (z) & INIT_MASK, q);
623 return;
624 }
625 case MODE_LONG_COMPLEX: {
626 MP_T *r = (MP_T *) w;
627 MP_T *i = (MP_T *) (w + size_mp ());
628 CHECK_INIT (p, (unt) r[0] & INIT_MASK, q);
629 CHECK_INIT (p, (unt) i[0] & INIT_MASK, q);
630 return;
631 }
632 #endif
633 case MODE_LONG_LONG_COMPLEX: {
634 MP_T *r = (MP_T *) w;
635 MP_T *i = (MP_T *) (w + size_long_mp ());
636 CHECK_INIT (p, (unt) r[0] & INIT_MASK, q);
637 CHECK_INIT (p, (unt) i[0] & INIT_MASK, q);
638 return;
639 }
640 case MODE_BOOL: {
641 A68G_BOOL *z = (A68G_BOOL *) w;
642 CHECK_INIT (p, INITIALISED (z), q);
643 return;
644 }
645 case MODE_CHAR: {
646 A68G_CHAR *z = (A68G_CHAR *) w;
647 CHECK_INIT (p, INITIALISED (z), q);
648 return;
649 }
650 case MODE_BITS: {
651 A68G_BITS *z = (A68G_BITS *) w;
652 CHECK_INIT (p, INITIALISED (z), q);
653 return;
654 }
655 case MODE_BYTES: {
656 A68G_BYTES *z = (A68G_BYTES *) w;
657 CHECK_INIT (p, INITIALISED (z), q);
658 return;
659 }
660 case MODE_LONG_BYTES: {
661 A68G_LONG_BYTES *z = (A68G_LONG_BYTES *) w;
662 CHECK_INIT (p, INITIALISED (z), q);
663 return;
664 }
665 case MODE_FILE: {
666 A68G_FILE *z = (A68G_FILE *) w;
667 CHECK_INIT (p, INITIALISED (z), q);
668 return;
669 }
670 case MODE_FORMAT: {
671 A68G_FORMAT *z = (A68G_FORMAT *) w;
672 CHECK_INIT (p, INITIALISED (z), q);
673 return;
674 }
675 case MODE_PIPE: {
676 A68G_REF *pipe_read = (A68G_REF *) w;
677 A68G_REF *pipe_write = (A68G_REF *) (w + A68G_REF_SIZE);
678 A68G_INT *pid = (A68G_INT *) (w + 2 * A68G_REF_SIZE);
679 CHECK_INIT (p, INITIALISED (pipe_read), q);
680 CHECK_INIT (p, INITIALISED (pipe_write), q);
681 CHECK_INIT (p, INITIALISED (pid), q);
682 return;
683 }
684 case MODE_SOUND: {
685 A68G_SOUND *z = (A68G_SOUND *) w;
686 CHECK_INIT (p, INITIALISED (z), q);
687 return;
688 }
689 }
690 }
691
692 //! @brief Propagator_name.
693
694 char *propagator_name (const PROP_PROC * p)
695 {
696 if (p == genie_and_function) {
697 return "genie_and_function";
698 }
699 if (p == genie_assertion) {
700 return "genie_assertion";
701 }
702 if (p == genie_assignation) {
703 return "genie_assignation";
704 }
705 if (p == genie_assignation_constant) {
706 return "genie_assignation_constant";
707 }
708 if (p == genie_call) {
709 return "genie_call";
710 }
711 if (p == genie_cast) {
712 return "genie_cast";
713 }
714 if (p == (PROP_PROC *) genie_closed) {
715 return "genie_closed";
716 }
717 if (p == genie_coercion) {
718 return "genie_coercion";
719 }
720 if (p == genie_collateral) {
721 return "genie_collateral";
722 }
723 if (p == genie_column_function) {
724 return "genie_column_function";
725 }
726 if (p == (PROP_PROC *) genie_conditional) {
727 return "genie_conditional";
728 }
729 if (p == genie_constant) {
730 return "genie_constant";
731 }
732 if (p == genie_denotation) {
733 return "genie_denotation";
734 }
735 if (p == genie_deproceduring) {
736 return "genie_deproceduring";
737 }
738 if (p == genie_dereference_frame_identifier) {
739 return "genie_dereference_frame_identifier";
740 }
741 if (p == genie_dereference_selection_name_quick) {
742 return "genie_dereference_selection_name_quick";
743 }
744 if (p == genie_dereference_slice_name_quick) {
745 return "genie_dereference_slice_name_quick";
746 }
747 if (p == genie_dereferencing) {
748 return "genie_dereferencing";
749 }
750 if (p == genie_dereferencing_quick) {
751 return "genie_dereferencing_quick";
752 }
753 if (p == genie_diagonal_function) {
754 return "genie_diagonal_function";
755 }
756 if (p == genie_dyadic) {
757 return "genie_dyadic";
758 }
759 if (p == genie_dyadic_quick) {
760 return "genie_dyadic_quick";
761 }
762 if (p == (PROP_PROC *) genie_enclosed) {
763 return "genie_enclosed";
764 }
765 if (p == genie_format_text) {
766 return "genie_format_text";
767 }
768 if (p == genie_formula) {
769 return "genie_formula";
770 }
771 if (p == genie_generator) {
772 return "genie_generator";
773 }
774 if (p == genie_identifier) {
775 return "genie_identifier";
776 }
777 if (p == genie_identifier_standenv) {
778 return "genie_identifier_standenv";
779 }
780 if (p == genie_identifier_standenv_proc) {
781 return "genie_identifier_standenv_proc";
782 }
783 if (p == genie_identity_relation) {
784 return "genie_identity_relation";
785 }
786 if (p == (PROP_PROC *) genie_int_case) {
787 return "genie_int_case";
788 }
789 if (p == genie_field_selection) {
790 return "genie_field_selection";
791 }
792 if (p == genie_frame_identifier) {
793 return "genie_frame_identifier";
794 }
795 if (p == (PROP_PROC *) genie_loop) {
796 return "genie_loop";
797 }
798 if (p == genie_monadic) {
799 return "genie_monadic";
800 }
801 if (p == genie_nihil) {
802 return "genie_nihil";
803 }
804 if (p == genie_or_function) {
805 return "genie_or_function";
806 }
807 #if defined (BUILD_PARALLEL_CLAUSE)
808 if (p == genie_parallel) {
809 return "genie_parallel";
810 }
811 #endif
812 if (p == genie_routine_text) {
813 return "genie_routine_text";
814 }
815 if (p == genie_row_function) {
816 return "genie_row_function";
817 }
818 if (p == genie_rowing) {
819 return "genie_rowing";
820 }
821 if (p == genie_rowing_ref_row_of_row) {
822 return "genie_rowing_ref_row_of_row";
823 }
824 if (p == genie_rowing_ref_row_row) {
825 return "genie_rowing_ref_row_row";
826 }
827 if (p == genie_rowing_row_of_row) {
828 return "genie_rowing_row_of_row";
829 }
830 if (p == genie_rowing_row_row) {
831 return "genie_rowing_row_row";
832 }
833 if (p == genie_selection) {
834 return "genie_selection";
835 }
836 if (p == genie_selection_name_quick) {
837 return "genie_selection_name_quick";
838 }
839 if (p == genie_selection_value_quick) {
840 return "genie_selection_value_quick";
841 }
842 if (p == genie_skip) {
843 return "genie_skip";
844 }
845 if (p == genie_slice) {
846 return "genie_slice";
847 }
848 if (p == genie_slice_name_quick) {
849 return "genie_slice_name_quick";
850 }
851 if (p == genie_transpose_function) {
852 return "genie_transpose_function";
853 }
854 if (p == genie_unit) {
855 return "genie_unit";
856 }
857 if (p == (PROP_PROC *) genie_united_case) {
858 return "genie_united_case";
859 }
860 if (p == genie_uniting) {
861 return "genie_uniting";
862 }
863 if (p == genie_voiding) {
864 return "genie_voiding";
865 }
866 if (p == genie_voiding_assignation) {
867 return "genie_voiding_assignation";
868 }
869 if (p == genie_voiding_assignation_constant) {
870 return "genie_voiding_assignation_constant";
871 }
872 if (p == genie_widen) {
873 return "genie_widen";
874 }
875 if (p == genie_widen_int_to_real) {
876 return "genie_widen_int_to_real";
877 }
878 return NO_TEXT;
879 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|