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