1 /******************************** -*- C -*- ****************************
2  *
3  *	Semantic Tree manipulation module.
4  *
5  *
6  ***********************************************************************/
7 
8 /***********************************************************************
9  *
10  * Copyright 1988,89,90,91,92,94,95,99,2000,2001,2002,2003,2006
11  * Free Software Foundation, Inc.
12  * Written by Steve Byrne.
13  *
14  * This file is part of GNU Smalltalk.
15  *
16  * GNU Smalltalk is free software; you can redistribute it and/or modify it
17  * under the terms of the GNU General Public License as published by the Free
18  * Software Foundation; either version 2, or (at your option) any later
19  * version.
20  *
21  * Linking GNU Smalltalk statically or dynamically with other modules is
22  * making a combined work based on GNU Smalltalk.  Thus, the terms and
23  * conditions of the GNU General Public License cover the whole
24  * combination.
25  *
26  * In addition, as a special exception, the Free Software Foundation
27  * give you permission to combine GNU Smalltalk with free software
28  * programs or libraries that are released under the GNU LGPL and with
29  * independent programs running under the GNU Smalltalk virtual machine.
30  *
31  * You may copy and distribute such a system following the terms of the
32  * GNU GPL for GNU Smalltalk and the licenses of the other code
33  * concerned, provided that you include the source code of that other
34  * code when and as the GNU GPL requires distribution of source code.
35  *
36  * Note that people who make modified versions of GNU Smalltalk are not
37  * obligated to grant this special exception for their modified
38  * versions; it is their choice whether to do so.  The GNU General
39  * Public License gives permission to release a modified version without
40  * this exception; this exception also makes it possible to release a
41  * modified version which carries forward this exception.
42  *
43  * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
44  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
45  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
46  * more details.
47  *
48  * You should have received a copy of the GNU General Public License along with
49  * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
50  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
51  *
52  ***********************************************************************/
53 
54 #include "gstpriv.h"
55 
56 /* Make a tree_node made up of the NODETYPE type-tag and a list_node
57    representing the head of the list, for NAME and VALUE.  */
58 static inline tree_node make_list_node (YYLTYPE *location,
59 					node_type nodeType,
60 					const char *name,
61 					tree_node value);
62 
63 /* Make a expr_node made up of the NODETYPE type-tag and an expr_node
64    with given RECEIVER, SELECTOR and EXPRESSION.  */
65 static inline tree_node make_expr_node (YYLTYPE *location,
66 					node_type nodeType,
67 					tree_node receiver,
68 					OOP selector,
69 					tree_node expression);
70 
71 /* Allocate from the compilation obstack a node and assign it the
72    NODETYPE type-tag.  */
73 static inline tree_node make_tree_node (YYLTYPE *location,
74 					node_type nodeType);
75 
76 /* Print the NODE method_node with LEVEL spaces of indentation.  */
77 static void print_method_node (tree_node node,
78 			       int level);
79 
80 /* Print the NODE method_node with LEVEL spaces of indentation.  */
81 static void print_block_node (tree_node node,
82 			      int level);
83 
84 /* Print the NODE expr_node with LEVEL spaces of indentation.  */
85 static void print_expr_node (tree_node node,
86 			     int level);
87 
88 /* Print the NODE list_node with LEVEL spaces of indentation.  */
89 static void print_list_node (tree_node node,
90 			     int level);
91 
92 /* Print the NODE list_node with LEVEL spaces of indentation,
93    assuming it is a attribute.  */
94 static void print_attribute_list_node (tree_node node,
95 				       int level);
96 
97 /* Print the NODE const_node with LEVEL spaces of indentation.  */
98 static void print_const_node (tree_node node,
99 			      int level);
100 
101 /* Print the NODE list_node with LEVEL spaces of indentation,
102    discarding the NAME of each node (hence the distinction between
103    this and print_list_node).  */
104 static void print_array_constructor_node (tree_node node,
105 					  int level);
106 
107 /* Print LEVEL spaces of indentation.  */
108 static void indent (int level);
109 
110 
111 
112 
113 tree_node
_gst_make_array_elt(YYLTYPE * location,tree_node elt)114 _gst_make_array_elt (YYLTYPE *location,
115 		     tree_node elt)
116 {
117   return (make_list_node (location, TREE_ARRAY_ELT_LIST, NULL, elt));
118 }
119 
120 
121 tree_node
_gst_make_method(YYLTYPE * location,YYLTYPE * endLocation,tree_node selectorExpr,tree_node temporaries,tree_node attributes,tree_node statements,int isOldSyntax)122 _gst_make_method (YYLTYPE *location,
123 		  YYLTYPE *endLocation,
124 		  tree_node selectorExpr,
125 		  tree_node temporaries,
126 		  tree_node attributes,
127 		  tree_node statements,
128 		  int isOldSyntax)
129 {
130   tree_node result;
131 
132   result = make_tree_node (location, TREE_METHOD_NODE);
133   result->v_method.endPos = endLocation->file_offset;
134   result->v_method.selectorExpr = selectorExpr;
135   result->v_method.temporaries = temporaries;
136   result->v_method.attributes = attributes;
137   result->v_method.statements = statements;
138   result->v_method.isOldSyntax = isOldSyntax;
139   return (result);
140 }
141 
142 
143 tree_node
_gst_make_cascaded_message(YYLTYPE * location,tree_node messageExpr,tree_node cascadedMessages)144 _gst_make_cascaded_message (YYLTYPE *location,
145 		     tree_node messageExpr,
146 			    tree_node cascadedMessages)
147 {
148   return (make_expr_node (location, TREE_CASCADE_EXPR, messageExpr, NULL,
149 			  cascadedMessages));
150 }
151 
152 
153 tree_node
_gst_make_unary_expr(YYLTYPE * location,tree_node receiver,const char * unarySelectorExpr)154 _gst_make_unary_expr (YYLTYPE *location,
155 		      tree_node receiver,
156 		      const char *unarySelectorExpr)
157 {
158   OOP selector;
159 
160   /* selectors, being interned symbols, don't need to be incubated --
161      symbols once created are always referenced */
162   selector = _gst_intern_string (unarySelectorExpr);
163   return (make_expr_node (location, TREE_UNARY_EXPR, receiver, selector, NULL));
164 }
165 
166 tree_node
_gst_intern_ident(YYLTYPE * location,const char * ident)167 _gst_intern_ident (YYLTYPE *location,
168 		   const char *ident)
169 {
170   return (make_expr_node
171 	  (location, TREE_SYMBOL_NODE, NULL, _gst_intern_string (ident), NULL));
172 }
173 
174 tree_node
_gst_make_return(YYLTYPE * location,tree_node expression)175 _gst_make_return (YYLTYPE *location,
176 		  tree_node expression)
177 {
178   return (make_expr_node
179 	  (location, TREE_RETURN_EXPR, expression, _gst_nil_oop, NULL));
180 }
181 
182 tree_node
_gst_make_keyword_expr(YYLTYPE * location,tree_node receiver,tree_node keywordMessage)183 _gst_make_keyword_expr (YYLTYPE *location,
184 		        tree_node receiver,
185 			tree_node keywordMessage)
186 {
187   return (make_expr_node
188 	  (location, TREE_KEYWORD_EXPR, receiver, _gst_nil_oop, keywordMessage));
189 }
190 
191 tree_node
_gst_make_assign(YYLTYPE * location,tree_node variables,tree_node expression)192 _gst_make_assign (YYLTYPE *location,
193 		  tree_node variables,
194 		  tree_node expression)
195 {
196   return (make_expr_node
197 	  (location, TREE_ASSIGN_EXPR, variables, _gst_nil_oop, expression));
198 }
199 
200 tree_node
_gst_make_statement_list(YYLTYPE * location,tree_node expression)201 _gst_make_statement_list (YYLTYPE *location,
202 			  tree_node expression)
203 {
204   return (make_list_node (location, TREE_STATEMENT_LIST, NULL, expression));
205 }
206 
207 tree_node
_gst_make_attribute_list(YYLTYPE * location,tree_node constant)208 _gst_make_attribute_list (YYLTYPE *location,
209 		          tree_node constant)
210 {
211   return (make_list_node (location, TREE_ATTRIBUTE_LIST, NULL, constant));
212 }
213 
214 tree_node
_gst_make_keyword_list(YYLTYPE * location,const char * keyword,tree_node expression)215 _gst_make_keyword_list (YYLTYPE *location,
216 			const char *keyword,
217 			tree_node expression)
218 {
219   return (make_list_node (location, TREE_KEYWORD_LIST, keyword, expression));
220 }
221 
222 tree_node
_gst_make_variable_list(YYLTYPE * location,tree_node variable)223 _gst_make_variable_list (YYLTYPE *location,
224 		     tree_node variable)
225 {
226   /* Actually, we rely on the fact that a variable is represented as a
227      tree node of type list_node, so all we do is change the node tag
228      to TREE_VAR_DECL_LIST.  */
229   variable->nodeType = TREE_VAR_DECL_LIST;
230   return (variable);
231 }
232 
233 tree_node
_gst_make_assignment_list(YYLTYPE * location,tree_node variable)234 _gst_make_assignment_list (YYLTYPE *location,
235 		     tree_node variable)
236 {
237   /* Actually, we rely on the fact that a variable is represented as a
238      tree node of type list_node, so all we do is change the node tag
239      to TREE_VAR_DECL_LIST.  */
240   return (make_list_node (location, TREE_VAR_ASSIGN_LIST, NULL, variable));
241 }
242 
243 
244 tree_node
_gst_make_binary_expr(YYLTYPE * location,tree_node receiver,const char * binaryOp,tree_node argument)245 _gst_make_binary_expr (YYLTYPE *location,
246 		       tree_node receiver,
247 		       const char *binaryOp,
248 		       tree_node argument)
249 {
250   OOP selector;
251 
252   selector = _gst_intern_string (binaryOp);
253   return (make_expr_node
254 	  (location, TREE_BINARY_EXPR, receiver, selector, argument));
255 }
256 
257 tree_node
_gst_make_message_list(YYLTYPE * location,tree_node messageElt)258 _gst_make_message_list (YYLTYPE *location,
259 		        tree_node messageElt)
260 {
261   return (make_list_node (location, TREE_MESSAGE_LIST, NULL, messageElt));
262 }
263 
264 tree_node
_gst_make_block(YYLTYPE * location,tree_node arguments,tree_node temporaries,tree_node statements)265 _gst_make_block (YYLTYPE *location,
266 		 tree_node arguments,
267 		 tree_node temporaries,
268 		 tree_node statements)
269 {
270   tree_node result;
271 
272   result = make_tree_node (location, TREE_BLOCK_NODE);
273   result->v_block.arguments = arguments;
274   result->v_block.temporaries = temporaries;
275   result->v_block.statements = statements;
276   return (result);
277 }
278 
279 tree_node
_gst_make_variable(YYLTYPE * location,const char * name)280 _gst_make_variable (YYLTYPE *location,
281 		    const char *name)
282 {
283   return (make_list_node (location, TREE_VARIABLE_NODE, name, NULL));
284 }
285 
286 
287 tree_node
_gst_make_int_constant(YYLTYPE * location,intptr_t ival)288 _gst_make_int_constant (YYLTYPE *location,
289 		     intptr_t ival)
290 {
291   tree_node result;
292 
293   result = make_tree_node (location, TREE_CONST_EXPR);
294   result->v_const.constType = CONST_INT;
295   result->v_const.val.iVal = ival;
296 
297   return (result);
298 }
299 
300 tree_node
_gst_make_byte_object_constant(YYLTYPE * location,byte_object boval)301 _gst_make_byte_object_constant (YYLTYPE *location,
302 		     byte_object boval)
303 {
304   tree_node result;
305 
306   result = make_tree_node (location, TREE_CONST_EXPR);
307   result->v_const.constType = CONST_BYTE_OBJECT;
308   result->v_const.val.boVal = boval;
309 
310   return (result);
311 }
312 
313 tree_node
_gst_make_float_constant(YYLTYPE * location,long double fval,int type)314 _gst_make_float_constant (YYLTYPE *location,
315 		     long double fval, int type)
316 {
317   tree_node result;
318 
319   result = make_tree_node (location, TREE_CONST_EXPR);
320   result->v_const.constType = type;
321   result->v_const.val.fVal = fval;
322 
323   return (result);
324 }
325 
326 tree_node
_gst_make_string_constant(YYLTYPE * location,const char * sval)327 _gst_make_string_constant (YYLTYPE *location,
328 		           const char *sval)
329 {
330   tree_node result;
331 
332   result = make_tree_node (location, TREE_CONST_EXPR);
333   result->v_const.constType = CONST_STRING;
334   result->v_const.val.sVal = sval;
335 
336   return (result);
337 }
338 
339 tree_node
_gst_make_deferred_binding_constant(YYLTYPE * location,tree_node varNode)340 _gst_make_deferred_binding_constant (YYLTYPE *location,
341 				     tree_node varNode)
342 {
343   tree_node result;
344 
345   result = make_tree_node (location, TREE_CONST_EXPR);
346   result->v_const.constType = CONST_DEFERRED_BINDING;
347   result->v_const.val.aVal = varNode;
348 
349   return (result);
350 }
351 
352 tree_node
_gst_make_oop_constant(YYLTYPE * location,OOP oval)353 _gst_make_oop_constant (YYLTYPE *location,
354 		        OOP oval)
355 {
356   tree_node result;
357 
358   result = make_tree_node (location, TREE_CONST_EXPR);
359   result->v_const.constType = CONST_OOP;
360   result->v_const.val.oopVal = oval;
361   INC_ADD_OOP (oval);
362 
363   return (result);
364 }
365 
366 tree_node
_gst_make_char_constant(YYLTYPE * location,int ival)367 _gst_make_char_constant (YYLTYPE *location, int ival)
368 {
369   tree_node result;
370 
371   result = make_tree_node (location, TREE_CONST_EXPR);
372   result->v_const.constType = CONST_CHAR;
373   result->v_const.val.iVal = ival;
374 
375   return (result);
376 }
377 
378 tree_node
_gst_make_symbol_constant(YYLTYPE * location,tree_node symbolNode)379 _gst_make_symbol_constant (YYLTYPE *location,
380 		     tree_node symbolNode)
381 {
382   tree_node result;
383 
384   result = make_tree_node (location, TREE_CONST_EXPR);
385   result->v_const.constType = CONST_OOP;
386   if (symbolNode)
387     result->v_const.val.oopVal = symbolNode->v_expr.selector;
388   else
389     result->v_const.val.oopVal = _gst_nil_oop;
390 
391   return (result);
392 }
393 
394 /* This function converts an gst_array constant's format (linked list of its
395  * elements) to a gst_byte_array constant's format (byte_object struct).  The code
396  * itself is awful and the list is extremely space inefficient, but consider
397  * that:
398  * a) it makes the parser simpler (Arrays and ByteArrays are treated in almost
399  *    the same way; only, the latter call this function and the former don't).
400  * b) a list is indeed an elegant solution because we don't know the size of
401  *    the byte array until we have parsed it all (that is, until we call this
402  *    function.
403  * c) the byte_object is the best format for ByteArrays: first, it is the one
404  *    which makes it easiest to make a full-fledged object out of the parse
405  *    tree; second, it is logical to choose it since LargeIntegers use it,
406  *    and ByteArrays are represented exactly the same as LargeIntegers.
407  */
408 tree_node
_gst_make_byte_array_constant(YYLTYPE * location,tree_node aval)409 _gst_make_byte_array_constant (YYLTYPE *location,
410 			       tree_node aval)
411 {
412   tree_node arrayElt, ival;
413   int len;
414   byte_object bo;
415   gst_uchar *data;
416 
417   for (len = 0, arrayElt = aval; arrayElt;
418        len++, arrayElt = arrayElt->v_list.next);
419 
420   bo = (byte_object) obstack_alloc (_gst_compilation_obstack,
421 				    sizeof (struct byte_object) + len);
422 
423   bo->class = _gst_byte_array_class;
424   bo->size = len;
425   data = bo->body;
426 
427   /* Now extract the node for each integer constant, storing its value
428      into the byte_object */
429   for (arrayElt = aval; arrayElt; arrayElt = arrayElt->v_list.next)
430     {
431       ival = arrayElt->v_list.value;
432       *data++ = ival->v_const.val.iVal;
433     }
434 
435   return (_gst_make_byte_object_constant (location, bo));
436 }
437 
438 tree_node
_gst_make_array_constant(YYLTYPE * location,tree_node aval)439 _gst_make_array_constant (YYLTYPE *location,
440 		     tree_node aval)
441 {
442   tree_node result;
443 
444   result = make_tree_node (location, TREE_CONST_EXPR);
445   result->v_const.constType = CONST_ARRAY;
446   result->v_const.val.aVal = aval;
447 
448   return (result);
449 }
450 
451 tree_node
_gst_make_array_constructor(YYLTYPE * location,tree_node statements)452 _gst_make_array_constructor (YYLTYPE *location,
453 		     tree_node statements)
454 {
455   tree_node result;
456 
457   result = make_tree_node (location, TREE_ARRAY_CONSTRUCTOR);
458   result->v_const.constType = CONST_ARRAY;
459   result->v_const.val.aVal = statements;
460 
461   return (result);
462 }
463 
464 tree_node
_gst_make_binding_constant(YYLTYPE * location,tree_node variables)465 _gst_make_binding_constant (YYLTYPE *location,
466 		     tree_node variables)
467 {
468   tree_node result;
469 
470   result = make_tree_node (location, TREE_CONST_EXPR);
471   result->v_const.constType = CONST_BINDING;
472   result->v_const.val.aVal = variables;
473 
474   return (result);
475 }
476 
477 tree_node
_gst_add_node(tree_node n1,tree_node n2)478 _gst_add_node (tree_node n1,
479 	       tree_node n2)
480 {
481   if (n1 == NULL)
482     return n2;
483 
484   *(n1->v_list.nextAddr) = n2;
485   n1->v_list.nextAddr = n2->v_list.nextAddr;
486   return n1;
487 }
488 
489 void
_gst_free_tree()490 _gst_free_tree ()
491 {
492   obstack_free (_gst_compilation_obstack, NULL);
493   obstack_init (_gst_compilation_obstack);
494 }
495 
496 
497 
498 
499 
500 /***********************************************************************
501  *
502  * Internal tree construction routines.
503  *
504  ***********************************************************************/
505 
506 
507 static tree_node
make_list_node(YYLTYPE * location,node_type nodeType,const char * name,tree_node value)508 make_list_node (YYLTYPE *location,
509 		node_type nodeType,
510 		const char *name,
511 		tree_node value)
512 {
513   tree_node result;
514 
515   result = make_tree_node (location, nodeType);
516   result->v_list.name = name;
517   result->v_list.value = value;
518   result->v_list.next = NULL;
519   result->v_list.nextAddr = &result->v_list.next;
520   return (result);
521 }
522 
523 static tree_node
make_expr_node(YYLTYPE * location,node_type nodeType,tree_node receiver,OOP selector,tree_node expression)524 make_expr_node (YYLTYPE *location,
525 		node_type nodeType,
526 		tree_node receiver,
527 		OOP selector,
528 		tree_node expression)
529 {
530   tree_node result;
531 
532   result = make_tree_node (location, nodeType);
533   result->v_expr.receiver = receiver;
534   result->v_expr.selector = selector;
535   result->v_expr.expression = expression;
536   return (result);
537 }
538 
539 static tree_node
make_tree_node(YYLTYPE * location,node_type nodeType)540 make_tree_node (YYLTYPE *location,
541 		     node_type nodeType)
542 {
543   tree_node result;
544 
545   result = (tree_node) obstack_alloc (_gst_compilation_obstack,
546 				      sizeof (struct tree_node));
547 
548   result->nodeType = nodeType;
549   result->location = *location;
550   return (result);
551 }
552 
553 
554 
555 /***********************************************************************
556  *
557  *	Printing routines.
558  *
559  ***********************************************************************/
560 void
_gst_print_tree(tree_node node,int level)561 _gst_print_tree (tree_node node,
562 		 int level)
563 {
564   const char *name;
565   if (node == NULL)
566     {
567       printf ("(nil)\n");
568       return;
569     }
570 
571   if (node->nodeType < TREE_FIRST || node->nodeType > TREE_LAST)
572     {
573       printf ("Unknown tree node type %d\n", node->nodeType);
574       return;
575     }
576 
577   switch (node->nodeType)
578     {
579     case TREE_METHOD_NODE: name = "TREE_METHOD_NODE"; break;
580     case TREE_UNARY_EXPR: name = "TREE_UNARY_EXPR"; break;
581     case TREE_BINARY_EXPR: name = "TREE_BINARY_EXPR"; break;
582     case TREE_KEYWORD_EXPR: name = "TREE_KEYWORD_EXPR"; break;
583     case TREE_VARIABLE_NODE: name = "TREE_VARIABLE_NODE"; break;
584     case TREE_ATTRIBUTE_LIST: name = "TREE_ATTRIBUTE_LIST"; break;
585     case TREE_KEYWORD_LIST: name = "TREE_KEYWORD_LIST"; break;
586     case TREE_VAR_DECL_LIST: name = "TREE_VAR_DECL_LIST"; break;
587     case TREE_VAR_ASSIGN_LIST: name = "TREE_VAR_ASSIGN_LIST"; break;
588     case TREE_STATEMENT_LIST: name = "TREE_STATEMENT_LIST"; break;
589     case TREE_RETURN_EXPR: name = "TREE_RETURN_EXPR"; break;
590     case TREE_ASSIGN_EXPR: name = "TREE_ASSIGN_EXPR"; break;
591     case TREE_CONST_EXPR: name = "TREE_CONST_EXPR"; break;
592     case TREE_SYMBOL_NODE: name = "TREE_SYMBOL_NODE"; break;
593     case TREE_ARRAY_ELT_LIST: name = "TREE_ARRAY_ELT_LIST"; break;
594     case TREE_BLOCK_NODE: name = "TREE_BLOCK_NODE"; break;
595     case TREE_CASCADE_EXPR: name = "TREE_CASCADE_EXPR"; break;
596     case TREE_MESSAGE_LIST: name = "TREE_MESSAGE_LIST"; break;
597     case TREE_ARRAY_CONSTRUCTOR: name = "TREE_ARRAY_CONSTRUCTOR"; break;
598     default: abort ();
599     }
600 
601   printf ("%s\n", name);
602   switch (node->nodeType)
603     {
604     case TREE_METHOD_NODE:
605       print_method_node (node, level + 2);
606       break;
607 
608     case TREE_BLOCK_NODE:
609       print_block_node (node, level + 2);
610       break;
611 
612     case TREE_SYMBOL_NODE:
613     case TREE_UNARY_EXPR:
614     case TREE_BINARY_EXPR:
615     case TREE_KEYWORD_EXPR:
616     case TREE_CASCADE_EXPR:
617     case TREE_RETURN_EXPR:
618     case TREE_ASSIGN_EXPR:
619       print_expr_node (node, level + 2);
620       break;
621 
622     case TREE_VARIABLE_NODE:
623     case TREE_KEYWORD_LIST:
624     case TREE_ARRAY_ELT_LIST:
625     case TREE_MESSAGE_LIST:
626     case TREE_STATEMENT_LIST:
627     case TREE_VAR_DECL_LIST:
628     case TREE_VAR_ASSIGN_LIST:
629       print_list_node (node, level + 2);
630       break;
631 
632     case TREE_ARRAY_CONSTRUCTOR:
633       print_array_constructor_node (node, level + 2);
634       break;
635 
636     case TREE_CONST_EXPR:
637       print_const_node (node, level + 2);
638       break;
639 
640     case TREE_ATTRIBUTE_LIST:
641       print_attribute_list_node (node, level + 2);
642       break;
643 
644     default:
645       abort ();
646     }
647 }
648 
649 static void
print_array_constructor_node(tree_node node,int level)650 print_array_constructor_node (tree_node node,
651 			      int level)
652 {
653   indent (level);
654   _gst_print_tree (node->v_const.val.aVal, level);
655 }
656 
657 static void
print_list_node(tree_node node,int level)658 print_list_node (tree_node node,
659 		 int level)
660 {
661   indent (level);
662   printf ("name: %s\n",
663 	  node->v_list.name ? node->v_list.name : "(nil)");
664   indent (level);
665   printf ("value: ");
666   _gst_print_tree (node->v_list.value, level + 7);
667   if (node->v_list.next)
668     {
669       indent (level - 2);
670       _gst_print_tree (node->v_list.next, level - 2);
671     }
672 }
673 
674 static void
print_expr_node(tree_node node,int level)675 print_expr_node (tree_node node,
676 		 int level)
677 {
678   indent (level);
679   printf ("selector: %#O\n", node->v_expr.selector);
680   indent (level);
681   printf ("receiver: ");
682   _gst_print_tree (node->v_expr.receiver, level + 10);
683   /* ??? don't print the expression for unary type things, and don't
684      print the receiver for symbol nodes */
685   indent (level);
686   printf ("expression: ");
687   _gst_print_tree (node->v_expr.expression, level + 12);
688 }
689 
690 static void
print_method_node(tree_node node,int level)691 print_method_node (tree_node node,
692 		   int level)
693 {
694   indent (level);
695   printf ("selectorExpr: ");
696   _gst_print_tree (node->v_method.selectorExpr, level + 14);
697   indent (level);
698   printf ("temporaries: ");
699   _gst_print_tree (node->v_method.temporaries, level + 13);
700   indent (level);
701   printf ("attributes: ");
702   _gst_print_tree (node->v_method.attributes, level + 9);
703   indent (level);
704   printf ("statements: ");
705   _gst_print_tree (node->v_method.statements, level + 12);
706   indent (level);
707   if (node->v_method.isOldSyntax)
708     printf ("old syntax\n");
709   else
710     printf ("new syntax\n");
711 }
712 
713 static void
print_block_node(tree_node node,int level)714 print_block_node (tree_node node,
715 		  int level)
716 {
717   indent (level);
718   printf ("arguments: ");
719   _gst_print_tree (node->v_block.arguments, level + 11);
720   indent (level);
721   printf ("temporaries: ");
722   _gst_print_tree (node->v_block.temporaries, level + 13);
723   indent (level);
724   printf ("statements: ");
725   _gst_print_tree (node->v_block.statements, level + 12);
726 }
727 
728 static void
print_const_node(tree_node node,int level)729 print_const_node (tree_node node,
730 		  int level)
731 {
732   indent (level);
733   switch (node->v_const.constType)
734     {
735     case CONST_INT:
736       printf ("int: %ld\n", node->v_const.val.iVal);
737       break;
738 
739     case CONST_FLOATD:
740       printf ("floatd: %g\n", (float) node->v_const.val.fVal);
741       break;
742 
743     case CONST_FLOATE:
744       printf ("floate: %g\n", (double) node->v_const.val.fVal);
745       break;
746 
747     case CONST_FLOATQ:
748       printf ("floatq: %Lg\n", node->v_const.val.fVal);
749       break;
750 
751     case CONST_STRING:
752       printf ("string: \"%s\"\n", node->v_const.val.sVal);
753       break;
754 
755     case CONST_OOP:
756       printf ("oop: %O\n", node->v_const.val.oopVal);
757       break;
758 
759     case CONST_ARRAY:
760       printf ("array: ");
761       _gst_print_tree (node->v_const.val.aVal, level + 7);
762       break;
763 
764     case CONST_DEFERRED_BINDING:
765       printf ("deferred variable binding: ");
766       _gst_print_tree (node->v_const.val.aVal, level + 27);
767       break;
768 
769     case CONST_BINDING:
770       printf ("variable binding: ");
771       _gst_print_tree (node->v_const.val.aVal, level + 18);
772       break;
773 
774     default:
775       _gst_errorf ("Unknown constant type %d", node->v_const.constType);
776     }
777 }
778 
779 static void
print_attribute_list_node(tree_node node,int level)780 print_attribute_list_node (tree_node node,
781 			   int level)
782 {
783   tree_node value = node->v_list.value;
784   OOP messageOOP = value->v_const.val.oopVal;
785   gst_message message = (gst_message) OOP_TO_OBJ (messageOOP);
786   OOP selectorOOP = message->selector;
787   gst_string selector = (gst_string) OOP_TO_OBJ (selectorOOP);
788   OOP argumentsOOP = message->args;
789   gst_object arguments = OOP_TO_OBJ (argumentsOOP);
790 
791   const char *sel = selector->chars;
792   char *name = alloca (oop_num_fields (selectorOOP) + 1);
793   int numArgs = oop_num_fields (argumentsOOP);
794 
795   int i;
796   char sep;
797 
798   indent (level);
799   printf ("value: ");
800   for (sep = '<', i = 0; i < numArgs; sep = ' ', i++)
801     {
802       /* Find the end of this keyword and print it together with
803          its argument.  */
804       const char *end = strchr (sel, ':');
805       memcpy (name, sel, end - sel);
806       name[end - sel] = 0;
807       sel = end + 1;
808       printf ("%c%s: %O", sep, name, arguments->data[i]);
809     }
810 
811   printf (">\n");
812   if (node->v_list.next)
813     {
814       indent (level - 2);
815       _gst_print_tree (node->v_list.next, level - 2);
816     }
817 }
818 
819 static void
indent(int level)820 indent (int level)
821 {
822   printf ("%*s", level, "");
823 }
824