1 /* node.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2009 */
2
3 /*
4
5 Copyright (c) 2005-2009 Made to Order Software Corp.
6
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31
32 */
33
34
35 #include "node.h"
36
37
38 namespace sswf
39 {
40 namespace as
41 {
42
43
44 /**********************************************************************/
45 /**********************************************************************/
46 /*** NODE PTR *******************************************************/
47 /**********************************************************************/
48 /**********************************************************************/
NodePtr(const NodePtr & node)49 NodePtr::NodePtr(const NodePtr& node)
50 {
51 f_node = node.f_node;
52 if(f_node != 0) {
53 f_node->AddRef();
54 }
55 }
56
57
~NodePtr()58 NodePtr::~NodePtr()
59 {
60 if(f_node != 0) {
61 f_node->Release();
62 }
63 }
64
65
operator =(const NodePtr & node)66 NodePtr& NodePtr::operator = (const NodePtr& node)
67 {
68 SetNode(node);
69 return *this;
70 }
71
72
SetInputInfo(const Input * input)73 void NodePtr::SetInputInfo(const Input *input)
74 {
75 AS_ASSERT(f_node != 0);
76 f_node->SetInputInfo(input);
77 }
78
79
CopyInputInfo(const NodePtr & node)80 void NodePtr::CopyInputInfo(const NodePtr& node)
81 {
82 AS_ASSERT(f_node != 0);
83 f_node->CopyInputInfo(node.f_node);
84 }
85
86
GetPage(void) const87 long NodePtr::GetPage(void) const
88 {
89 if(f_node != 0) {
90 return f_node->GetPage();
91 }
92
93 return 0;
94 }
95
96
GetPageLine(void) const97 long NodePtr::GetPageLine(void) const
98 {
99 if(f_node != 0) {
100 return f_node->GetPageLine();
101 }
102
103 return 0;
104 }
105
106
GetParagraph(void) const107 long NodePtr::GetParagraph(void) const
108 {
109 if(f_node != 0) {
110 return f_node->GetParagraph();
111 }
112
113 return 0;
114 }
115
116
GetLine(void) const117 long NodePtr::GetLine(void) const
118 {
119 if(f_node != 0) {
120 return f_node->GetLine();
121 }
122
123 return 0;
124 }
125
126
GetFilename(void) const127 const String& NodePtr::GetFilename(void) const
128 {
129 static const String empty;
130 if(f_node != 0) {
131 return f_node->GetFilename();
132 }
133
134 return empty;
135 }
136
137
138
139
SetNode(const Node * node)140 void NodePtr::SetNode(const Node *node)
141 {
142 if(node != 0) {
143 const_cast<Node *>(node)->AddRef();
144 }
145 if(f_node != 0) {
146 f_node->Release();
147 }
148 f_node = const_cast<Node *>(node);
149 }
150
151
SetNode(const NodePtr & node)152 void NodePtr::SetNode(const NodePtr& node)
153 {
154 if(node.f_node != 0) {
155 node.f_node->AddRef();
156 }
157 if(f_node != 0) {
158 f_node->Release();
159 }
160 f_node = node.f_node;
161 }
162
163
CreateNode(node_t type)164 void NodePtr::CreateNode(node_t type)
165 {
166 ClearNode();
167
168 f_node = new Node(type);
169 }
170
171
Clone(const NodePtr & source)172 NodePtr& NodePtr::Clone(const NodePtr& source)
173 {
174 Node *n;
175
176 if(source.f_node != 0) {
177 n = new Node(*source.f_node, f_node == 0
178 ? *source.f_node->GetParent().f_node :
179 *f_node->GetParent().f_node);
180 }
181 else {
182 n = 0;
183 }
184
185 ClearNode();
186
187 f_node = n;
188
189 return *this;
190 }
191
192
ClearNode(void)193 void NodePtr::ClearNode(void)
194 {
195 if(f_node != 0) {
196 f_node->Release();
197 }
198
199 f_node = 0;
200 }
201
202
GetData(void) const203 Data& NodePtr::GetData(void) const
204 {
205 AS_ASSERT(f_node != 0);
206 return const_cast<Data&>(f_node->GetData());
207 }
208
209
SetData(const Data & data)210 void NodePtr::SetData(const Data& data)
211 {
212 AS_ASSERT(f_node != 0);
213 f_node->SetData(data);
214 }
215
216
GetAttrs(void) const217 unsigned long NodePtr::GetAttrs(void) const
218 {
219 AS_ASSERT(f_node != 0);
220 return f_node->GetAttrs();
221 }
222
223
SetAttrs(unsigned long attrs)224 void NodePtr::SetAttrs(unsigned long attrs)
225 {
226 AS_ASSERT(f_node != 0);
227 f_node->SetAttrs(attrs);
228 }
229
230
HasSideEffects(void) const231 bool NodePtr::HasSideEffects(void) const
232 {
233 AS_ASSERT(f_node != 0);
234 return f_node->HasSideEffects();
235 }
236
237
IsLocked(void) const238 bool NodePtr::IsLocked(void) const
239 {
240 AS_ASSERT(f_node != 0);
241 return f_node->IsLocked();
242 }
243
244
Lock(void)245 void NodePtr::Lock(void)
246 {
247 AS_ASSERT(f_node != 0);
248 f_node->Lock();
249 }
250
251
Unlock(void)252 void NodePtr::Unlock(void)
253 {
254 AS_ASSERT(f_node != 0);
255 f_node->Unlock();
256 }
257
258
SetOffset(int offset)259 void NodePtr::SetOffset(int offset)
260 {
261 AS_ASSERT(f_node != 0);
262 f_node->SetOffset(offset);
263 }
264
265
GetOffset(void) const266 int NodePtr::GetOffset(void) const
267 {
268 AS_ASSERT(f_node != 0);
269 return f_node->GetOffset();
270 }
271
272
ReplaceWith(NodePtr & node)273 void NodePtr::ReplaceWith(NodePtr& node)
274 {
275 AS_ASSERT(f_node != 0 && node.f_node != 0);
276
277 if(f_node == node.f_node) {
278 return;
279 }
280
281 f_node->ReplaceWith(node.f_node);
282 f_node->Release();
283 f_node = node.f_node;
284 f_node->AddRef();
285 }
286
287
DeleteChild(int index)288 void NodePtr::DeleteChild(int index)
289 {
290 AS_ASSERT(f_node != 0);
291 f_node->DeleteChild(index);
292 }
293
294
AddChild(NodePtr & child)295 void NodePtr::AddChild(NodePtr& child)
296 {
297 AS_ASSERT(f_node != 0);
298 f_node->AddChild(child);
299 }
300
301
InsertChild(int index,NodePtr & child)302 void NodePtr::InsertChild(int index, NodePtr& child)
303 {
304 AS_ASSERT(f_node != 0);
305 f_node->InsertChild(index, child);
306 }
307
308
SetChild(int index,NodePtr & child)309 void NodePtr::SetChild(int index, NodePtr& child)
310 {
311 AS_ASSERT(f_node != 0);
312 f_node->SetChild(index, child);
313 }
314
315
GetChildCount(void) const316 int NodePtr::GetChildCount(void) const
317 {
318 if(f_node != 0) {
319 return f_node->GetChildCount();
320 }
321
322 return 0;
323 }
324
325
GetChild(int index) const326 NodePtr& NodePtr::GetChild(int index) const
327 {
328 AS_ASSERT(f_node != 0);
329 return f_node->GetChild(index);
330 }
331
332
SetParent(Node * parent)333 void NodePtr::SetParent(Node *parent)
334 {
335 AS_ASSERT(f_node != 0);
336 f_node->SetParent(parent);
337 }
338
339
GetParent(void)340 NodePtr& NodePtr::GetParent(void)
341 {
342 AS_ASSERT(f_node != 0);
343 return f_node->GetParent();
344 }
345
346
SetLink(link_t index,NodePtr & link)347 void NodePtr::SetLink(link_t index, NodePtr& link)
348 {
349 AS_ASSERT(f_node != 0);
350 f_node->SetLink(index, link);
351 }
352
353
GetLink(link_t index)354 NodePtr& NodePtr::GetLink(link_t index)
355 {
356 AS_ASSERT(f_node != 0);
357 return f_node->GetLink(index);
358 }
359
360
AddVariable(NodePtr & variable)361 void NodePtr::AddVariable(NodePtr& variable)
362 {
363 AS_ASSERT(f_node != 0);
364 f_node->AddVariable(variable);
365 }
366
367
GetVariableCount(void) const368 int NodePtr::GetVariableCount(void) const
369 {
370 if(f_node != 0) {
371 return f_node->GetVariableCount();
372 }
373
374 return 0;
375 }
376
377
GetVariable(int index) const378 NodePtr& NodePtr::GetVariable(int index) const
379 {
380 AS_ASSERT(f_node != 0);
381 return f_node->GetVariable(index);
382 }
383
384
AddLabel(NodePtr & label)385 void NodePtr::AddLabel(NodePtr& label)
386 {
387 AS_ASSERT(f_node != 0);
388 f_node->AddLabel(label);
389 }
390
391
GetLabelCount(void) const392 int NodePtr::GetLabelCount(void) const
393 {
394 if(f_node != 0) {
395 return f_node->GetLabelCount();
396 }
397
398 return 0;
399 }
400
401
GetLabel(int index) const402 NodePtr& NodePtr::GetLabel(int index) const
403 {
404 AS_ASSERT(f_node != 0);
405 return f_node->GetLabel(index);
406 }
407
408
FindLabel(const String & name) const409 NodePtr& NodePtr::FindLabel(const String& name) const
410 {
411 AS_ASSERT(f_node != 0);
412 return f_node->FindLabel(name);
413 }
414
415
Display(FILE * out,int indent,NodePtr * parent,char c) const416 void NodePtr::Display(FILE *out, int indent, NodePtr *parent, char c) const
417 {
418 AS_ASSERT(f_node != 0);
419 if(parent == 0) {
420 parent = &f_node->GetParent();
421 }
422 f_node->Display(out, indent, parent, c);
423 }
424
425
DisplayPtr(FILE * out) const426 void NodePtr::DisplayPtr(FILE *out) const
427 {
428 fprintf(out, "%08lX", (long) f_node);
429 }
430
431
432
433
434 struct operator_to_string_t
435 {
436 node_t f_node;
437 const char * f_name;
438 };
439
440 int g_file_line = __LINE__;
441 static const operator_to_string_t g_operator_to_string[] =
442 {
443 // single character -- sorted in ASCII
444 { NODE_LOGICAL_NOT, "!" },
445 { NODE_MODULO, "%" },
446 { NODE_BITWISE_AND, "&" },
447 { NODE_MULTIPLY, "*" },
448 { NODE_ADD, "+" },
449 { NODE_SUBTRACT, "-" },
450 { NODE_DIVIDE, "/" },
451 { NODE_LESS, "<" },
452 { NODE_ASSIGNMENT, "=" },
453 { NODE_GREATER, ">" },
454 { NODE_BITWISE_XOR, "^" },
455 { NODE_BITWISE_OR, "|" },
456 { NODE_BITWISE_NOT, "~" },
457
458 // two or more characters transformed to an enum only
459 { NODE_ASSIGNMENT_ADD, "+=" },
460 { NODE_ASSIGNMENT_BITWISE_AND, "&=" },
461 { NODE_ASSIGNMENT_BITWISE_OR, "|=" },
462 { NODE_ASSIGNMENT_BITWISE_XOR, "^=" },
463 { NODE_ASSIGNMENT_DIVIDE, "/=" },
464 { NODE_ASSIGNMENT_LOGICAL_AND, "&&=" },
465 { NODE_ASSIGNMENT_LOGICAL_OR, "||=" },
466 { NODE_ASSIGNMENT_LOGICAL_XOR, "^^=" },
467 { NODE_ASSIGNMENT_MAXIMUM, "?>=" },
468 { NODE_ASSIGNMENT_MINIMUM, "?<=" },
469 { NODE_ASSIGNMENT_MODULO, "%=" },
470 { NODE_ASSIGNMENT_MULTIPLY, "*=" },
471 { NODE_ASSIGNMENT_POWER, "**=" },
472 { NODE_ASSIGNMENT_ROTATE_LEFT, "!<=" },
473 { NODE_ASSIGNMENT_ROTATE_RIGHT, "!>=" },
474 { NODE_ASSIGNMENT_SHIFT_LEFT, "<<=" },
475 { NODE_ASSIGNMENT_SHIFT_RIGHT, ">>=" },
476 { NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED, ">>>=" },
477 { NODE_ASSIGNMENT_SUBTRACT, "-=" },
478 { NODE_CALL, "()" },
479 { NODE_DECREMENT, "--" },
480 { NODE_EQUAL, "==" },
481 { NODE_GREATER_EQUAL, ">=" },
482 { NODE_INCREMENT, "++" },
483 { NODE_LESS_EQUAL, "<=" },
484 { NODE_LOGICAL_AND, "&&" },
485 { NODE_LOGICAL_OR, "||" },
486 { NODE_LOGICAL_XOR, "^^" },
487 { NODE_MATCH, "~=" },
488 { NODE_MAXIMUM, "?>" },
489 { NODE_MINIMUM, "?<" },
490 { NODE_NOT_EQUAL, "!=" },
491 { NODE_POST_DECREMENT, "--" },
492 { NODE_POST_INCREMENT, "++" },
493 { NODE_POWER, "**" },
494 { NODE_ROTATE_LEFT, "!<" },
495 { NODE_ROTATE_RIGHT, "!>" },
496 { NODE_SHIFT_LEFT, "<<" },
497 { NODE_SHIFT_RIGHT, ">>" },
498 { NODE_SHIFT_RIGHT_UNSIGNED, ">>>" },
499 { NODE_STRICTLY_EQUAL, "===" },
500 { NODE_STRICTLY_NOT_EQUAL, "!==" }
501
502 // the following doesn't make it in user redefinable operators yet
503 //{ NODE_CONDITIONAL, "" },
504 //{ NODE_DELETE, "" },
505 //{ NODE_FOR_IN, "" },
506 //{ NODE_IN, "" },
507 //{ NODE_INSTANCEOF, "" },
508 //{ NODE_IS, "" },
509 //{ NODE_LIST, "" },
510 //{ NODE_NEW, "" },
511 //{ NODE_RANGE, "" },
512 //{ NODE_SCOPE, "" },
513 };
514
515 #define operator_to_string_count (sizeof(g_operator_to_string) / sizeof(g_operator_to_string[0]))
516
517
OperatorToString(void)518 const char *NodePtr::OperatorToString(void)
519 {
520 #if defined(_DEBUG) || defined(DEBUG)
521 // make sure that the nodes are properly sorted
522 static bool checked = false;
523 if(!checked) {
524 // check only once
525 checked = true;
526 for(unsigned int idx = 1; idx < operator_to_string_count; ++idx) {
527 if(g_operator_to_string[idx].f_node <= g_operator_to_string[idx - 1].f_node) {
528 fprintf(stderr, "INTERNAL ERROR at offset %d (line ~#%d, node %d vs. %d): the g_operator_to_string table isn't sorted properly. We can't binary search it.\n",
529 idx, idx + g_file_line + 3,
530 g_operator_to_string[idx].f_node,
531 g_operator_to_string[idx - 1].f_node);
532 AS_ASSERT(0);
533 }
534 }
535 }
536 #endif
537 int i, j, p, r, op;
538
539 Data& data = GetData();
540 op = data.f_type;
541
542 i = 0;
543 j = operator_to_string_count;
544 while(i < j) {
545 p = (j - i) / 2 + i;
546 r = g_operator_to_string[p].f_node - op;
547 if(r == 0) {
548 return g_operator_to_string[p].f_name;
549 }
550 if(r < 0) {
551 i = p + 1;
552 }
553 else {
554 j = p;
555 }
556 }
557
558 return 0;
559 }
560
561
562
StringToOperator(void)563 node_t NodePtr::StringToOperator(void)
564 {
565 const operator_to_string_t *lst;
566 int idx;
567
568 Data& data = GetData();
569
570 lst = g_operator_to_string;
571 idx = operator_to_string_count;
572 while(idx > 0) {
573 idx--;
574 if(data.f_str == lst->f_name) {
575 return lst->f_node;
576 }
577 }
578
579 return NODE_UNKNOWN;
580 }
581
582
583
584
585
586
587 /**********************************************************************/
588 /**********************************************************************/
589 /*** NODE ***********************************************************/
590 /**********************************************************************/
591 /**********************************************************************/
592
Node(node_t type)593 Node::Node(node_t type)
594 {
595 Init();
596 f_data.f_type = type;
597 }
598
599
Node(const Node & source,const Node & parent)600 Node::Node(const Node& source, const Node& parent)
601 {
602 #if defined(_DEBUG) || defined(DEBUG)
603 switch(source.f_data.f_type) {
604 case NODE_STRING:
605 case NODE_INT64:
606 case NODE_FLOAT64:
607 case NODE_TRUE:
608 case NODE_FALSE:
609 case NODE_NULL:
610 case NODE_UNDEFINED:
611 case NODE_REGULAR_EXPRESSION:
612 break;
613
614 default:
615 // ERROR: only constants can be cloned at this
616 // time (otherwise we'd need to clone all the
617 // children node too!!!)
618 AS_ASSERT(0);
619 break;
620
621 }
622 #endif
623
624 Init();
625
626 f_page = source.f_page;
627 f_page_line = source.f_page_line;
628 f_paragraph = source.f_paragraph;
629 f_line = source.f_line;
630 f_filename = source.f_filename;
631 f_data = source.f_data;
632 f_parent.SetNode(&const_cast<Node&>(parent));
633 for(int idx = 0; idx < NodePtr::LINK_max; ++idx) {
634 f_link[idx] = source.f_link[idx];
635 }
636
637 // constants should not have variables nor labels
638 }
639
640
~Node()641 Node::~Node()
642 {
643 delete [] f_children;
644 }
645
646
Init(void)647 void Node::Init(void)
648 {
649 f_refcount = 1;
650 f_lock = 0;
651 f_page = 0;
652 f_page_line = 0;
653 f_paragraph = 0;
654 f_line = 0;
655 //f_filename -- auto-init
656 //f_data -- auto-init
657 f_attrs = 0;
658 //f_parent -- auto-init
659 f_offset = 0x7FFFFFFF;
660 f_count = 0;
661 f_max = 0;
662 f_children = 0;
663 //f_link[] -- auto-init
664 f_var_count = 0;
665 f_var_max = 0;
666 f_variables = 0;
667 f_label_count = 0;
668 f_label_max = 0;
669 f_labels = 0;
670 }
671
672
AddRef(void)673 void Node::AddRef(void)
674 {
675 ++f_refcount;
676 }
677
678
Release(void)679 void Node::Release(void)
680 {
681 --f_refcount;
682 if(f_refcount == 0) {
683 delete this;
684 }
685 }
686
687
SetInputInfo(const Input * input)688 void Node::SetInputInfo(const Input *input)
689 {
690 if(input == 0) {
691 return;
692 }
693
694 // copy the input info so we can generate an error on
695 // any node at a later time (especially in the compiler)
696 f_page = input->Page();
697 f_page_line = input->PageLine();
698 f_paragraph = input->Paragraph();
699 f_line = input->Line();
700 f_filename = input->GetFilename();
701 }
702
703
CopyInputInfo(const Node * node)704 void Node::CopyInputInfo(const Node *node)
705 {
706 f_page = node->f_page;
707 f_page_line = node->f_page_line;
708 f_paragraph = node->f_paragraph;
709 f_line = node->f_line;
710 f_filename = node->f_filename;
711 }
712
713
ReplaceWith(Node * node)714 void Node::ReplaceWith(Node *node)
715 {
716 AS_ASSERT(f_lock == 0); // this should be okay?
717 AS_ASSERT(!node->f_parent.HasNode());
718
719 node->f_parent = f_parent;
720 f_parent.ClearNode();
721 }
722
723
DeleteChild(int index)724 void Node::DeleteChild(int index)
725 {
726 AS_ASSERT(f_lock == 0);
727 AS_ASSERT(index < f_count);
728
729 f_children[index].SetParent(0);
730
731 --f_count;
732 while(index < f_count) {
733 f_children[index] = f_children[index + 1];
734 index++;
735 }
736 f_children[f_count].ClearNode();
737 }
738
739
AddChild(NodePtr & child)740 void Node::AddChild(NodePtr& child)
741 {
742 AS_ASSERT(f_lock == 0);
743
744 if(f_max == 0) {
745 // for most parents, 3 children is more than enough
746 // (left hand, right hand and at times center)
747 f_max = 3;
748 f_children = new NodePtr[3];
749 }
750 if(f_count >= f_max) {
751 // for lists, the number of children can vary widely
752 f_max += 10;
753 NodePtr *extra = new NodePtr[f_max];
754 for(int i = 0; i < f_count; ++i) {
755 extra[i] = f_children[i];
756 }
757 delete [] f_children;
758 f_children = extra;
759 }
760
761 f_children[f_count] = child;
762 child.SetParent(this);
763 ++f_count;
764 }
765
766
InsertChild(int index,NodePtr & child)767 void Node::InsertChild(int index, NodePtr& child)
768 {
769 AS_ASSERT(f_lock == 0);
770 AS_ASSERT(index <= f_count);
771
772 if(f_max == 0) {
773 // for most parents, 3 children is more than enough
774 // (left hand, right hand and at times center)
775 f_max = 3;
776 f_children = new NodePtr[3];
777 }
778 if(f_count >= f_max) {
779 // for lists, the number of children can vary widely
780 f_max += 10;
781 NodePtr *extra = new NodePtr[f_max];
782 for(int i = 0; i < f_count; ++i) {
783 extra[i] = f_children[i];
784 }
785 delete [] f_children;
786 f_children = extra;
787 }
788
789 for(int i = f_count; i > index; --i) {
790 f_children[i] = f_children[i - 1];
791 }
792
793 f_children[index] = child;
794 child.SetParent(this);
795 ++f_count;
796 }
797
798
SetChild(int index,NodePtr & child)799 void Node::SetChild(int index, NodePtr& child)
800 {
801 AS_ASSERT(f_lock == 0); // this isn't so bad...
802 AS_ASSERT(index < f_max);
803 if(f_children[index].HasNode()) {
804 f_children[index].SetParent(0);
805 }
806 f_children[index] = child;
807 child.SetParent(this);
808 }
809
810
GetChild(int index) const811 NodePtr& Node::GetChild(int index) const
812 {
813 AS_ASSERT(index < f_max);
814 return f_children[index];
815 }
816
817
HasSideEffects(void) const818 bool Node::HasSideEffects(void) const
819 {
820 //
821 // Well... I'm wondering if we can really
822 // trust this current version.
823 //
824 // Problem I:
825 // some identifiers can be getters and
826 // they can have side effects; though
827 // a getter should be considered constant
828 // toward the object being read and thus
829 // it should be fine in 99% of cases
830 // [imagine a serial number generator...]
831 //
832 // Problem II:
833 // some operators may not have been
834 // compiled yet and they could have
835 // side effects too; now this is much
836 // less likely a problem because then
837 // the programmer is most certainly
838 // creating a really weird program
839 // with all sorts of side effects that
840 // he wants no one else to know about,
841 // etc. etc. etc.
842 //
843 // Problem III:
844 // Note that we don't memorize whether
845 // a node has side effects because its
846 // children may change and then the side
847 // effects may disappear
848 //
849
850 switch(f_data.f_type) {
851 case NODE_ASSIGNMENT:
852 case NODE_ASSIGNMENT_ADD:
853 case NODE_ASSIGNMENT_BITWISE_AND:
854 case NODE_ASSIGNMENT_BITWISE_OR:
855 case NODE_ASSIGNMENT_BITWISE_XOR:
856 case NODE_ASSIGNMENT_DIVIDE:
857 case NODE_ASSIGNMENT_LOGICAL_AND:
858 case NODE_ASSIGNMENT_LOGICAL_OR:
859 case NODE_ASSIGNMENT_LOGICAL_XOR:
860 case NODE_ASSIGNMENT_MAXIMUM:
861 case NODE_ASSIGNMENT_MINIMUM:
862 case NODE_ASSIGNMENT_MODULO:
863 case NODE_ASSIGNMENT_MULTIPLY:
864 case NODE_ASSIGNMENT_POWER:
865 case NODE_ASSIGNMENT_ROTATE_LEFT:
866 case NODE_ASSIGNMENT_ROTATE_RIGHT:
867 case NODE_ASSIGNMENT_SHIFT_LEFT:
868 case NODE_ASSIGNMENT_SHIFT_RIGHT:
869 case NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
870 case NODE_ASSIGNMENT_SUBTRACT:
871 case NODE_CALL:
872 case NODE_DECREMENT:
873 case NODE_DELETE:
874 case NODE_INCREMENT:
875 case NODE_NEW:
876 case NODE_POST_DECREMENT:
877 case NODE_POST_INCREMENT:
878 return true;
879
880 //case NODE_IDENTIFIER:
881 //
882 // TODO: Test whether this is a reference to a getter
883 // function (needs to be compiled already...)
884 //
885 // break;
886
887 default:
888 break;
889
890 }
891
892 for(int idx = 0; idx < f_count; ++idx) {
893 if(f_children[idx].HasNode()
894 && f_children[idx].HasSideEffects()) {
895 return true;
896 }
897 }
898
899 return false;
900 }
901
902
903
AddVariable(NodePtr & variable)904 void Node::AddVariable(NodePtr& variable)
905 {
906 #if defined(_DEBUG) || defined(DEBUG)
907 Data& data = variable.GetData();
908 AS_ASSERT(data.f_type == NODE_VARIABLE);
909 #endif
910 if(f_var_max == 0) {
911 f_var_max = 10;
912 f_variables = new NodePtr[10];
913 }
914 if(f_var_count >= f_var_max) {
915 f_var_max += 10;
916 NodePtr *extra = new NodePtr[f_var_max];
917 for(int i = 0; i < f_var_count; ++i) {
918 extra[i] = f_variables[i];
919 }
920 delete [] f_variables;
921 f_variables = extra;
922 }
923
924 f_variables[f_var_count] = variable;
925 ++f_var_count;
926 }
927
928
929
930
GetVariable(int index) const931 NodePtr& Node::GetVariable(int index) const
932 {
933 AS_ASSERT(index < f_var_max);
934 return f_variables[index];
935 }
936
937
938
939
AddLabel(NodePtr & label)940 void Node::AddLabel(NodePtr& label)
941 {
942 #if defined(_DEBUG) || defined(DEBUG)
943 Data& data = label.GetData();
944 AS_ASSERT(data.f_type == NODE_LABEL);
945 #endif
946 if(f_label_max == 0) {
947 f_label_max = 5;
948 f_labels = new NodePtr[5];
949 }
950 if(f_label_count >= f_label_max) {
951 f_label_max += 5;
952 NodePtr *extra = new NodePtr[f_label_max];
953 for(int i = 0; i < f_label_count; ++i) {
954 extra[i] = f_labels[i];
955 }
956 delete [] f_labels;
957 f_labels = extra;
958 }
959
960 // we should sort those
961 f_labels[f_label_count] = label;
962 ++f_label_count;
963 }
964
965
966
967
GetLabel(int index) const968 NodePtr& Node::GetLabel(int index) const
969 {
970 AS_ASSERT(index < f_label_max);
971 return f_labels[index];
972 }
973
974
975
FindLabel(const String & name) const976 NodePtr& Node::FindLabel(const String& name) const
977 {
978 static NodePtr not_found;
979
980 AS_ASSERT(!not_found.HasNode());
981
982 // once sorted, convert to a binary search
983 for(int idx = 0; idx < f_label_count; ++idx) {
984 Data& data = f_labels[idx].GetData();
985 if(data.f_str == name) {
986 return f_labels[idx];
987 }
988 }
989
990 return not_found;
991 }
992
993
994
995
996
997
998
999
1000
1001
1002
1003 /**********************************************************************/
1004 /**********************************************************************/
1005 /*** NODE DISPLAY ***************************************************/
1006 /**********************************************************************/
1007 /**********************************************************************/
1008
1009 /* This function is mainly for debug purposes.
1010 * It is used by the asc tool to display the final
1011 * tree.
1012 */
Display(FILE * out,int indent,NodePtr * parent,char c) const1013 void Node::Display(FILE *out, int indent, NodePtr *parent, char c) const
1014 {
1015 fprintf(out, "%08lX:%02d%c %*s", (long) this, indent, c, indent, "");
1016 if(parent != 0 && !f_parent.SameAs(*parent)) {
1017 fprintf(out, ">>WRONG PARENT: ");
1018 f_parent.DisplayPtr(out);
1019 fprintf(out, "<< ");
1020 }
1021 f_data.Display(out);
1022 bool first = true;
1023 for(int lnk = 0; lnk < NodePtr::LINK_max; ++lnk) {
1024 if(f_link[lnk].HasNode()) {
1025 if(first) {
1026 first = false;
1027 fprintf(out, " Lnk:");
1028 }
1029 fprintf(out, " [%d]=", lnk);
1030 f_link[lnk].DisplayPtr(out);
1031 }
1032 }
1033 unsigned long attrs = GetAttrs();
1034 if(attrs != 0) {
1035 fprintf(out, " Attrs:");
1036 if((attrs & NODE_ATTR_PUBLIC) != 0) {
1037 attrs &= ~NODE_ATTR_PUBLIC;
1038 fprintf(out, " PUBLIC");
1039 }
1040 if((attrs & NODE_ATTR_PRIVATE) != 0) {
1041 attrs &= ~NODE_ATTR_PRIVATE;
1042 fprintf(out, " PRIVATE");
1043 }
1044 if((attrs & NODE_ATTR_PROTECTED) != 0) {
1045 attrs &= ~NODE_ATTR_PROTECTED;
1046 fprintf(out, " PROTECTED");
1047 }
1048 if((attrs & NODE_ATTR_STATIC) != 0) {
1049 attrs &= ~NODE_ATTR_STATIC;
1050 fprintf(out, " STATIC");
1051 }
1052 if((attrs & NODE_ATTR_ABSTRACT) != 0) {
1053 attrs &= ~NODE_ATTR_ABSTRACT;
1054 fprintf(out, " ABSTRACT");
1055 }
1056 if((attrs & NODE_ATTR_VIRTUAL) != 0) {
1057 attrs &= ~NODE_ATTR_VIRTUAL;
1058 fprintf(out, " VIRTUAL");
1059 }
1060 if((attrs & NODE_ATTR_INTERNAL) != 0) {
1061 attrs &= ~NODE_ATTR_INTERNAL;
1062 fprintf(out, " INTERNAL");
1063 }
1064 if((attrs & NODE_ATTR_INTRINSIC) != 0) {
1065 attrs &= ~NODE_ATTR_INTRINSIC;
1066 fprintf(out, " INTRINSIC");
1067 }
1068 if((attrs & NODE_ATTR_CONSTRUCTOR) != 0) {
1069 attrs &= ~NODE_ATTR_CONSTRUCTOR;
1070 fprintf(out, " CONSTRUCTOR");
1071 }
1072 if((attrs & NODE_ATTR_FINAL) != 0) {
1073 attrs &= ~NODE_ATTR_FINAL;
1074 fprintf(out, " FINAL");
1075 }
1076 if((attrs & NODE_ATTR_ENUMERABLE) != 0) {
1077 attrs &= ~NODE_ATTR_ENUMERABLE;
1078 fprintf(out, " ENUMERABLE");
1079 }
1080 if((attrs & NODE_ATTR_TRUE) != 0) {
1081 attrs &= ~NODE_ATTR_TRUE;
1082 fprintf(out, " TRUE");
1083 }
1084 if((attrs & NODE_ATTR_FALSE) != 0) {
1085 attrs &= ~NODE_ATTR_FALSE;
1086 fprintf(out, " FALSE");
1087 }
1088 if((attrs & NODE_ATTR_UNUSED) != 0) {
1089 attrs &= ~NODE_ATTR_UNUSED;
1090 fprintf(out, " UNUSED");
1091 }
1092 if((attrs & NODE_ATTR_DYNAMIC) != 0) {
1093 attrs &= ~NODE_ATTR_DYNAMIC;
1094 fprintf(out, " DYNAMIC");
1095 }
1096 if((attrs & NODE_ATTR_FOREACH) != 0) {
1097 attrs &= ~NODE_ATTR_FOREACH;
1098 fprintf(out, " FOREACH");
1099 }
1100 if((attrs & NODE_ATTR_NOBREAK) != 0) {
1101 attrs &= ~NODE_ATTR_NOBREAK;
1102 fprintf(out, " NOBREAK");
1103 }
1104 if((attrs & NODE_ATTR_AUTOBREAK) != 0) {
1105 attrs &= ~NODE_ATTR_AUTOBREAK;
1106 fprintf(out, " AUTOBREAK");
1107 }
1108 if((attrs & NODE_ATTR_DEFINED) != 0) {
1109 attrs &= ~NODE_ATTR_DEFINED;
1110 fprintf(out, " DEFINED");
1111 }
1112
1113 if(attrs != 0) {
1114 fprintf(out, " <unamed flags: %08lX>", attrs);
1115 }
1116 }
1117
1118 #if 1
1119 // to be very verbose... print also the filename and line info
1120 char n[256];
1121 size_t sz = sizeof(n);
1122 f_filename.ToUTF8(n, sz);
1123 fprintf(out, " %s:%ld", n, f_line);
1124 #endif
1125
1126 fprintf(out, "\n");
1127 NodePtr me;
1128 me.SetNode(this);
1129 for(int idx = 0; idx < f_count; ++idx) {
1130 f_children[idx].Display(out, indent + 1, &me, '-');
1131 }
1132 for(int idx = 0; idx < f_var_count; ++idx) {
1133 f_variables[idx].Display(out, indent + 1, 0, '=');
1134 }
1135 for(int idx = 0; idx < f_label_count; ++idx) {
1136 f_labels[idx].Display(out, indent + 1, 0, ':');
1137 }
1138 }
1139
1140
1141
1142
1143
1144
1145
1146 }; // namespace as
1147 }; // namespace sswf
1148