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