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 ¶meters = 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