1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2013 Academy of Motion Picture Arts and Sciences
3 // ("A.M.P.A.S."). Portions contributed by others as indicated.
4 // All rights reserved.
5 //
6 // A worldwide, royalty-free, non-exclusive right to copy, modify, create
7 // derivatives, and use, in source and binary forms, is hereby granted,
8 // subject to acceptance of this license. Performance of any of the
9 // aforementioned acts indicates acceptance to be bound by the following
10 // terms and conditions:
11 //
12 //  * Copies of source code, in whole or in part, must retain the
13 //    above copyright notice, this list of conditions and the
14 //    Disclaimer of Warranty.
15 //
16 //  * Use in binary form must retain the above copyright notice,
17 //    this list of conditions and the Disclaimer of Warranty in the
18 //    documentation and/or other materials provided with the distribution.
19 //
20 //  * Nothing in this license shall be deemed to grant any rights to
21 //    trademarks, copyrights, patents, trade secrets or any other
22 //    intellectual property of A.M.P.A.S. or any contributors, except
23 //    as expressly stated herein.
24 //
25 //  * Neither the name "A.M.P.A.S." nor the name of any other
26 //    contributors to this software may be used to endorse or promote
27 //    products derivative of or based on this software without express
28 //    prior written permission of A.M.P.A.S. or the contributors, as
29 //    appropriate.
30 //
31 // This license shall be construed pursuant to the laws of the State of
32 // California, and any disputes related thereto shall be subject to the
33 // jurisdiction of the courts therein.
34 //
35 // Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND
36 // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
37 // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
38 // FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO
39 // EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE
40 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY,
41 // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
46 // THE POSSIBILITY OF SUCH DAMAGE.
47 //
48 // WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY
49 // SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER
50 // RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY
51 // COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER
52 // THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED.
53 ///////////////////////////////////////////////////////////////////////////
54 
55 
56 //-----------------------------------------------------------------------------
57 //
58 //	The syntax tree for the color transformation language.
59 //
60 //-----------------------------------------------------------------------------
61 
62 #include <CtlSyntaxTree.h>
63 #include <CtlSymbolTable.h>
64 #include <CtlMessage.h>
65 #include <CtlLContext.h>
66 #include <iostream>
67 #include <iomanip>
68 #include <cassert>
69 #include <CtlErrors.h>
70 
71 using namespace std;
72 
73 namespace Ctl {
74 
75 
SyntaxNode(int lineNumber)76 SyntaxNode::SyntaxNode (int lineNumber):
77     lineNumber (lineNumber)
78 {
79     // empty
80 }
81 
82 
~SyntaxNode()83 SyntaxNode::~SyntaxNode ()
84 {
85     // empty
86 }
87 
88 
89 void
printTree() const90 SyntaxNode::printTree () const
91 {
92     print (0);
93 }
94 
95 
ModuleNode(int lineNumber,const StatementNodePtr & constants,const FunctionNodePtr & functions)96 ModuleNode::ModuleNode
97     (int lineNumber,
98      const StatementNodePtr &constants,
99      const FunctionNodePtr &functions)
100 :
101     SyntaxNode (lineNumber),
102     constants (constants),
103     functions (functions)
104 {
105     // empty
106 }
107 
108 
109 void
print(int indent) const110 ModuleNode::print (int indent) const
111 {
112     cout << setw (indent) << "" << lineNumber << " module " << endl;
113 
114     if (constants)
115 	constants->print (indent + 1);
116 
117     if (functions)
118 	functions->print (indent + 1);
119 }
120 
121 
FunctionNode(int lineNumber,const std::string & name,const SymbolInfoPtr & info,const StatementNodePtr & body)122 FunctionNode::FunctionNode
123     (int lineNumber,
124      const std::string &name,
125      const SymbolInfoPtr &info,
126      const StatementNodePtr &body)
127 :
128     SyntaxNode (lineNumber),
129     name (name),
130     info (info),
131     body (body),
132     next (0)
133 {
134     // empty
135 }
136 
137 
138 void
print(int indent) const139 FunctionNode::print (int indent) const
140 {
141     cout << setw (indent) << "" << lineNumber << " function " << name << endl;
142 
143     if (info)
144 	info->print (indent + 1);
145 
146     if (body)
147 	body->print (indent + 1);
148 
149     if (next)
150 	next->print (indent);
151 }
152 
153 
StatementNode(int lineNumber)154 StatementNode::StatementNode (int lineNumber):
155     SyntaxNode (lineNumber),
156     next (0)
157 {
158     // empty
159 }
160 
161 
LinearStatementNode(int lineNumber)162 LinearStatementNode::LinearStatementNode (int lineNumber):
163     StatementNode (lineNumber)
164 {
165     // empty
166 }
167 
168 
169 bool
pathEndsWithReturn() const170 LinearStatementNode::pathEndsWithReturn () const
171 {
172     return next && next->pathEndsWithReturn();
173 }
174 
175 
VariableNode(int lineNumber,const std::string & name,const SymbolInfoPtr & info,const ExprNodePtr & initialValue,bool assignInitialValue)176 VariableNode::VariableNode
177     (int lineNumber,
178      const std::string &name,
179      const SymbolInfoPtr &info,
180      const ExprNodePtr &initialValue,
181      bool assignInitialValue)
182 :
183     LinearStatementNode (lineNumber),
184     name (name),
185     info (info),
186     initialValue (initialValue),
187     assignInitialValue (assignInitialValue)
188 {
189     // empty
190 }
191 
192 
193 void
print(int indent) const194 VariableNode::print (int indent) const
195 {
196     cout << setw (indent) << "" << lineNumber << " variable " << name << endl;
197 
198     if (info)
199 	info->print (indent + 1);
200 
201     if (initialValue && !(info && info->value()))
202     {
203 	cout << setw (indent + 1) << "" << "initial value" << endl;
204 	initialValue->print (indent + 2);
205 	cout << setw (indent + 1) << "" << "assign initial value" << endl;
206 	cout << setw (indent + 2) << "" << assignInitialValue << endl;
207     }
208 
209     if (next)
210 	next->print (indent);
211 }
212 
213 
AssignmentNode(int lineNumber,const ExprNodePtr & lhs,const ExprNodePtr & rhs)214 AssignmentNode::AssignmentNode
215     (int lineNumber,
216      const ExprNodePtr &lhs,
217      const ExprNodePtr &rhs)
218 :
219     LinearStatementNode (lineNumber),
220     lhs (lhs),
221     rhs (rhs)
222 {
223     // empty
224 }
225 
226 
227 void
print(int indent) const228 AssignmentNode::print (int indent) const
229 {
230     cout << setw (indent) << "" << lineNumber << " assignment" << endl;
231 
232     if (lhs)
233 	lhs->print (indent + 1);
234 
235     if (rhs)
236 	rhs->print (indent + 1);
237 
238     if (next)
239 	next->print (indent);
240 }
241 
242 
ExprStatementNode(int lineNumber,const ExprNodePtr & expr)243 ExprStatementNode::ExprStatementNode
244     (int lineNumber,
245      const ExprNodePtr &expr)
246 :
247     LinearStatementNode (lineNumber),
248     expr (expr)
249 {
250     // empty
251 }
252 
253 
254 void
print(int indent) const255 ExprStatementNode::print (int indent) const
256 {
257     cout << setw (indent) << "" << lineNumber << " expr statement" << endl;
258 
259     if (expr)
260 	expr->print (indent + 1);
261 
262     if (next)
263 	next->print (indent);
264 }
265 
266 
IfNode(int lineNumber,const ExprNodePtr & condition,const StatementNodePtr & truePath,const StatementNodePtr & falsePath)267 IfNode::IfNode
268     (int lineNumber,
269      const ExprNodePtr &condition,
270      const StatementNodePtr &truePath,
271      const StatementNodePtr &falsePath)
272 :
273     StatementNode (lineNumber),
274     condition (condition),
275     truePath (truePath),
276     falsePath (falsePath)
277 {
278     // empty
279 }
280 
281 
282 void
print(int indent) const283 IfNode::print (int indent) const
284 {
285     cout << setw (indent) << "" << lineNumber << " if" << endl;
286 
287     if (condition)
288     {
289 	cout << setw (indent + 1) << "" << "condition" << endl;
290 	condition->print (indent + 2);
291     }
292 
293     if (truePath)
294     {
295 	cout << setw (indent + 1) << "" << "true path" << endl;
296 	truePath->print (indent + 2);
297     }
298 
299     if (falsePath)
300     {
301 	cout << setw (indent + 1) << "" << "false path" << endl;
302 	falsePath->print (indent + 2);
303     }
304 
305     if (next)
306 	next->print (indent);
307 }
308 
309 
310 bool
pathEndsWithReturn() const311 IfNode::pathEndsWithReturn () const
312 {
313     return (truePath  && truePath->pathEndsWithReturn() &&
314 	    falsePath && falsePath->pathEndsWithReturn()) ||
315 	   (next && next->pathEndsWithReturn());
316 }
317 
318 
ReturnNode(int lineNumber,const SymbolInfoPtr & info,const ExprNodePtr & returnedValue)319 ReturnNode::ReturnNode
320     (int lineNumber,
321      const SymbolInfoPtr &info,
322      const ExprNodePtr &returnedValue)
323 :
324     StatementNode (lineNumber),
325     info (info),
326     returnedValue (returnedValue)
327 {
328     // empty
329 }
330 
331 
332 void
print(int indent) const333 ReturnNode::print (int indent) const
334 {
335     cout << setw (indent) << "" << lineNumber << " return" << endl;
336 
337     if (info)
338 	info->print (indent + 1);
339 
340     if (returnedValue)
341 	returnedValue->print (indent + 1);
342 
343     if (next)
344 	next->print (indent);
345 }
346 
347 
348 bool
pathEndsWithReturn() const349 ReturnNode::pathEndsWithReturn () const
350 {
351     return true;
352 }
353 
354 
WhileNode(int lineNumber,const ExprNodePtr & condition,const StatementNodePtr & loopBody)355 WhileNode::WhileNode
356     (int lineNumber,
357      const ExprNodePtr &condition,
358      const StatementNodePtr &loopBody)
359 :
360     StatementNode (lineNumber),
361     condition (condition),
362     loopBody (loopBody)
363 {
364     // empty
365 }
366 
367 
368 void
print(int indent) const369 WhileNode::print (int indent) const
370 {
371     cout << setw (indent) << "" << lineNumber << " while" << endl;
372 
373     if (condition)
374     {
375 	cout << setw (indent + 1) << "" << "condition" << endl;
376 	condition->print (indent + 2);
377     }
378 
379     if (loopBody)
380     {
381 	cout << setw (indent + 1) << "" << "loop body" << endl;
382 	loopBody->print (indent + 2);
383     }
384 
385     if (next)
386 	next->print (indent);
387 }
388 
389 
390 bool
pathEndsWithReturn() const391 WhileNode::pathEndsWithReturn () const
392 {
393     BoolLiteralNodePtr constCondition = condition.cast<BoolLiteralNode>();
394 
395     if (constCondition && constCondition->value)
396     {
397 	//
398 	// The loop condition has already been evaluated, and it is true.
399 	// The only way to get out of the loop is via a return statement.
400 	// Code after the loop is unreachable.
401 	//
402 
403 	return true;
404     }
405     else
406     {
407 	//
408 	// The loop condition must be evaluated at run time.  Code after
409 	// the loop is reachable unless all paths through the loop body
410 	// end with a return statement.
411 	//
412 
413 	return (loopBody && loopBody->pathEndsWithReturn()) ||
414 	       (next && next->pathEndsWithReturn());
415     }
416 }
417 
418 
ExprNode(int lineNumber)419 ExprNode::ExprNode (int lineNumber):
420     SyntaxNode (lineNumber),
421     type (0)
422 {
423     // empty
424 }
425 
426 
BinaryOpNode(int lineNumber,Token op,const ExprNodePtr & leftOperand,const ExprNodePtr & rightOperand)427 BinaryOpNode::BinaryOpNode
428     (int lineNumber,
429      Token op,
430      const ExprNodePtr &leftOperand,
431      const ExprNodePtr &rightOperand)
432 :
433     ExprNode (lineNumber),
434     op (op),
435     leftOperand (leftOperand),
436     rightOperand (rightOperand),
437     operandType (0)
438 {
439     // empty
440 }
441 
442 
443 void
print(int indent) const444 BinaryOpNode::print (int indent) const
445 {
446     cout << setw (indent) << "" << lineNumber << " binary operator " <<
447 	    tokenAsString (op) << endl;
448 
449     if (type)
450 	type->print (indent + 1);
451     else
452 	cout << setw (indent + 1) << "" << "*** type unknown ***" << endl;
453 
454     if (leftOperand)
455 	leftOperand->print (indent + 1);
456 
457     if (rightOperand)
458 	rightOperand->print (indent + 1);
459 }
460 
461 
462 void
computeType(LContext & lcontext,const SymbolInfoPtr & initInfo)463 BinaryOpNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
464 {
465     if (!leftOperand || !rightOperand)
466 	return;
467 
468     leftOperand->computeType (lcontext, initInfo);
469     rightOperand->computeType (lcontext, initInfo);
470 
471     if (!leftOperand->type || !rightOperand->type)
472 	return;
473 
474     ArrayTypePtr arrayType = leftOperand->type.cast<ArrayType>();
475     StructTypePtr structType = leftOperand->type.cast<StructType>();
476 
477     if( arrayType || structType )
478     {
479 	MESSAGE_LE (lcontext, ERR_OP_TYPE, lineNumber,
480 	    "Invalid operand types for " << tokenAsString (op) << " "
481 	    "operator (" << leftOperand->type->asString() << " " <<
482 	    tokenAsString (op) << " " <<
483 	    rightOperand->type->asString() << ").");
484     }
485 
486     if (op == TK_AND || op == TK_OR)
487     {
488 	//
489 	// It must be possible to cast the operands to type bool,
490 	// and the operator produces a result of type bool.
491 	//
492 
493 	BoolTypePtr boolType = lcontext.newBoolType ();
494 
495 	if (boolType->canCastFrom (leftOperand->type) &&
496 	    boolType->canCastFrom (rightOperand->type))
497 	{
498 	    operandType = boolType;
499 	    type = boolType;
500 	    return;
501 	}
502     }
503     else if (op == TK_EQUAL || op == TK_GREATER || op == TK_GREATEREQUAL ||
504 	     op == TK_LESS || op == TK_LESSEQUAL || op == TK_NOTEQUAL)
505     {
506 	//
507 	// It must be possible to promote the operands to a common type.
508 	// The operator produces a result of type bool.
509 	//
510 
511 	BoolTypePtr boolType = lcontext.newBoolType ();
512 
513 	if (leftOperand->type->isSameTypeAs (rightOperand->type))
514 	{
515 	    operandType = leftOperand->type;
516 	    type = boolType;
517 	    return;
518 	}
519 	else if (leftOperand->type->canPromoteFrom (rightOperand->type))
520 	{
521 	    operandType = leftOperand->type;
522 	    type = boolType;
523 	    return;
524 	}
525 	else if (rightOperand->type->canPromoteFrom (leftOperand->type))
526 	{
527 	    operandType = rightOperand->type;
528 	    type = boolType;
529 	    return;
530 	}
531     }
532     else
533     {
534 	//
535 	// It must be possible to promote the operands to a common type.
536 	// The operator produces a result of this common type.
537 	//
538 
539 	if (leftOperand->type->isSameTypeAs (rightOperand->type))
540 	{
541 	    operandType = leftOperand->type;
542 	    type = operandType;
543 	    return;
544 	}
545 	else if (leftOperand->type->canPromoteFrom (rightOperand->type))
546 	{
547 	    operandType = leftOperand->type;
548 	    type = operandType;
549 	    return;
550 	}
551 	else if (rightOperand->type->canPromoteFrom (leftOperand->type))
552 	{
553 	    operandType = rightOperand->type;
554 	    type = operandType;
555 	    return;
556 	}
557     }
558 
559     MESSAGE_LE (lcontext, ERR_OP_TYPE, lineNumber,
560 	"Invalid operand types for " << tokenAsString (op) << " "
561 	"operator (" << leftOperand->type->asString() << " " <<
562 	tokenAsString (op) << " " <<
563 	rightOperand->type->asString() << ").");
564 }
565 
566 
567 ExprNodePtr
evaluate(LContext & lcontext)568 BinaryOpNode::evaluate (LContext &lcontext)
569 {
570     leftOperand = leftOperand->evaluate (lcontext);
571     rightOperand = rightOperand->evaluate (lcontext);
572 
573     if (!type || !operandType)
574 	return this;
575 
576     if (!operandType->isSameTypeAs (leftOperand->type))
577 	leftOperand = operandType->castValue (lcontext, leftOperand);
578 
579     if (!operandType->isSameTypeAs (rightOperand->type))
580 	rightOperand = operandType->castValue (lcontext, rightOperand);
581 
582     return operandType->evaluate (lcontext, this);
583 }
584 
585 
586 bool
isLvalue(const SymbolInfoPtr & initInfo) const587 BinaryOpNode::isLvalue (const SymbolInfoPtr &initInfo) const
588 {
589     return false;
590 }
591 
592 
UnaryOpNode(int lineNumber,Token op,const ExprNodePtr & operand)593 UnaryOpNode::UnaryOpNode
594     (int lineNumber,
595      Token op,
596      const ExprNodePtr &operand)
597 :
598     ExprNode (lineNumber),
599     op (op),
600     operand (operand)
601 {
602     // empty
603 }
604 
605 
606 void
print(int indent) const607 UnaryOpNode::print (int indent) const
608 {
609     cout << setw (indent) << "" << lineNumber << " unary operator " <<
610 	    tokenAsString (op) << endl;
611 
612     if (type)
613 	type->print (indent + 1);
614     else
615 	cout << setw (indent + 1) << "" << "*** type unknown ***" << endl;
616 
617     if (operand)
618 	operand->print (indent + 1);
619 }
620 
621 
622 void
computeType(LContext & lcontext,const SymbolInfoPtr & initInfo)623 UnaryOpNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
624 {
625     if (!operand)
626 	return;
627 
628     operand->computeType (lcontext, initInfo);
629 
630     if (!operand->type)
631 	return;
632 
633     if (op == TK_BITNOT)
634     {
635 	//
636 	// Operator ~ can only be applied to operands of type bool int, or
637 	// unsigned int.  The operator produces a result of the same type as
638 	// the operand.
639 	//
640 
641 	BoolTypePtr boolType = lcontext.newBoolType ();
642 
643 	if (boolType->isSameTypeAs (operand->type))
644 	{
645 	    type = boolType;
646 	    return;
647 	}
648 
649 	IntTypePtr intType = lcontext.newIntType ();
650 
651 	if (intType->isSameTypeAs (operand->type))
652 	{
653 	    type = intType;
654 	    return;
655 	}
656 
657 	UIntTypePtr uIntType = lcontext.newUIntType ();
658 
659 	if (uIntType->isSameTypeAs (operand->type))
660 	{
661 	    type = uIntType;
662 	    return;
663 	}
664     }
665     else if (op == TK_MINUS)
666     {
667 	//
668 	// Operator - can only be applied to operands of type int, unsigned
669 	// int, half or float.  The operator produces a result of the same
670 	// type as the operand, except for unsigned int where it produces a
671 	// result of type int.
672 	//
673 
674 	IntTypePtr intType = lcontext.newIntType ();
675 
676 	if (intType->isSameTypeAs (operand->type))
677 	{
678 	    type = intType;
679 	    return;
680 	}
681 
682 	UIntTypePtr uIntType = lcontext.newUIntType ();
683 
684 	if (uIntType->isSameTypeAs (operand->type))
685 	{
686 	    type = intType;  // not uIntType!
687 	    return;
688 	}
689 
690 	HalfTypePtr halfType = lcontext.newHalfType ();
691 
692 	if (halfType->isSameTypeAs (operand->type))
693 	{
694 	    type = halfType;
695 	    return;
696 	}
697 
698 	FloatTypePtr floatType = lcontext.newFloatType ();
699 
700 	if (floatType->isSameTypeAs (operand->type))
701 	{
702 	    type = floatType;
703 	    return;
704 	}
705     }
706     else if (op == TK_NOT)
707     {
708 	//
709 	// Operator ! can be applied to operands that can be converted
710 	// to type bool.  The operator produces a result of type bool.
711 	//
712 
713 	BoolTypePtr boolType = lcontext.newBoolType ();
714 
715 	if (boolType->canCastFrom (operand->type))
716 	{
717 	    type = boolType;
718 	    return;
719 	}
720     }
721 
722     MESSAGE_LE (lcontext, ERR_OP_TYPE, lineNumber,
723 	"Invalid operand type for " << tokenAsString (op) << " operator "
724 	"(" << tokenAsString (op) << operand->type->asString() << ").");
725 }
726 
727 
728 ExprNodePtr
evaluate(LContext & lcontext)729 UnaryOpNode::evaluate (LContext &lcontext)
730 {
731     operand = operand->evaluate (lcontext);
732 
733     if (!type)
734 	return this;
735 
736     if (!type->isSameTypeAs (operand->type))
737 	operand = type->castValue (lcontext, operand);
738 
739     return type->evaluate (lcontext, this);
740 }
741 
742 
743 bool
isLvalue(const SymbolInfoPtr & initInfo) const744 UnaryOpNode::isLvalue (const SymbolInfoPtr &initInfo) const
745 {
746     return false;
747 }
748 
749 
MemberNode(int lineNumber,const ExprNodePtr & obj,const std::string & member)750 MemberNode::MemberNode
751     (int lineNumber,
752      const ExprNodePtr &obj,
753      const std::string &member)
754 :
755     ExprNode (lineNumber),
756     obj (obj),
757     member (member),
758     offset (0)
759 {
760     // empty
761 }
762 
763 
764 void
print(int indent) const765 MemberNode::print (int indent) const
766 {
767     cout << setw (indent) << "" << lineNumber << " access of member "
768 	 << member << endl;
769 
770     if (type)
771 	type->print (indent + 1);
772     else
773 	cout << setw (indent + 1) << "" << "*** type unknown ***" << endl;
774 
775     if (obj)
776 	obj->print (indent + 1);
777 
778 }
779 
780 
781 void
computeType(LContext & lcontext,const SymbolInfoPtr & initInfo)782 MemberNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
783 {
784     obj->computeType (lcontext, initInfo);
785 
786     if (!obj->type)
787     {
788 	type = lcontext.newIntType();
789 	return;
790     }
791 
792     StructTypePtr structType = obj->type.cast<StructType>();
793 
794     if (!structType)
795     {
796 	MESSAGE_LE (lcontext, ERR_NON_STRUCT, lineNumber,
797 		    "Applied member access operator to non-struct "
798 		    "of type " << obj->type->asString() << ".");
799 
800 	type = lcontext.newIntType();
801 	return;
802     }
803 
804     //
805     // check that the member exists and gets its type
806     //
807 
808     for (MemberVectorConstIterator it = structType->members().begin();
809  	 it != structType->members().end();
810 	 it++)
811     {
812 	if (it->name == member)
813 	{
814 	    type = it->type;
815 	    offset = it->offset;
816 	    return;
817 	}
818     }
819 
820     if (!type)
821     {
822 	MESSAGE_LE (lcontext, ERR_MEMBER_ACCESS, lineNumber,
823 		    "Unable to find member \"" << member << "\".");
824 
825 	type = lcontext.newIntType();
826     }
827 }
828 
829 
830 ExprNodePtr
evaluate(LContext & lcontext)831 MemberNode::evaluate (LContext &lcontext)
832 {
833     obj = obj->evaluate(lcontext);
834     return this;
835 }
836 
837 
838 bool
isLvalue(const SymbolInfoPtr & initInfo) const839 MemberNode::isLvalue (const SymbolInfoPtr &initInfo) const
840 {
841     return obj && obj->isLvalue (initInfo);
842 }
843 
844 
SizeNode(int lineNumber,const ExprNodePtr & obj)845 SizeNode::SizeNode
846     (int lineNumber,
847      const ExprNodePtr &obj)
848 :
849     ExprNode (lineNumber),
850     obj (obj)
851 {
852     // empty
853 }
854 
855 
856 void
print(int indent) const857 SizeNode::print (int indent) const
858 {
859     cout << setw (indent) << "" << lineNumber << " array size of "
860 	 << endl;
861 
862     if (obj)
863 	obj->print (indent + 1);
864 }
865 
866 
867 void
computeType(LContext & lcontext,const SymbolInfoPtr & initInfo)868 SizeNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
869 {
870     obj->computeType (lcontext, initInfo);
871 
872     ArrayTypePtr arrayType = obj->type.cast<ArrayType>();
873 
874     if( !arrayType)
875     {
876 	string type = "unknown";
877 	if( obj && obj->type)
878 	    type = obj->type->asString();
879 	MESSAGE_LE (lcontext, ERR_NON_ARRAY, lineNumber,
880 		    "Applied size operator to non-array "
881 		    " of type " << type << ".");
882     }
883     type = lcontext.newIntType ();
884 }
885 
886 
887 ExprNodePtr
evaluate(LContext & lcontext)888 SizeNode::evaluate (LContext &lcontext)
889 {
890     obj = obj->evaluate(lcontext);
891     ArrayTypePtr arrayType = obj->type.cast<ArrayType>();
892     if( !arrayType)
893     {
894 	return lcontext.newIntLiteralNode (lineNumber, 1);
895     }
896     else if( arrayType->size() != 0 )
897     {
898 	return lcontext.newIntLiteralNode (lineNumber, arrayType->size());
899     }
900     return this;
901 }
902 
903 
904 bool
isLvalue(const SymbolInfoPtr & initInfo) const905 SizeNode::isLvalue (const SymbolInfoPtr &initInfo) const
906 {
907     return false;
908 }
909 
910 
911 
ArrayIndexNode(int lineNumber,const ExprNodePtr & array,const ExprNodePtr & index)912 ArrayIndexNode::ArrayIndexNode
913     (int lineNumber,
914      const ExprNodePtr &array,
915      const ExprNodePtr &index)
916 :
917     ExprNode (lineNumber),
918     array (array),
919     index (index)
920 {
921     // empty
922 }
923 
924 
925 void
print(int indent) const926 ArrayIndexNode::print (int indent) const
927 {
928     cout << setw (indent) << "" << lineNumber << " array index " << endl;
929 
930     if (type)
931 	type->print (indent + 1);
932     else
933 	cout << setw (indent + 1) << "" << "*** type unknown ***" << endl;
934 
935     if (array)
936 	array->print (indent + 1);
937 
938     if (index)
939 	index->print (indent + 1);
940 }
941 
942 
943 void
computeType(LContext & lcontext,const SymbolInfoPtr & initInfo)944 ArrayIndexNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
945 {
946     if (!array || !index)
947 	return;
948 
949     array->computeType (lcontext, initInfo);
950     index->computeType (lcontext, initInfo);
951 
952     if (!array->type || !index->type)
953 	return;
954 
955     ArrayTypePtr arrayType = array->type.cast<ArrayType>();
956 
957     if (!arrayType)
958     {
959 	string name = "";
960 	if( NameNodePtr arrayName =  array.cast<NameNode>() )
961 	{
962 	    name = arrayName->name;
963 	    MESSAGE_LE (lcontext, ERR_NON_ARR_IND, array->lineNumber,
964 			"Applied [] operator to non-array (" << name << " "
965 			"is of type " << array->type->asString() << ").");
966 	}
967 	else
968 	{
969 	    MESSAGE_LE (lcontext, ERR_NON_ARR_IND, array->lineNumber,
970 			"Applied [] operator to non-array of type "
971 			<< array->type->asString() << ".");
972 	}
973 	type = lcontext.newIntType();
974 	return;
975     }
976 
977     IntTypePtr intType = lcontext.newIntType ();
978 
979     if (!intType->canPromoteFrom (index->type))
980     {
981 	string name = "";
982 	if( NameNodePtr arrayName =  array.cast<NameNode>() )
983 	    name = arrayName->name;
984 
985 	MESSAGE_LE (lcontext, ERR_ARR_IND_TYPE, array->lineNumber,
986 	    "Index into array " << name << " is not an iteger "
987 	    "(index is of type " << index->type->asString() << ").");
988 
989 	type = lcontext.newIntType();
990 	return;
991     }
992 
993     type = arrayType->elementType();
994 }
995 
996 
997 ExprNodePtr
evaluate(LContext & lcontext)998 ArrayIndexNode::evaluate (LContext &lcontext)
999 {
1000     IntTypePtr intType = lcontext.newIntType ();
1001 
1002     array = array->evaluate (lcontext);
1003     index = index->evaluate (lcontext);
1004 
1005 
1006     if( IntLiteralNodePtr literal = index.cast<IntLiteralNode>())
1007     {
1008 	if(literal->value < 0)
1009 	{
1010 	    string name = "";
1011 	    if( NameNodePtr arrayName =  array.cast<NameNode>() )
1012 		name = arrayName->name;
1013 
1014 	    MESSAGE_LE (lcontext, ERR_ARR_IND_TYPE, array->lineNumber,
1015 			"Index into array " << name << " is negative "
1016 			"(" << literal->value << ").");
1017 	}
1018 
1019 	ArrayTypePtr arrayType = array->type.cast<ArrayType>();
1020 	if(!arrayType)
1021 	    return this;
1022 	if( literal->value >= arrayType->size() && arrayType->size() != 0)
1023 	{
1024 	    string name = "";
1025 	    if( NameNodePtr arrayName =  array.cast<NameNode>() )
1026 		name = arrayName->name;
1027 
1028 	    MESSAGE_LE (lcontext, ERR_ARR_IND_TYPE, array->lineNumber,
1029 			"Index into array " << name << " is out of range "
1030 			"(index = " << literal->value << ", "
1031 			"array size = " << arrayType->size() << ").");
1032 	}
1033 
1034 
1035     }
1036 
1037     if (index->type && !intType->isSameTypeAs (index->type))
1038 	index = intType->castValue (lcontext, index);
1039 
1040     return this;
1041 }
1042 
1043 
1044 bool
isLvalue(const SymbolInfoPtr & initInfo) const1045 ArrayIndexNode::isLvalue (const SymbolInfoPtr &initInfo) const
1046 {
1047     return array && array->isLvalue (initInfo);
1048 }
1049 
1050 
NameNode(int lineNumber,const std::string & name,const SymbolInfoPtr & info)1051 NameNode::NameNode
1052     (int lineNumber,
1053      const std::string &name,
1054      const SymbolInfoPtr &info)
1055 :
1056      ExprNode (lineNumber),
1057      name (name),
1058      info (info)
1059 {
1060     // empty
1061 }
1062 
1063 
1064 void
print(int indent) const1065 NameNode::print (int indent) const
1066 {
1067     cout << setw (indent) << "" << lineNumber << " name " << name << endl;
1068 
1069     if (info)
1070 	info->print (indent + 1);
1071     else
1072 	cout << setw (indent + 1) << "" << "*** no info ***" << endl;
1073 }
1074 
1075 
1076 void
computeType(LContext & lcontext,const SymbolInfoPtr & initInfo)1077 NameNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
1078 {
1079     if (info)
1080 	type = info->type();
1081 }
1082 
1083 
1084 ExprNodePtr
evaluate(LContext & lcontext)1085 NameNode::evaluate (LContext &lcontext)
1086 {
1087     if (info && info->isData() && info->value())
1088     {
1089 	ValueNodePtr valueNode = info->value().cast<ValueNode>();
1090 	if(valueNode)
1091 	    info->value()->evaluate (lcontext);
1092 	else
1093 	    return info->value()->evaluate (lcontext);
1094     }
1095     return this;
1096 }
1097 
1098 
1099 bool
isLvalue(const SymbolInfoPtr & initInfo) const1100 NameNode::isLvalue (const SymbolInfoPtr &initInfo) const
1101 {
1102     if (!type)
1103 	return false;
1104 
1105     if (type.cast<VoidType>())
1106 	return false;
1107 
1108     DataTypePtr dataType = type.cast<DataType>();
1109 
1110     if (!dataType)
1111 	return false;
1112 
1113     if (initInfo && initInfo.pointer() == info.pointer())
1114 	return true;
1115     else
1116 	return info->isWritable();
1117 }
1118 
1119 
LiteralNode(int lineNumber)1120 LiteralNode::LiteralNode (int lineNumber):
1121     ExprNode (lineNumber)
1122 {
1123     // empty
1124 }
1125 
1126 
1127 void
computeType(LContext & lcontext,const SymbolInfoPtr & initInfo)1128 LiteralNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
1129 {
1130     // empty
1131 }
1132 
1133 
1134 ExprNodePtr
evaluate(LContext & lcontext)1135 LiteralNode::evaluate (LContext &lcontext)
1136 {
1137     return this;
1138 }
1139 
1140 
1141 bool
isLvalue(const SymbolInfoPtr & initInfo) const1142 LiteralNode::isLvalue (const SymbolInfoPtr &initInfo) const
1143 {
1144     return false;
1145 }
1146 
1147 
BoolLiteralNode(int lineNumber,const LContext & lcontext,bool value)1148 BoolLiteralNode::BoolLiteralNode
1149     (int lineNumber,
1150      const LContext &lcontext,
1151      bool value)
1152 :
1153     LiteralNode (lineNumber),
1154     value (value)
1155 {
1156     type = lcontext.newBoolType ();
1157 }
1158 
1159 
1160 void
print(int indent) const1161 BoolLiteralNode::print (int indent) const
1162 {
1163     cout << setw (indent) << "" << lineNumber << " bool " << value << endl;
1164 }
1165 
1166 void
printLiteral() const1167 BoolLiteralNode::printLiteral () const
1168 {
1169     cout << value;
1170 }
1171 
1172 
IntLiteralNode(int lineNumber,const LContext & lcontext,int value)1173 IntLiteralNode::IntLiteralNode
1174     (int lineNumber,
1175      const LContext &lcontext,
1176      int value)
1177 :
1178     LiteralNode (lineNumber),
1179     value (value)
1180 {
1181     type = lcontext.newIntType ();
1182 }
1183 
1184 
1185 void
print(int indent) const1186 IntLiteralNode::print (int indent) const
1187 {
1188     cout << setw (indent) << "" << lineNumber << " int " << value << endl;
1189 }
1190 void
printLiteral() const1191 IntLiteralNode::printLiteral () const
1192 {
1193     cout << value;
1194 }
1195 
1196 
UIntLiteralNode(int lineNumber,const LContext & lcontext,unsigned int value)1197 UIntLiteralNode::UIntLiteralNode
1198     (int lineNumber,
1199      const LContext &lcontext,
1200      unsigned int value)
1201 :
1202     LiteralNode (lineNumber),
1203     value (value)
1204 {
1205     type = lcontext.newUIntType ();
1206 }
1207 
1208 
1209 void
print(int indent) const1210 UIntLiteralNode::print (int indent) const
1211 {
1212     cout << setw (indent) << "" << lineNumber <<
1213 	    " unsigned int " << value << endl;
1214 }
1215 void
printLiteral() const1216 UIntLiteralNode::printLiteral () const
1217 {
1218     cout << value;
1219 }
1220 
1221 
HalfLiteralNode(int lineNumber,const LContext & lcontext,half value)1222 HalfLiteralNode::HalfLiteralNode
1223     (int lineNumber,
1224      const LContext &lcontext,
1225      half value)
1226 :
1227     LiteralNode (lineNumber),
1228     value (value)
1229 {
1230     type = lcontext.newHalfType ();
1231 }
1232 
1233 
1234 void
print(int indent) const1235 HalfLiteralNode::print (int indent) const
1236 {
1237     cout << setw (indent) << "" << lineNumber << " half " << value << endl;
1238 }
1239 void
printLiteral() const1240 HalfLiteralNode::printLiteral () const
1241 {
1242     cout << value;
1243 }
1244 
1245 
FloatLiteralNode(int lineNumber,const LContext & lcontext,float value)1246 FloatLiteralNode::FloatLiteralNode
1247     (int lineNumber,
1248      const LContext &lcontext,
1249      float value)
1250 :
1251     LiteralNode (lineNumber),
1252     value (value)
1253 {
1254     type = lcontext.newFloatType ();
1255 }
1256 
1257 
1258 void
print(int indent) const1259 FloatLiteralNode::print (int indent) const
1260 {
1261     cout << setw (indent) << "" << lineNumber << " float " << value << endl;
1262 }
1263 void
printLiteral() const1264 FloatLiteralNode::printLiteral () const
1265 {
1266     cout << value;
1267 }
1268 
1269 
StringLiteralNode(int lineNumber,const LContext & lcontext,const string & value)1270 StringLiteralNode::StringLiteralNode
1271     (int lineNumber,
1272      const LContext &lcontext,
1273      const string &value)
1274 :
1275     LiteralNode (lineNumber),
1276     value (value)
1277 {
1278     type = lcontext.newStringType ();
1279 }
1280 
1281 
1282 void
print(int indent) const1283 StringLiteralNode::print (int indent) const
1284 {
1285     cout << setw (indent) << "" << lineNumber <<
1286 	    " float \"" << value << "\"" << endl;
1287 }
1288 void
printLiteral() const1289 StringLiteralNode::printLiteral () const
1290 {
1291     cout << value;
1292 }
1293 
1294 
CallNode(int lineNumber,const NameNodePtr & function,const ExprNodeVector & arguments)1295 CallNode::CallNode
1296     (int lineNumber,
1297      const NameNodePtr &function,
1298      const ExprNodeVector &arguments)
1299 :
1300     ExprNode (lineNumber),
1301     function (function),
1302     arguments (arguments)
1303 {
1304     // empty
1305 }
1306 
1307 
1308 void
print(int indent) const1309 CallNode::print (int indent) const
1310 {
1311     cout << setw (indent) << "" << lineNumber << " function call" << endl;
1312 
1313     if (function)
1314 	function->print (indent + 1);
1315 
1316     for (int i = 0; i < (int)arguments.size(); ++i)
1317 	arguments[i]->print (indent + 1);
1318 }
1319 
1320 
1321 void
computeType(LContext & lcontext,const SymbolInfoPtr & initInfo)1322 CallNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
1323 {
1324     //
1325     // Compute the type of a function call.  This is the same type
1326     // as the function's return type, provided the call is valid.
1327     //
1328 
1329     //
1330     // Verify that what we are trying to call is actually a function.
1331     //
1332 
1333     if (!function)
1334 	return;
1335 
1336     function->computeType (lcontext, initInfo);
1337 
1338     if (!function->type)
1339 	return;
1340 
1341     FunctionTypePtr functionType = function->type.cast <FunctionType>();
1342 
1343     if (!functionType)
1344     {
1345 	MESSAGE_LE (lcontext, ERR_NON_FUNC, function->lineNumber,
1346 	    "Invalid function call to call non-function "
1347 	    "(" << function->name << " is of type " <<
1348 	    function->type->asString() << ").");
1349 
1350 	return;
1351     }
1352 
1353     //
1354     // We shouldn't have more function call arguments than parameters.
1355     //
1356 
1357     const ParamVector &parameters = functionType->parameters();
1358 
1359     if (arguments.size() > parameters.size())
1360     {
1361 	MESSAGE_LE (lcontext, ERR_FUNC_ARG_NUM, function->lineNumber,
1362 	    "Too many arguments in call to function " << function->name << ".");
1363 
1364 	return;
1365     }
1366 
1367     //
1368     // Compare the types of the arguments to the call with
1369     // the types of the function's parameters.
1370     //
1371 
1372     for (int i = 0; i < (int)parameters.size(); ++i)
1373     {
1374 	if (i < (int)arguments.size())
1375 	{
1376 	    //
1377 	    // We have a function call argument for parameter i.
1378 	    //
1379 
1380 	    arguments[i]->computeType (lcontext, initInfo);
1381 
1382 	    TypePtr argType = arguments[i]->type;
1383 
1384 	    if (!argType)
1385 		return;
1386 
1387 	    DataTypePtr paramType = parameters[i].type;
1388 
1389 	    if (parameters[i].isWritable())
1390 	    {
1391 		//
1392 		// output parameter -- argument must be an lvalue
1393 		// of the same type as the parameter
1394 		//
1395 
1396 		if (!arguments[i]->isLvalue (initInfo))
1397 		{
1398 		    MESSAGE_LE (lcontext, ERR_FUNC_ARG_LVAL, arguments[i]->lineNumber,
1399 			"Argument " << i+1 << " in call to function " <<
1400 			function->name << " corresponds to an output "
1401 			"parameter but it is not an lvalue.");
1402 
1403 		    return;
1404 		}
1405 
1406 		if (!paramType->isSameTypeAs (argType))
1407 		{
1408 		    MESSAGE_LE (lcontext,
1409 			ERR_FUNC_ARG_TYPE, arguments[i]->lineNumber,
1410 			"Type of argument " << i+1 << " in call to "
1411 			"function " << function->name << " is not the "
1412 			"same as the type of the function's parameter "
1413 			"(" << argType->asString() << " value "
1414 			"for " << paramType->asString() << " parameter.)");
1415 		    return;
1416 		}
1417 	    }
1418 	    else
1419 	    {
1420 		//
1421 		// input parameter -- it must be possible to cast
1422 		// the argument type to the parameter type
1423 		//
1424 
1425 		if (!paramType->canCastFrom (argType))
1426 		{
1427 		    MESSAGE_LE (lcontext, ERR_FUNC_ARG_TYPE,
1428 			arguments[i]->lineNumber,
1429 			"Cannot convert the type of argument " << i+1 << " "
1430 			"in call to function " << function->name << " "
1431 			"to the type of the function's parameter "
1432 			"(" << argType->asString() << " value "
1433 			"for " << paramType->asString() << " parameter.)");
1434 		    return;
1435 		}
1436 	    }
1437 	}
1438 	else
1439 	{
1440 	    //
1441 	    // We have no function call argument for parameter i.
1442 	    // The parameter must have a default value.
1443 	    //
1444 
1445 	    if (!parameters[i].defaultValue)
1446 	    {
1447 		MESSAGE_LE (lcontext, ERR_FUNC_ARG_NUM,
1448 		    function->lineNumber,
1449 		    "Not enough arguments in call to "
1450 		    "function " << function->name << ".");
1451 		return;
1452 	    }
1453 	}
1454     }
1455 
1456     //
1457     // If we get here, then the call is valid.
1458     //
1459 
1460     type = functionType->returnType();
1461 }
1462 
1463 
1464 ExprNodePtr
evaluate(LContext & lcontext)1465 CallNode::evaluate (LContext &lcontext)
1466 {
1467     for (int i = 0; i < (int)arguments.size(); ++i)
1468 	arguments[i] = arguments[i]->evaluate (lcontext);
1469 
1470     return this;
1471 }
1472 
1473 
1474 bool
isLvalue(const SymbolInfoPtr & initInfo) const1475 CallNode::isLvalue (const SymbolInfoPtr &initInfo) const
1476 {
1477     return false;
1478 }
1479 
1480 
ValueNode(int lineNumber,const ExprNodeVector & elements)1481 ValueNode::ValueNode
1482     (int lineNumber,
1483      const ExprNodeVector &elements)
1484 :
1485     ExprNode (lineNumber),
1486     elements (elements)
1487 {
1488     // empty
1489 }
1490 
1491 
1492 void
print(int indent) const1493 ValueNode::print (int indent) const
1494 {
1495     cout << setw (indent) << "" << lineNumber << " value initializer" << endl;
1496 
1497     if(elements.size() <= 20)
1498     {
1499 	for (int i = 0; i < (int)elements.size(); ++i)
1500 	    elements[i]->print (indent + 1);
1501     }
1502     else
1503     {
1504 	cout << setw (indent) << "[";
1505 	for (int i = 0; i < (int)elements.size(); ++i)
1506 	{
1507 	    LiteralNodePtr literal = elements[i].cast<LiteralNode>();
1508 	    if(literal)
1509 	    {
1510 		literal->printLiteral();
1511 
1512 		if( i == (int)elements.size() -1)
1513 		    cout << "]\n";
1514 		else
1515 		{
1516 		    cout << ", ";
1517 
1518 		    if( i >= 199 && elements.size() - i > 10)
1519 		    {
1520 			cout << "\n";
1521 			cout  << setw (indent) << "" << "...< "
1522 			      << elements.size() - i - 11
1523 			      << " elements omitted > \n";
1524 			cout  << setw (indent) << "";
1525 			i = elements.size() - 11;
1526 		    }
1527 		    else if( (i+1)%10 == 0)
1528 		    {
1529 			cout << "\n";
1530 			cout << setw(indent) << "";
1531 		    }
1532 		}
1533 	    }
1534 	    else
1535 		elements[i]->print (indent + 1);
1536 
1537 	}
1538     }
1539 
1540 }
1541 
1542 
1543 void
computeType(LContext & lcontext,const SymbolInfoPtr & initInfo)1544 ValueNode::computeType (LContext &lcontext, const SymbolInfoPtr &initInfo)
1545 {
1546     for (int i = 0; i < (int)elements.size(); ++i)
1547     {
1548 	elements[i]->computeType (lcontext, initInfo);
1549 
1550 	if (!elements[i]->type)
1551 	    return;
1552     }
1553 }
1554 
1555 
1556 ExprNodePtr
evaluate(LContext & lcontext)1557 ValueNode::evaluate (LContext &lcontext)
1558 {
1559     for (int i = 0; i < (int)elements.size(); ++i)
1560 	elements[i] = elements[i]->evaluate (lcontext);
1561 
1562     return this;
1563 }
1564 
1565 
1566 bool
checkElementTypes(const DataTypePtr & dataType,LContext & lcontext) const1567 ValueNode::checkElementTypes (const DataTypePtr &dataType,
1568 			      LContext &lcontext) const
1569 {
1570     int eIndex = 0;
1571     return checkElementTypesRec(dataType, lcontext, eIndex);
1572 }
1573 
1574 bool
checkElementTypesRec(const DataTypePtr & dataType,LContext & lcontext,int & eIndex) const1575 ValueNode::checkElementTypesRec (const DataTypePtr &dataType,
1576 				 LContext &lcontext,
1577 				 int &eIndex) const
1578 {
1579     //
1580     //  recursively iterate through nested structs and arrays
1581     //  in this data type, checking element types along the way
1582     //
1583 
1584     assert(eIndex < (int)elements.size());
1585     if( StructTypePtr structType = dataType.cast<StructType>() )
1586     {
1587 	for(MemberVectorConstIterator it = structType->members().begin();
1588 	    it != structType->members().end();
1589 	    it++)
1590 	{
1591 	    if(!checkElementTypesRec(it->type, lcontext, eIndex))
1592 		return false;
1593 	}
1594     }
1595     else if( ArrayTypePtr arrayType = dataType.cast<ArrayType>() )
1596     {
1597 	for (int i = 0; i < arrayType->size(); ++i)
1598 	{
1599 	    if( !checkElementTypesRec(arrayType->elementType(), lcontext, eIndex) )
1600 		return false;
1601 	}
1602     }
1603     else if (!dataType->canCastFrom (elements[eIndex++]->type))
1604     {
1605 	string fromType = "unknown";
1606 	if( elements[eIndex-1]->type)
1607 	    fromType = elements[eIndex-1]->type->asString();
1608 	MESSAGE_LE (lcontext, ERR_ARR_EL_TYPE,
1609 		    elements[eIndex-1]->lineNumber,
1610 		    "Cannot convert the type of value element "
1611 		    << eIndex-1 << " "
1612 		    "(" << fromType << ") "
1613 		    "to type " << dataType->asString() << ".");
1614 	return false;
1615     }
1616     return true;
1617 }
1618 
1619 
1620 bool
elementsAreLiterals() const1621 ValueNode::elementsAreLiterals () const
1622 {
1623     for (int i = 0; i < (int)elements.size(); ++i)
1624 	if (!elements[i].cast<LiteralNode>())
1625 	    return false;
1626 
1627     return true;
1628 }
1629 
1630 
1631 bool
isLvalue(const SymbolInfoPtr & initInfo) const1632 ValueNode::isLvalue (const SymbolInfoPtr &initInfo) const
1633 {
1634     return false;
1635 }
1636 
1637 } // namespace Ctl
1638