aec5836f8b8de0481731cfdfabcec75b8af3a382
[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 << " " << oper << " " << term2;
418 }
419
420 void AddNode::streamTo(SourceStream &s) const
421 {
422   s << term1 << " " << oper << " " << term2;
423 }
424
425 void ShiftNode::streamTo(SourceStream &s) const
426 {
427   s << term1;
428   if (oper == OpLShift)
429     s << "<<";
430   else if (oper == OpRShift)
431     s << ">>";
432   else
433     s << ">>>";
434   s << term2;
435 }
436
437 void RelationalNode::streamTo(SourceStream &s) const
438 {
439   s << expr1;
440   switch (oper) {
441   case OpLess:
442     s << " < ";
443     break;
444   case OpGreater:
445     s << " > ";
446     break;
447   case OpLessEq:
448     s << " <= ";
449     break;
450   case OpGreaterEq:
451     s << " >= ";
452     break;
453   case OpInstanceOf:
454     s << " instanceof ";
455     break;
456   case OpIn:
457     s << " in ";
458     break;
459   default:
460     ;
461   }
462   s << expr2;
463 }
464
465 void EqualNode::streamTo(SourceStream &s) const
466 {
467   s << expr1;
468  switch (oper) {
469  case OpEqEq:
470    s << " == ";
471    break;
472  case OpNotEq:
473    s << " != ";
474    break;
475  case OpStrEq:
476    s << " === ";
477    break;
478  case OpStrNEq:
479    s << " !== ";
480    break;
481  default:
482    ;
483  }
484   s << expr2;
485 }
486
487 void BitOperNode::streamTo(SourceStream &s) const
488 {
489   s << expr1;
490   if (oper == OpBitAnd)
491     s << " & ";
492   else if (oper == OpBitXOr)
493     s << " ^ ";
494   else
495     s << " | ";
496   s << expr2;
497 }
498
499 void BinaryLogicalNode::streamTo(SourceStream &s) const
500 {
501   s << expr1 << (oper == OpAnd ? " && " : " || ") << expr2;
502 }
503
504 void ConditionalNode::streamTo(SourceStream &s) const
505 {
506   s << logical << " ? " << expr1 << " : " << expr2;
507 }
508
509 static void streamAssignmentOperatorTo(SourceStream &s, Operator oper)
510 {
511   const char *opStr;
512   switch (oper) {
513   case OpEqual:
514     opStr = " = ";
515     break;
516   case OpMultEq:
517     opStr = " *= ";
518     break;
519   case OpDivEq:
520     opStr = " /= ";
521     break;
522   case OpPlusEq:
523     opStr = " += ";
524     break;
525   case OpMinusEq:
526     opStr = " -= ";
527     break;
528   case OpLShift:
529     opStr = " <<= ";
530     break;
531   case OpRShift:
532     opStr = " >>= ";
533     break;
534   case OpURShift:
535     opStr = " >>>= ";
536     break;
537   case OpAndEq:
538     opStr = " &= ";
539     break;
540   case OpXOrEq:
541     opStr = " ^= ";
542     break;
543   case OpOrEq:
544     opStr = " |= ";
545     break;
546   case OpModEq:
547     opStr = " %= ";
548     break;
549   default:
550     opStr = " ?= ";
551   }
552   s << opStr;
553 }
554
555 void AssignResolveNode::streamTo(SourceStream &s) const
556 {
557   s << m_ident;
558   streamAssignmentOperatorTo(s, m_oper);
559   s << m_right;
560 }
561
562 void AssignBracketNode::streamTo(SourceStream &s) const
563 {
564   s << m_base << "[" << m_subscript << "]";
565   streamAssignmentOperatorTo(s, m_oper);
566   s << m_right;
567 }
568
569 void AssignDotNode::streamTo(SourceStream &s) const
570 {
571   s << SourceStream::DotExpr << m_base << "." << m_ident;
572   streamAssignmentOperatorTo(s, m_oper);
573   s << m_right;
574 }
575
576 void AssignErrorNode::streamTo(SourceStream& s) const
577 {
578   s << m_left;
579   streamAssignmentOperatorTo(s, m_oper);
580   s << m_right;
581 }
582
583 void CommaNode::streamTo(SourceStream &s) const
584 {
585   s << expr1 << ", " << expr2;
586 }
587
588 void AssignExprNode::streamTo(SourceStream &s) const
589 {
590   s << " = " << expr;
591 }
592
593 void VarDeclNode::streamTo(SourceStream &s) const
594 {
595   s << ident << init;
596 }
597
598 void VarDeclListNode::streamTo(SourceStream &s) const
599 {
600   s << "var " << var;
601   for (VarDeclListNode *n = next.get(); n; n = n->next.get())
602     s << ", " << n->var;
603 }
604
605 void VarStatementNode::streamTo(SourceStream &s) const
606 {
607   s << SourceStream::Endl << next << ";";
608 }
609
610 void BlockNode::streamTo(SourceStream &s) const
611 {
612   s << SourceStream::Endl << "{" << SourceStream::Indent
613     << source << SourceStream::Unindent << SourceStream::Endl << "}";
614 }
615
616 void EmptyStatementNode::streamTo(SourceStream &s) const
617 {
618   s << SourceStream::Endl << ";";
619 }
620
621 void ExprStatementNode::streamTo(SourceStream &s) const
622 {
623   s << SourceStream::Endl << expr << ";";
624 }
625
626 void IfNode::streamTo(SourceStream &s) const
627 {
628   s << SourceStream::Endl << "if (" << expr << ")" << SourceStream::Indent
629     << statement1 << SourceStream::Unindent;
630   if (statement2)
631     s << SourceStream::Endl << "else" << SourceStream::Indent
632       << statement2 << SourceStream::Unindent;
633 }
634
635 void DoWhileNode::streamTo(SourceStream &s) const
636 {
637   s << SourceStream::Endl << "do " << SourceStream::Indent
638     << statement << SourceStream::Unindent << SourceStream::Endl
639     << "while (" << expr << ");";
640 }
641
642 void WhileNode::streamTo(SourceStream &s) const
643 {
644   s << SourceStream::Endl << "while (" << expr << ")" << SourceStream::Indent
645     << statement << SourceStream::Unindent;
646 }
647
648 void ForNode::streamTo(SourceStream &s) const
649 {
650   s << SourceStream::Endl << "for ("
651     << expr1
652     << "; " << expr2
653     << "; " << expr3
654     << ")" << SourceStream::Indent << statement << SourceStream::Unindent;
655 }
656
657 void ForInNode::streamTo(SourceStream &s) const
658 {
659   s << SourceStream::Endl << "for (";
660   if (varDecl)
661     s << "var " << varDecl;
662   else
663     s << lexpr;
664
665   s << " in " << expr << ")" << SourceStream::Indent
666     << statement << SourceStream::Unindent;
667 }
668
669 void ContinueNode::streamTo(SourceStream &s) const
670 {
671   s << SourceStream::Endl << "continue";
672   if (!ident.isNull())
673     s << " " << ident;
674   s << ";";
675 }
676
677 void BreakNode::streamTo(SourceStream &s) const
678 {
679   s << SourceStream::Endl << "break";
680   if (!ident.isNull())
681     s << " " << ident;
682   s << ";";
683 }
684
685 void ReturnNode::streamTo(SourceStream &s) const
686 {
687   s << SourceStream::Endl << "return";
688   if (value)
689     s << " " << value;
690   s << ";";
691 }
692
693 void WithNode::streamTo(SourceStream &s) const
694 {
695   s << SourceStream::Endl << "with (" << expr << ") "
696     << statement;
697 }
698
699 void CaseClauseNode::streamTo(SourceStream &s) const
700 {
701   s << SourceStream::Endl;
702   if (expr)
703     s << "case " << expr;
704   else
705     s << "default";
706   s << ":" << SourceStream::Indent;
707   if (source)
708     s << source;
709   s << SourceStream::Unindent;
710 }
711
712 void ClauseListNode::streamTo(SourceStream &s) const
713 {
714   for (const ClauseListNode *n = this; n; n = n->getNext())
715     s << n->getClause();
716 }
717
718 void CaseBlockNode::streamTo(SourceStream &s) const
719 {
720   for (const ClauseListNode *n = list1.get(); n; n = n->getNext())
721     s << n->getClause();
722   if (def)
723     s << def;
724   for (const ClauseListNode *n = list2.get(); n; n = n->getNext())
725     s << n->getClause();
726 }
727
728 void SwitchNode::streamTo(SourceStream &s) const
729 {
730   s << SourceStream::Endl << "switch (" << expr << ") {"
731     << SourceStream::Indent << block << SourceStream::Unindent
732     << SourceStream::Endl << "}";
733 }
734
735 void LabelNode::streamTo(SourceStream &s) const
736 {
737   s << SourceStream::Endl << label << ":" << SourceStream::Indent
738     << statement << SourceStream::Unindent;
739 }
740
741 void ThrowNode::streamTo(SourceStream &s) const
742 {
743   s << SourceStream::Endl << "throw " << expr << ";";
744 }
745
746 void TryNode::streamTo(SourceStream &s) const
747 {
748   s << SourceStream::Endl << "try " << tryBlock;
749   if (catchBlock)
750     s << SourceStream::Endl << "catch (" << exceptionIdent << ")" << catchBlock;
751   if (finallyBlock)
752     s << SourceStream::Endl << "finally " << finallyBlock;
753 }
754
755 void ParameterNode::streamTo(SourceStream &s) const
756 {
757   s << id;
758   for (ParameterNode *n = next.get(); n; n = n->next.get())
759     s << ", " << n->id;
760 }
761
762 void FuncDeclNode::streamTo(SourceStream &s) const
763 {
764   s << SourceStream::Endl << "function " << ident << "(" << param << ")" << body;
765 }
766
767 void FuncExprNode::streamTo(SourceStream &s) const
768 {
769   s << "function " << ident << "(" << param << ")" << body;
770 }
771
772 void SourceElementsNode::streamTo(SourceStream &s) const
773 {
774   for (const SourceElementsNode *n = this; n; n = n->next.get())
775     s << n->node;
776 }