Separating all of the simple binary expression nodes into multiple classes
[WebKit-https.git] / JavaScriptCore / kjs / nodes2string.cpp
1 /*
2  *  This file is part of the KDE libraries
3  *  Copyright (C) 2002 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "nodes.h"
25 #include "function.h"
26
27 namespace KJS {
28   /**
29    * A simple text streaming class that helps with code indentation.
30    */
31   class SourceStream {
32   public:
33     enum Format {
34       Endl, Indent, Unindent, DotExpr
35     };
36     SourceStream() : m_groupIfNumber(false) {}
37     UString toString() const { return str; }
38     SourceStream& operator<<(const Identifier &);
39     SourceStream& operator<<(const UString &);
40     SourceStream& operator<<(const char *);
41     SourceStream& operator<<(double);
42     SourceStream& operator<<(char);
43     SourceStream& operator<<(Format f);
44     SourceStream& operator<<(const Node *);
45     template <typename T> SourceStream& operator<<(RefPtr<T> n) { return this->operator<<(n.get()); }
46
47   private:
48     UString str; /* TODO: buffer */
49     UString ind;
50     bool m_groupIfNumber;
51   };
52 }
53
54 using namespace KJS;
55
56 SourceStream& SourceStream::operator<<(char c)
57 {
58   m_groupIfNumber = false;
59   UChar ch(c);
60   str += UString(&ch, 1);
61   return *this;
62 }
63
64 SourceStream& SourceStream::operator<<(const char *s)
65 {
66   m_groupIfNumber = false;
67   str += UString(s);
68   return *this;
69 }
70
71 SourceStream& SourceStream::operator<<(double value)
72 {
73   if (m_groupIfNumber)
74     str.append("(");
75
76   str += UString::from(value);
77
78   if (m_groupIfNumber)
79     str.append(")");
80
81   m_groupIfNumber = false;
82   return *this;
83 }
84
85 SourceStream& SourceStream::operator<<(const UString &s)
86 {
87   m_groupIfNumber = false;
88   str += s;
89   return *this;
90 }
91
92 SourceStream& SourceStream::operator<<(const Identifier &s)
93 {
94   m_groupIfNumber = false;
95   str += s.ustring();
96   return *this;
97 }
98
99 SourceStream& SourceStream::operator<<(const Node *n)
100 {
101   if (n)
102     n->streamTo(*this);
103   m_groupIfNumber = false;
104   return *this;
105 }
106
107 SourceStream& SourceStream::operator<<(Format f)
108 {
109   m_groupIfNumber = false;
110   switch (f) {
111     case Endl:
112       str += "\n" + ind;
113       break;
114     case Indent:
115       ind += "  ";
116       break;
117     case Unindent:
118       ind = ind.substr(0, ind.size() - 2);
119       break;
120   case DotExpr:
121       m_groupIfNumber = true;
122       break;
123   }
124
125   return *this;
126 }
127
128 UString Node::toString() const
129 {
130   SourceStream str;
131   streamTo(str);
132
133   return str.toString();
134 }
135
136 void NullNode::streamTo(SourceStream &s) const { s << "null"; }
137
138 void BooleanNode::streamTo(SourceStream &s) const
139 {
140   s << (value ? "true" : "false");
141 }
142
143 void NumberNode::streamTo(SourceStream &s) const { s << val; }
144
145 void StringNode::streamTo(SourceStream &s) const
146 {
147   s << '"' << escapeStringForPrettyPrinting(value) << '"';
148 }
149
150 void RegExpNode::streamTo(SourceStream &s) const
151
152     s << "/" <<  pattern << "/" << flags; 
153 }
154
155 void ThisNode::streamTo(SourceStream &s) const { s << "this"; }
156
157 void ResolveNode::streamTo(SourceStream &s) const { s << ident; }
158
159 void GroupNode::streamTo(SourceStream &s) const
160 {
161   s << "(" << group << ")"; 
162 }
163
164 void ElementNode::streamTo(SourceStream &s) const
165 {
166   for (const ElementNode *n = this; n; n = n->next.get()) {
167     for (int i = 0; i < n->elision; i++)
168       s << ",";
169     s << n->node;
170     if (n->next)
171         s << ",";
172   }
173 }
174
175 void ArrayNode::streamTo(SourceStream &s) const
176 {
177   s << "[" << element;
178   for (int i = 0; i < elision; i++)
179     s << ",";
180   // Parser consumes one elision comma if there's array elements 
181   // present in the expression.
182   if (opt && element)
183     s << ",";
184   s << "]";
185 }
186
187 void ObjectLiteralNode::streamTo(SourceStream &s) const
188 {
189   if (list)
190     s << "{ " << list << " }";
191   else
192     s << "{ }";
193 }
194
195 void PropertyListNode::streamTo(SourceStream &s) const
196 {
197   s << node;
198   
199   for (const PropertyListNode *n = next.get(); n; n = n->next.get())
200     s << ", " << n->node;
201 }
202
203 void PropertyNode::streamTo(SourceStream &s) const
204 {
205   switch (type) {
206     case Constant:
207       s << name << ": " << assign;
208       break;
209     case Getter:
210     case Setter: {
211       const FuncExprNode *func = static_cast<const FuncExprNode *>(assign.get());
212       if (type == Getter)
213         s << "get "; 
214       else
215         s << "set ";
216       
217       s << name << "(" << func->param << ")" << func->body;
218       break;
219     }
220   }
221 }
222
223 void PropertyNameNode::streamTo(SourceStream &s) const
224 {
225   if (str.isNull())
226     s << UString::from(numeric);
227   else
228     s << '"' << escapeStringForPrettyPrinting(str.ustring()) << '"';
229 }
230
231 void BracketAccessorNode::streamTo(SourceStream &s) const
232 {
233   s << expr1 << "[" << expr2 << "]";
234 }
235
236 void DotAccessorNode::streamTo(SourceStream &s) const
237 {
238   s << SourceStream::DotExpr << expr << "." << ident;
239 }
240
241 void ArgumentListNode::streamTo(SourceStream &s) const
242 {
243   s << expr;
244   for (ArgumentListNode *n = next.get(); n; n = n->next.get())
245     s << ", " << n->expr;
246 }
247
248 void ArgumentsNode::streamTo(SourceStream &s) const
249 {
250   s << "(" << list << ")";
251 }
252
253 void NewExprNode::streamTo(SourceStream &s) const
254 {
255   s << "new " << expr << args;
256 }
257
258 void FunctionCallValueNode::streamTo(SourceStream &s) const
259 {
260   s << expr << args;
261 }
262
263 void FunctionCallResolveNode::streamTo(SourceStream &s) const
264 {
265   s << ident << args;
266 }
267
268 void FunctionCallBracketNode::streamTo(SourceStream &s) const
269 {
270   s << base << "[" << subscript << "]" << args;
271 }
272
273 void FunctionCallParenBracketNode::streamTo(SourceStream &s) const
274 {
275   s << "(" << base << "[" << subscript << "])" << args;
276 }
277
278 void FunctionCallDotNode::streamTo(SourceStream &s) const
279 {
280   s << SourceStream::DotExpr << base << "." << ident << args;
281 }
282
283 void FunctionCallParenDotNode::streamTo(SourceStream &s) const
284 {
285   s << "(" << SourceStream::DotExpr << base << "." << ident << ")" << args;
286 }
287
288 void PostfixResolveNode::streamTo(SourceStream &s) const
289 {
290   s << m_ident;
291   if (m_oper == OpPlusPlus)
292     s << "++";
293   else
294     s << "--";
295 }
296
297 void PostfixBracketNode::streamTo(SourceStream &s) const
298 {
299   s << m_base << "[" << m_subscript << "]";
300   if (m_oper == OpPlusPlus)
301     s << "++";
302   else
303     s << "--";
304 }
305
306 void PostfixDotNode::streamTo(SourceStream &s) const
307 {
308   s << SourceStream::DotExpr << m_base << "." << m_ident;
309   if (m_oper == OpPlusPlus)
310     s << "++";
311   else
312     s << "--";
313 }
314
315 void PostfixErrorNode::streamTo(SourceStream& s) const
316 {
317   s << m_expr;
318   if (m_oper == OpPlusPlus)
319     s << "++";
320   else
321     s << "--";
322 }
323
324 void DeleteResolveNode::streamTo(SourceStream &s) const
325 {
326   s << "delete " << m_ident;
327 }
328
329 void DeleteBracketNode::streamTo(SourceStream &s) const
330 {
331   s << "delete " << m_base << "[" << m_subscript << "]";
332 }
333
334 void DeleteDotNode::streamTo(SourceStream &s) const
335 {
336   s << "delete " << SourceStream::DotExpr << m_base << "." << m_ident;
337 }
338
339 void DeleteValueNode::streamTo(SourceStream &s) const
340 {
341   s << "delete " << m_expr;
342 }
343
344 void VoidNode::streamTo(SourceStream &s) const
345 {
346   s << "void " << expr;
347 }
348
349 void TypeOfValueNode::streamTo(SourceStream &s) const
350 {
351   s << "typeof " << m_expr;
352 }
353
354 void TypeOfResolveNode::streamTo(SourceStream &s) const
355 {
356   s << "typeof " << m_ident;
357 }
358
359 void PrefixResolveNode::streamTo(SourceStream &s) const
360 {
361   if (m_oper == OpPlusPlus)
362     s << "++";
363   else
364     s << "--";
365   s << m_ident;
366 }
367
368 void PrefixBracketNode::streamTo(SourceStream &s) const
369 {
370   if (m_oper == OpPlusPlus)
371     s << "++";
372   else
373     s << "--";
374   s << m_base << "[" << m_subscript << "]";
375 }
376
377 void PrefixDotNode::streamTo(SourceStream &s) const
378 {
379   if (m_oper == OpPlusPlus)
380     s << "++";
381   else
382     s << "--";
383   s << SourceStream::DotExpr << m_base << "." << m_ident;
384 }
385
386 void PrefixErrorNode::streamTo(SourceStream& s) const
387 {
388   if (m_oper == OpPlusPlus)
389     s << "++";
390   else
391     s << "--";
392   s << m_expr;
393 }
394
395 void UnaryPlusNode::streamTo(SourceStream &s) const
396 {
397   s << "+ " << expr;
398 }
399
400 void NegateNode::streamTo(SourceStream &s) const
401 {
402   s << "- " << expr;
403 }
404
405 void BitwiseNotNode::streamTo(SourceStream &s) const
406 {
407   s << "~" << expr;
408 }
409
410 void LogicalNotNode::streamTo(SourceStream &s) const
411 {
412   s << "!" << expr;
413 }
414
415 void MultNode::streamTo(SourceStream &s) const
416 {
417     s << term1 << " * " << term2;
418 }
419
420 void DivNode::streamTo(SourceStream &s) const
421 {
422     s << term1 << " / " << term2;
423 }
424
425 void ModNode::streamTo(SourceStream &s) const
426 {
427     s << term1 << " % " << term2;
428 }
429
430 void AddNode::streamTo(SourceStream &s) const
431 {
432     s << term1 << " + " << term2;
433 }
434
435 void SubNode::streamTo(SourceStream &s) const
436 {
437     s << term1 << " - " << term2;
438 }
439
440 void LeftShiftNode::streamTo(SourceStream &s) const
441 {
442   s << term1 << "<<" << term2;
443 }
444
445 void RightShiftNode::streamTo(SourceStream &s) const
446 {
447   s << term1 << ">>" << term2;
448 }
449
450 void UnsignedRightShiftNode::streamTo(SourceStream &s) const
451 {
452   s << term1 << ">>>" << term2;
453 }
454
455 void LessNode::streamTo(SourceStream &s) const
456 {
457   s << expr1 << " < " << expr2;
458 }
459
460 void GreaterNode::streamTo(SourceStream &s) const
461 {
462   s << expr1 << " > " << expr2;
463 }
464
465 void LessEqNode::streamTo(SourceStream &s) const
466 {
467   s << expr1 << " <= " << expr2;
468 }
469
470 void GreaterEqNode::streamTo(SourceStream &s) const
471 {
472   s << expr1 << " >= " << expr2;
473 }
474
475 void InstanceOfNode::streamTo(SourceStream &s) const
476 {
477   s << expr1 << " instanceof " << expr2;
478 }
479
480 void InNode::streamTo(SourceStream &s) const
481 {
482   s << expr1 << " in " << expr2;
483 }
484
485 void EqualNode::streamTo(SourceStream &s) const
486 {
487   s << expr1 << " == " << expr2;
488 }
489
490 void NotEqualNode::streamTo(SourceStream &s) const
491 {
492   s << expr1 << " == " << expr2;
493 }
494
495 void StrictEqualNode::streamTo(SourceStream &s) const
496 {
497   s << expr1 << " === " << expr2;
498 }
499
500 void NotStrictEqualNode::streamTo(SourceStream &s) const
501 {
502   s << expr1 << " !== " << expr2;
503 }
504
505 void BitAndNode::streamTo(SourceStream &s) const
506 {
507   s << expr1 << " & " << expr2;
508 }
509
510 void BitXOrNode::streamTo(SourceStream &s) const
511 {
512   s << expr1 << " ^ " << expr2;
513 }
514
515 void BitOrNode::streamTo(SourceStream &s) const
516 {
517   s << expr1 << " | " << expr2;
518 }
519
520 void LogicalAndNode::streamTo(SourceStream &s) const
521 {
522   s << expr1 << " && " << expr2;
523 }
524
525 void LogicalOrNode::streamTo(SourceStream &s) const
526 {
527   s << expr1 << " || " << expr2;
528 }
529
530 void ConditionalNode::streamTo(SourceStream &s) const
531 {
532   s << logical << " ? " << expr1 << " : " << expr2;
533 }
534
535 static void streamAssignmentOperatorTo(SourceStream &s, Operator oper)
536 {
537   const char *opStr;
538   switch (oper) {
539   case OpEqual:
540     opStr = " = ";
541     break;
542   case OpMultEq:
543     opStr = " *= ";
544     break;
545   case OpDivEq:
546     opStr = " /= ";
547     break;
548   case OpPlusEq:
549     opStr = " += ";
550     break;
551   case OpMinusEq:
552     opStr = " -= ";
553     break;
554   case OpLShift:
555     opStr = " <<= ";
556     break;
557   case OpRShift:
558     opStr = " >>= ";
559     break;
560   case OpURShift:
561     opStr = " >>>= ";
562     break;
563   case OpAndEq:
564     opStr = " &= ";
565     break;
566   case OpXOrEq:
567     opStr = " ^= ";
568     break;
569   case OpOrEq:
570     opStr = " |= ";
571     break;
572   case OpModEq:
573     opStr = " %= ";
574     break;
575   default:
576     opStr = " ?= ";
577   }
578   s << opStr;
579 }
580
581 void AssignResolveNode::streamTo(SourceStream &s) const
582 {
583   s << m_ident;
584   streamAssignmentOperatorTo(s, m_oper);
585   s << m_right;
586 }
587
588 void AssignBracketNode::streamTo(SourceStream &s) const
589 {
590   s << m_base << "[" << m_subscript << "]";
591   streamAssignmentOperatorTo(s, m_oper);
592   s << m_right;
593 }
594
595 void AssignDotNode::streamTo(SourceStream &s) const
596 {
597   s << SourceStream::DotExpr << m_base << "." << m_ident;
598   streamAssignmentOperatorTo(s, m_oper);
599   s << m_right;
600 }
601
602 void AssignErrorNode::streamTo(SourceStream& s) const
603 {
604   s << m_left;
605   streamAssignmentOperatorTo(s, m_oper);
606   s << m_right;
607 }
608
609 void CommaNode::streamTo(SourceStream &s) const
610 {
611   s << expr1 << ", " << expr2;
612 }
613
614 void AssignExprNode::streamTo(SourceStream &s) const
615 {
616   s << " = " << expr;
617 }
618
619 void VarDeclNode::streamTo(SourceStream &s) const
620 {
621   s << ident << init;
622 }
623
624 void VarDeclListNode::streamTo(SourceStream &s) const
625 {
626   s << "var " << var;
627   for (VarDeclListNode *n = next.get(); n; n = n->next.get())
628     s << ", " << n->var;
629 }
630
631 void VarStatementNode::streamTo(SourceStream &s) const
632 {
633   s << SourceStream::Endl << next << ";";
634 }
635
636 void BlockNode::streamTo(SourceStream &s) const
637 {
638   s << SourceStream::Endl << "{" << SourceStream::Indent
639     << source << SourceStream::Unindent << SourceStream::Endl << "}";
640 }
641
642 void EmptyStatementNode::streamTo(SourceStream &s) const
643 {
644   s << SourceStream::Endl << ";";
645 }
646
647 void ExprStatementNode::streamTo(SourceStream &s) const
648 {
649   s << SourceStream::Endl << expr << ";";
650 }
651
652 void IfNode::streamTo(SourceStream &s) const
653 {
654   s << SourceStream::Endl << "if (" << expr << ")" << SourceStream::Indent
655     << statement1 << SourceStream::Unindent;
656   if (statement2)
657     s << SourceStream::Endl << "else" << SourceStream::Indent
658       << statement2 << SourceStream::Unindent;
659 }
660
661 void DoWhileNode::streamTo(SourceStream &s) const
662 {
663   s << SourceStream::Endl << "do " << SourceStream::Indent
664     << statement << SourceStream::Unindent << SourceStream::Endl
665     << "while (" << expr << ");";
666 }
667
668 void WhileNode::streamTo(SourceStream &s) const
669 {
670   s << SourceStream::Endl << "while (" << expr << ")" << SourceStream::Indent
671     << statement << SourceStream::Unindent;
672 }
673
674 void ForNode::streamTo(SourceStream &s) const
675 {
676   s << SourceStream::Endl << "for ("
677     << expr1
678     << "; " << expr2
679     << "; " << expr3
680     << ")" << SourceStream::Indent << statement << SourceStream::Unindent;
681 }
682
683 void ForInNode::streamTo(SourceStream &s) const
684 {
685   s << SourceStream::Endl << "for (";
686   if (varDecl)
687     s << "var " << varDecl;
688   else
689     s << lexpr;
690
691   s << " in " << expr << ")" << SourceStream::Indent
692     << statement << SourceStream::Unindent;
693 }
694
695 void ContinueNode::streamTo(SourceStream &s) const
696 {
697   s << SourceStream::Endl << "continue";
698   if (!ident.isNull())
699     s << " " << ident;
700   s << ";";
701 }
702
703 void BreakNode::streamTo(SourceStream &s) const
704 {
705   s << SourceStream::Endl << "break";
706   if (!ident.isNull())
707     s << " " << ident;
708   s << ";";
709 }
710
711 void ReturnNode::streamTo(SourceStream &s) const
712 {
713   s << SourceStream::Endl << "return";
714   if (value)
715     s << " " << value;
716   s << ";";
717 }
718
719 void WithNode::streamTo(SourceStream &s) const
720 {
721   s << SourceStream::Endl << "with (" << expr << ") "
722     << statement;
723 }
724
725 void CaseClauseNode::streamTo(SourceStream &s) const
726 {
727   s << SourceStream::Endl;
728   if (expr)
729     s << "case " << expr;
730   else
731     s << "default";
732   s << ":" << SourceStream::Indent;
733   if (source)
734     s << source;
735   s << SourceStream::Unindent;
736 }
737
738 void ClauseListNode::streamTo(SourceStream &s) const
739 {
740   for (const ClauseListNode *n = this; n; n = n->getNext())
741     s << n->getClause();
742 }
743
744 void CaseBlockNode::streamTo(SourceStream &s) const
745 {
746   for (const ClauseListNode *n = list1.get(); n; n = n->getNext())
747     s << n->getClause();
748   if (def)
749     s << def;
750   for (const ClauseListNode *n = list2.get(); n; n = n->getNext())
751     s << n->getClause();
752 }
753
754 void SwitchNode::streamTo(SourceStream &s) const
755 {
756   s << SourceStream::Endl << "switch (" << expr << ") {"
757     << SourceStream::Indent << block << SourceStream::Unindent
758     << SourceStream::Endl << "}";
759 }
760
761 void LabelNode::streamTo(SourceStream &s) const
762 {
763   s << SourceStream::Endl << label << ":" << SourceStream::Indent
764     << statement << SourceStream::Unindent;
765 }
766
767 void ThrowNode::streamTo(SourceStream &s) const
768 {
769   s << SourceStream::Endl << "throw " << expr << ";";
770 }
771
772 void TryNode::streamTo(SourceStream &s) const
773 {
774   s << SourceStream::Endl << "try " << tryBlock;
775   if (catchBlock)
776     s << SourceStream::Endl << "catch (" << exceptionIdent << ")" << catchBlock;
777   if (finallyBlock)
778     s << SourceStream::Endl << "finally " << finallyBlock;
779 }
780
781 void ParameterNode::streamTo(SourceStream &s) const
782 {
783   s << id;
784   for (ParameterNode *n = next.get(); n; n = n->next.get())
785     s << ", " << n->id;
786 }
787
788 void FuncDeclNode::streamTo(SourceStream &s) const
789 {
790   s << SourceStream::Endl << "function " << ident << "(" << param << ")" << body;
791 }
792
793 void FuncExprNode::streamTo(SourceStream &s) const
794 {
795   s << "function " << ident << "(" << param << ")" << body;
796 }
797
798 void SourceElementsNode::streamTo(SourceStream &s) const
799 {
800   for (const SourceElementsNode *n = this; n; n = n->next.get())
801     s << n->node;
802 }