root/trunk/gcc/gcc/algol60/statement.c

Revision 169, 21.5 kB (checked in by ant_39, 2 years ago)
  • Fixes in cloning and reparenting of statements.
  • Full second resolution now performed on call site.
  • New test for type mismatch of implicit parameter.
Line 
1 #include <assert.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4
5 #include "statement.h"
6 #include "cursor.h"
7 #include "slist.h"
8 #include "expression.h"
9 #include "desig-expr.h"
10 #include "logger.h"
11 #include "symbol.h"
12 #include "label.h"
13 #include "type.h"
14 #include "estring.h"
15 #include "boundspair.h"
16 #include "for-elmt.h"
17 #include "meta.h"
18 #include "a60_symtab.h"
19 #include "visitor-impl.h"
20
21 static char const * private_statement_signature = "statement";
22
23 typedef struct struct_stmt_dummy_rep_t
24 {
25 }
26 stmt_dummy_rep_t;
27
28 typedef struct struct_stmt_assign_rep_t
29 {
30   expression_t * rhs;
31   slist_t * lhss;
32 }
33 stmt_assign_rep_t;
34
35 typedef struct struct_stmt_call_rep_t
36 {
37   expression_t * call;
38 }
39 stmt_call_rep_t;
40
41 typedef struct struct_stmt_cond_rep_t
42 {
43   expression_t * cond;
44   statement_t * ifclause;
45   statement_t * elseclause;
46 }
47 stmt_cond_rep_t;
48
49 typedef struct struct_stmt_for_rep_t
50 {
51   expression_t * variable;
52   slist_t * elmts;
53   statement_t * body;
54 }
55 stmt_for_rep_t;
56
57 typedef struct struct_stmt_goto_rep_t
58 {
59   desig_expr_t * target;
60 }
61 stmt_goto_rep_t;
62
63 /// Used for blocks as well as for toplevs.
64 typedef struct struct_container_rep_t
65 {
66   slist_t * statements;
67   a60_symtab_t * symtab;
68 }
69 container_rep_t;
70
71 typedef enum enum_stmt_kind_t
72 {
73   sk_dummy,
74   sk_assign,
75   sk_call,
76   sk_cond,
77   sk_for,
78   sk_goto,
79   sk_block,
80   sk_toplev,
81 }
82 stmt_kind_t;
83
84 struct struct_statement_t
85 {
86   visitable_t base;
87
88   cursor_t * cursor;
89   container_t * parent;
90   slist_t * labels;
91   union {
92     stmt_dummy_rep_t dummy;
93     stmt_assign_rep_t assign;
94     stmt_call_rep_t call;
95     stmt_cond_rep_t cond;
96     stmt_for_rep_t afor;
97     stmt_goto_rep_t agoto;
98     container_rep_t block; ///< Used by both block and toplev.
99   };
100 };
101
102 static void *
103 private_check_symbol_label (void * ptr, void * data ATTRIBUTE_UNUSED)
104 {
105   symbol_t * sym = a60_as_symbol (ptr);
106   if (!types_same (symbol_type (sym), type_label ()))
107     sym = NULL;
108   return sym;
109 }
110
111 static statement_t *
112 private_new_statement (stmt_kind_t kind, cursor_t * cursor, container_t * parent)
113 {
114   statement_t * ret = malloc (sizeof (statement_t));
115 #ifndef NDEBUG
116   ret->base.signature = private_statement_signature;
117 #endif
118   ret->base.kind = kind;
119   ret->cursor = cursor;
120   ret->parent = parent;
121   ret->labels = new_slist_typed (private_check_symbol_label, NULL);
122   return ret;
123 }
124
125 statement_t *
126 new_stmt_dummy (cursor_t * cursor)
127 {
128   return private_new_statement (sk_dummy, cursor, NULL);
129 }
130
131 static void *
132 private_check_expr_lvalue (void * ptr, void * data ATTRIBUTE_UNUSED)
133 {
134   expression_t * expr = a60_as_expression (ptr);
135   if (expr && !expr_is_lvalue (expr))
136     expr = NULL;
137   return expr;
138 }
139
140 statement_t *
141 new_stmt_assign (cursor_t * cursor, slist_t * lhss, expression_t * rhs)
142 {
143   assert (lhss != NULL);
144   assert (rhs != NULL);
145
146   statement_t * ret = private_new_statement (sk_assign, cursor, NULL);
147   slist_set_type (lhss, private_check_expr_lvalue, NULL);
148   ret->assign.lhss = lhss;
149   ret->assign.rhs = rhs;
150
151   return ret;
152 }
153
154 statement_t *
155 new_stmt_call (cursor_t * cursor, expression_t * call)
156 {
157   assert (call != NULL);
158
159   statement_t * ret = private_new_statement (sk_call, cursor, NULL);
160   ret->call.call = call;
161   return ret;
162 }
163
164 statement_t *
165 new_stmt_cond (cursor_t * cursor, expression_t * cond,
166                statement_t * ifclause, statement_t * elseclause)
167 {
168   assert (cond != NULL);
169   assert (ifclause != NULL);
170
171   statement_t * ret = private_new_statement (sk_cond, cursor, NULL);
172   ret->cond.cond = cond;
173   ret->cond.ifclause = ifclause;
174   ret->cond.elseclause = elseclause;
175   return ret;
176 }
177
178 statement_t *
179 new_stmt_for (cursor_t * cursor, expression_t * variable, slist_t * elmts, statement_t * body)
180 {
181   assert (variable != NULL);
182   assert (elmts != NULL);
183   assert (body != NULL);
184
185   statement_t * ret = private_new_statement (sk_for, cursor, NULL);
186   ret->afor.variable = variable;
187   slist_set_type (elmts, adapt_test, a60_as_for_elmt);
188   ret->afor.elmts = elmts;
189   ret->afor.body = body;
190   return ret;
191 }
192
193 statement_t *
194 new_stmt_goto (cursor_t * cursor, desig_expr_t * target)
195 {
196   assert (target != NULL);
197
198   statement_t * ret = private_new_statement (sk_goto, cursor, NULL);
199   ret->agoto.target = target;
200   return ret;
201 }
202
203 static container_t *
204 private_new_container (stmt_kind_t kind, cursor_t * cursor, a60_symtab_t * symtab)
205 {
206   statement_t * ret = private_new_statement (kind, cursor, NULL);
207   ret->block.statements = new_slist_typed (adapt_test, a60_as_statement);
208   ret->block.symtab = symtab;
209   return (container_t *)ret;
210 }
211
212 container_t *
213 new_stmt_block (cursor_t * cursor, a60_symtab_t * symtab)
214 {
215   return private_new_container (sk_block, cursor, symtab);
216 }
217
218 container_t *
219 new_stmt_toplev (cursor_t * cursor, a60_symtab_t * symtab)
220 {
221   return private_new_container (sk_toplev, cursor, symtab);
222 }
223
224 static void *
225 private_symtab_pick_labels (symbol_t * sym, void * _labels)
226 {
227   slist_t * labels = a60_as_slist (_labels);
228   if (types_same (symbol_type (sym), type_label ()))
229     slist_pushback (labels, sym);
230   return NULL;
231 }
232
233 statement_t *
234 clone_statement (statement_t const * self)
235 {
236   assert (self != NULL);
237
238   statement_t * ret = private_new_statement (self->base.kind, self->cursor, NULL);
239
240   switch (self->base.kind)
241     {
242     case sk_dummy:
243       break;
244
245     case sk_assign:
246       ret->assign.lhss = clone_slist (self->assign.lhss);
247       slist_map (ret->assign.lhss, adapt_test, clone_expression);
248       ret->assign.rhs = clone_expression (self->assign.rhs);
249       break;
250
251     case sk_call:
252       ret->call.call = clone_expression (self->call.call);
253       break;
254
255     case sk_cond:
256       ret->cond.cond = clone_expression (self->cond.cond);
257       ret->cond.ifclause = clone_statement (self->cond.ifclause);
258       ret->cond.elseclause
259         = ret->cond.elseclause ? clone_statement (self->cond.elseclause) : NULL;
260       break;
261
262     case sk_for:
263       ret->afor.variable = clone_expression (self->afor.variable);
264       ret->afor.elmts = clone_slist (self->afor.elmts);
265       slist_map (ret->afor.elmts, adapt_test, clone_for_elmt);
266       ret->afor.body = clone_statement (self->afor.body);
267       break;
268
269     case sk_goto:
270       ret->agoto.target = clone_desig_expr (self->agoto.target);
271       break;
272
273     case sk_block:
274     case sk_toplev:
275       {
276         ret->block.symtab = a60_clone_symtab (self->block.symtab);
277         ret->block.statements = new_slist_typed (adapt_test, a60_as_statement);
278
279         // extract labels from the list
280         slist_t * labels = new_slist ();
281         a60_symtab_each (ret->block.symtab,
282                          a60_symbol_callback (private_symtab_pick_labels),
283                          labels);
284         slist_it_t * jt = slist_iter (labels);
285
286         // clone statement list and retarget labels in one pass
287         slist_it_t * it = slist_iter (self->block.statements);
288         for (; slist_it_has (it); slist_it_next (it))
289           {
290             statement_t * stmt = slist_it_get (it);
291             statement_t * clone = clone_statement (stmt);
292             container_add_stmt (a60_as_container (ret), clone);
293
294             slist_it_reset (jt, labels);
295             for (; slist_it_has (jt); slist_it_next (jt))
296               {
297                 symbol_t * sym = slist_it_get (jt);
298                 statement_t * target = symbol_stmt (sym);
299                 if (target == stmt)
300                   {
301                     symbol_set_stmt (sym, clone);
302                     stmt_add_label (clone, sym);
303                   }
304               }
305           }
306
307         delete_slist_it (jt);
308         delete_slist_it (it);
309         delete_slist (labels);
310       }
311       break;
312     };
313
314   return ret;
315 }
316
317 container_t *
318 clone_container (container_t const * self)
319 {
320   return a60_as_container (clone_statement (a60_as_statement ((container_t *)self)));
321 }
322
323 statement_t *
324 a60_as_statement (void * obj)
325 {
326 #ifndef NDEBUG
327   a60_check_access (obj, private_statement_signature);
328 #endif
329   return (statement_t *)obj;
330 }
331
332 container_t *
333 a60_as_container (void * obj)
334 {
335 #ifndef NDEBUG
336   statement_t * st = a60_as_statement (obj);
337   assert (st->base.kind == sk_block
338           || st->base.kind == sk_toplev);
339 #endif
340   return (container_t *)obj;
341 }
342
343 static char const *
344 padding (int level)
345 {
346   static char const* padding =
347     "                                                            "
348     "                                                            "
349     "                                                            "
350     "                                                            "
351     "                                                            ";
352   if (level > 300)
353     level = 300;
354   return padding + 300 - level;
355 }
356
357
358 static void private_stmt_dump (statement_t const * self, estring_t * buf, int level);
359
360 static void
361 private_dump_container (statement_t const * self ATTRIBUTE_UNUSED,
362                         estring_t * buf ATTRIBUTE_UNUSED,
363                         int level ATTRIBUTE_UNUSED)
364 {
365   /*
366   estring_t * buf0 = new_estring ();
367
368   // dump all variables but labels and hidden symbols
369   slist_it_t * it = slist_iter (self->block.symtab);
370   for (; slist_it_has (it); slist_it_next (it))
371     {
372       symbol_t * sym = slist_it_get (it);
373       type_t const * symtype = symbol_type (sym);
374       if (types_same (symtype, type_label ())
375           || symbol_hidden (sym))
376         continue;
377
378       type_to_str_canon (symtype, buf0);
379       estr_append_cstr (buf, padding (level));
380       estr_append (buf, buf0);
381       estr_push (buf, ' ');
382       estr_append (buf, label_id (symbol_label (sym)));
383       if (type_is_own (symtype))
384         symtype = type_host (symtype);
385       if (type_is_array (symtype))
386         {
387           estr_push (buf, '[');
388           int first = 1;
389           for (; type_is_array (symtype); symtype = type_host (symtype))
390             {
391               boundspair_t * bp = t_array_bounds (symtype);
392               if (first)
393                 first = 0;
394               else
395                 estr_push (buf, ',');
396               expr_to_str (boundspair_lo (bp), buf0);
397               estr_append (buf, buf0);
398               estr_push (buf, ':');
399               expr_to_str (boundspair_hi (bp), buf0);
400               estr_append (buf, buf0);
401             }
402           estr_push (buf, ']');
403         }
404       estr_append_cstr (buf, ";\n");
405     }
406
407   slist_it_reset (it, self->block.statements);
408
409   // dump all statemenets
410   for (;slist_it_has (it);)
411     {
412       statement_t * stmt = slist_it_get (it);
413
414       // look for any labels pointing to this command
415       slist_it_t * lt = slist_iter (stmt_labels (stmt));
416       for (; slist_it_has (lt); slist_it_next (lt))
417         {
418           symbol_t * sym = slist_it_get (lt);
419           estr_append_cstr (buf, padding (level));
420           estr_append (buf, label_id (symbol_label (sym)));
421           estr_append_cstr (buf, ":\n");
422         }
423       delete_slist_it (lt);
424
425       slist_it_next (it);
426
427       // dump the statement itself.  Don't dump it, if there are no
428       // more statements in container (i.e. `stmt' is last statement)
429       // and `stmt' is dummy statement.
430       if (slist_it_has (it)
431           || ((statement_t *)stmt)->base.kind != sk_dummy)
432         private_stmt_dump (stmt, buf, level);
433       else
434         break;
435     }
436   delete_slist_it (it);
437
438   delete_estring (buf0);
439   */
440 }
441
442 static void
443 private_dump_assign (statement_t const * self, estring_t * buf, int level)
444 {
445   slist_it_t * it = slist_iter (self->assign.lhss);
446   estring_t * buf0 = new_estring ();
447   estr_append_cstr (buf, padding (level));
448   for (; slist_it_has (it); slist_it_next (it))
449     {
450       expression_t * expr = slist_it_get (it);
451       estr_append (buf, expr_to_str (expr, buf0));
452       estr_append_cstr (buf, " := ");
453     }
454   estr_append (buf, expr_to_str (self->assign.rhs, buf0));
455   estr_append_cstr (buf, ";\n");
456   delete_estring (buf0);
457   delete_slist_it (it);
458 }
459
460 static void
461 private_stmt_dump (statement_t const * self, estring_t * buf, int level)
462 {
463   switch (self->base.kind)
464     {
465     case sk_dummy:
466       return;
467
468     case sk_assign:
469       private_dump_assign (self, buf, level);
470       return;
471
472     case sk_call:
473       {
474         estring_t * buf0 = expr_to_str (self->call.call, NULL);
475         estr_append_cstr (buf, padding (level));
476         estr_append (buf, buf0);
477         estr_append_cstr (buf, ";\n");
478         delete_estring (buf0);
479         return;
480       }
481
482     case sk_cond:
483       {
484         estr_append_cstr (buf, padding (level));
485         estr_append_cstr (buf, "'if' ");
486         estring_t * buf0 = expr_to_str (self->cond.cond, NULL);
487         estr_append (buf, buf0);
488         delete_estring (buf0);
489         estr_append_cstr (buf, " 'then'\n");
490         private_stmt_dump (self->cond.ifclause, buf, level + 1);
491         if (self->cond.elseclause)
492           {
493             estr_append_cstr (buf, padding (level));
494             estr_append_cstr (buf, "'else'\n");
495             private_stmt_dump (self->cond.elseclause, buf, level + 1);
496           }
497         return;
498       }
499
500     case sk_for:
501       {
502         estr_append_cstr (buf, padding (level));
503         estr_append_cstr (buf, "'for' ");
504         estring_t * buf0 = expr_to_str (self->afor.variable, NULL);
505         estr_append (buf, buf0);
506         estr_append_cstr (buf, " := ");
507
508         slist_it_t * it = slist_iter (self->afor.elmts);
509         int first = 1;
510         for (; slist_it_has (it); slist_it_next (it))
511           {
512             for_elmt_t * elmt = slist_it_get (it);
513             if (first)
514               first = 0;
515             else
516               estr_append_cstr (buf, ", ");
517             for_elmt_to_str (elmt, buf0);
518             estr_append (buf, buf0);
519           }
520         delete_slist_it (it);
521         delete_estring (buf0);
522
523         estr_append_cstr (buf, " 'do'\n");
524         private_stmt_dump (self->afor.body, buf, level + 1);
525         return;
526       }
527
528     case sk_goto:
529       {
530         estr_append_cstr (buf, padding (level));
531         estr_append_cstr (buf, "'goto' ");
532         estring_t * buf0 = desig_expr_to_str (self->agoto.target, NULL);
533         estr_append (buf, buf0);
534         delete_estring (buf0);
535         return;
536       }
537
538     case sk_block:
539       estr_append_cstr (buf, padding (level));
540       estr_append_cstr (buf, "'begin'\n");
541       private_dump_container (self, buf, level+1);
542       estr_append_cstr (buf, padding (level));
543       estr_append_cstr (buf, "'end';\n");
544       return;
545
546     case sk_toplev:
547       private_dump_container (self, buf, level);
548       return;
549     };
550
551   assert (!"Should never get there!");
552 }
553
554 estring_t *
555 stmt_to_str (statement_t const * self, estring_t * buf)
556 {
557   assert (self != NULL);
558
559   if (buf == NULL)
560     buf = new_estring ();
561   else
562     estr_clear (buf);
563
564   private_stmt_dump (self, buf, 0);
565   return buf;
566 }
567
568 static void
569 private_resolve_symbols_assign (statement_t * self, logger_t * log)
570 {
571   expr_resolve_symbols (self->assign.rhs, self->parent, log);
572   slist_it_t * it = slist_iter (self->assign.lhss);
573   for (; slist_it_has (it); slist_it_next (it