JavaScriptCore:
[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 Apple Computer, Inc.
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
35     };
36
37     UString toString() const { return str; }
38     SourceStream& operator<<(const Identifier &);
39     SourceStream& operator<<(const UString &);
40     SourceStream& operator<<(const char *);
41     SourceStream& operator<<(char);
42     SourceStream& operator<<(Format f);
43     SourceStream& operator<<(const Node *);
44     template <typename T> SourceStream& operator<<(RefPtr<T> n) { return this->operator<<(n.get()); }
45   private:
46     UString str; /* TODO: buffer */
47     UString ind;
48   };
49 }
50
51 using namespace KJS;
52
53 SourceStream& SourceStream::operator<<(char c)
54 {
55   UChar ch(c);
56   str += UString(&ch, 1);
57   return *this;
58 }
59
60 SourceStream& SourceStream::operator<<(const char *s)
61 {
62   str += UString(s);
63   return *this;
64 }
65
66 SourceStream& SourceStream::operator<<(const UString &s)
67 {
68   str += s;
69   return *this;
70 }
71
72 SourceStream& SourceStream::operator<<(const Identifier &s)
73 {
74   str += s.ustring();
75   return *this;
76 }
77
78 SourceStream& SourceStream::operator<<(const Node *n)
79 {
80   if (n)
81     n->streamTo(*this);
82   return *this;
83 }
84
85 SourceStream& SourceStream::operator<<(Format f)
86 {
87   switch (f) {
88     case Endl:
89       str += "\n" + ind;
90       break;
91     case Indent:
92       ind += "  ";
93       break;
94     case Unindent:
95       ind = ind.substr(0, ind.size() - 2);
96       break;
97   }
98
99   return *this;
100 }
101
102 UString Node::toString() const
103 {
104   SourceStream str;
105   streamTo(str);
106
107   return str.toString();
108 }
109
110 void NullNode::streamTo(SourceStream &s) const { s << "null"; }
111
112 void BooleanNode::streamTo(SourceStream &s) const
113 {
114   s << (value ? "true" : "false");
115 }
116
117 void NumberNode::streamTo(SourceStream &s) const { s << UString::from(value); }
118
119 void StringNode::streamTo(SourceStream &s) const
120 {
121   s << '"' << escapeStringForPrettyPrinting(value) << '"';
122 }
123
124 void RegExpNode::streamTo(SourceStream &s) const
125
126     s << "/" <<  pattern << "/" << flags; 
127 }
128
129 void ThisNode::streamTo(SourceStream &s) const { s << "this"; }
130
131 void ResolveNode::streamTo(SourceStream &s) const { s << ident; }
132
133 void GroupNode::streamTo(SourceStream &s) const
134 {
135   s << "(" << group << ")"; 
136 }
137
138 void ElementNode::streamTo(SourceStream &s) const
139 {
140   for (const ElementNode *n = this; n; n = n->next.get()) {
141     for (int i = 0; i < n->elision; i++)
142       s << ",";
143     s << n->node;
144   }
145 }
146
147 void ArrayNode::streamTo(SourceStream &s) const
148 {
149   s << "[" << element;
150   for (int i = 0; i < elision; i++)
151     s << ",";
152   s << "]";
153 }
154
155 void ObjectLiteralNode::streamTo(SourceStream &s) const
156 {
157   if (list)
158     s << "{ " << list << " }";
159   else
160     s << "{ }";
161 }
162
163 void PropertyListNode::streamTo(SourceStream &s) const
164 {
165   s << node;
166   
167   for (const PropertyListNode *n = next.get(); n; n = n->next.get())
168     s << ", " << n->node;
169 }
170
171 void PropertyNode::streamTo(SourceStream &s) const
172 {
173   switch (type) {
174     case Constant:
175       s << name << ": " << assign;
176       break;
177     case Getter:
178     case Setter: {
179       const FuncExprNode *func = static_cast<const FuncExprNode *>(assign.get());
180       if (type == Getter)
181         s << "get "; 
182       else
183         s << "set ";
184       
185       s << name << "(" << func->param << ")" << func->body;
186       break;
187     }
188   }
189 }
190
191 void PropertyNameNode::streamTo(SourceStream &s) const
192 {
193   if (str.isNull())
194     s << UString::from(numeric);
195   else
196     s << str;
197 }
198
199 void BracketAccessorNode::streamTo(SourceStream &s) const
200 {
201   s << expr1 << "[" << expr2 << "]";
202 }
203
204 void DotAccessorNode::streamTo(SourceStream &s) const
205 {
206   s << expr << "." << ident;
207 }
208
209 void ArgumentListNode::streamTo(SourceStream &s) const
210 {
211   s << expr;
212   for (ArgumentListNode *n = next.get(); n; n = n->next.get())
213     s << ", " << n->expr;
214 }
215
216 void ArgumentsNode::streamTo(SourceStream &s) const
217 {
218   s << "(" << list << ")";
219 }
220
221 void NewExprNode::streamTo(SourceStream &s) const
222 {
223   s << "new " << expr << args;
224 }
225
226 void FunctionCallValueNode::streamTo(SourceStream &s) const
227 {
228   s << expr << args;
229 }
230
231 void FunctionCallResolveNode::streamTo(SourceStream &s) const
232 {
233   s << ident << args;
234 }
235
236 void FunctionCallBracketNode::streamTo(SourceStream &s) const
237 {
238   s << base << "[" << subscript << "]" << args;
239 }
240
241 void FunctionCallParenBracketNode::streamTo(SourceStream &s) const
242 {
243   s << "(" << base << "[" << subscript << "])" << args;
244 }
245
246 void FunctionCallDotNode::streamTo(SourceStream &s) const
247 {
248   s << base << "." << ident << args;
249 }
250
251 void FunctionCallParenDotNode::streamTo(SourceStream &s) const
252 {
253   s << "(" << base << "." << ident << ")" << args;
254 }
255
256 void PostfixResolveNode::streamTo(SourceStream &s) const
257 {
258   s << m_ident;
259   if (m_oper == OpPlusPlus)
260     s << "++";
261   else
262     s << "--";
263 }
264
265 void PostfixBracketNode::streamTo(SourceStream &s) const
266 {
267   s << m_base << "[" << m_subscript << "]";
268   if (m_oper == OpPlusPlus)
269     s << "++";
270   else
271     s << "--";
272 }
273
274 void PostfixDotNode::streamTo(SourceStream &s) const
275 {
276   s << m_base << "." << m_ident;
277   if (m_oper == OpPlusPlus)
278     s << "++";
279   else
280     s << "--";
281 }
282
283 void DeleteResolveNode::streamTo(SourceStream &s) const
284 {
285   s << "delete " << m_ident;
286 }
287
288 void DeleteBracketNode::streamTo(SourceStream &s) const
289 {
290   s << "delete " << m_base << "[" << m_subscript << "]";
291 }
292
293 void DeleteDotNode::streamTo(SourceStream &s) const
294 {
295   s << "delete " << m_base << "." << m_ident;
296 }
297
298 void DeleteValueNode::streamTo(SourceStream &s) const
299 {
300   s << "delete " << m_expr;
301 }
302
303 void VoidNode::streamTo(SourceStream &s) const
304 {
305   s << "void " << expr;
306 }
307
308 void TypeOfValueNode::streamTo(SourceStream &s) const
309 {
310   s << "typeof " << m_expr;
311 }
312
313 void TypeOfResolveNode::streamTo(SourceStream &s) const
314 {
315   s << "typeof " << m_ident;
316 }
317
318 void PrefixResolveNode::streamTo(SourceStream &s) const
319 {
320   if (m_oper == OpPlusPlus)
321     s << "++";
322   else
323     s << "--";
324   s << m_ident;
325 }
326
327 void PrefixBracketNode::streamTo(SourceStream &s) const
328 {
329   if (m_oper == OpPlusPlus)
330     s << "++";
331   else
332     s << "--";
333   s << m_base << "[" << m_subscript << "]";
334 }
335
336 void PrefixDotNode::streamTo(SourceStream &s) const
337 {
338   if (m_oper == OpPlusPlus)
339     s << "++";
340   else
341     s << "--";
342   s << m_base << "." << m_ident;
343 }
344
345 void UnaryPlusNode::streamTo(SourceStream &s) const
346 {
347   s << "+" << expr;
348 }
349
350 void NegateNode::streamTo(SourceStream &s) const
351 {
352   s << "-" << expr;
353 }
354
355 void BitwiseNotNode::streamTo(SourceStream &s) const
356 {
357   s << "~" << expr;
358 }
359
360 void LogicalNotNode::streamTo(SourceStream &s) const
361 {
362   s << "!" << expr;
363 }
364
365 void MultNode::streamTo(SourceStream &s) const
366 {
367   s << term1 << oper << term2;
368 }
369
370 void AddNode::streamTo(SourceStream &s) const
371 {
372   s << term1 << oper << term2;
373 }
374
375 void ShiftNode::streamTo(SourceStream &s) const
376 {
377   s << term1;
378   if (oper == OpLShift)
379     s << "<<";
380   else if (oper == OpRShift)
381     s << ">>";
382   else
383     s << ">>>";
384   s << term2;
385 }
386
387 void RelationalNode::streamTo(SourceStream &s) const
388 {
389   s << expr1;
390   switch (oper) {
391   case OpLess:
392     s << " < ";
393     break;
394   case OpGreater:
395     s << " > ";
396     break;
397   case OpLessEq:
398     s << " <= ";
399     break;
400   case OpGreaterEq:
401     s << " >= ";
402     break;
403   case OpInstanceOf:
404     s << " instanceof ";
405     break;
406   case OpIn:
407     s << " in ";
408     break;
409   default:
410     ;
411   }
412   s << expr2;
413 }
414
415 void EqualNode::streamTo(SourceStream &s) const
416 {
417   s << expr1;
418  switch (oper) {
419  case OpEqEq:
420    s << " == ";
421    break;
422  case OpNotEq:
423    s << " != ";
424    break;
425  case OpStrEq:
426    s << " === ";
427    break;
428  case OpStrNEq:
429    s << " !== ";
430    break;
431  default:
432    ;
433  }
434   s << expr2;
435 }
436
437 void BitOperNode::streamTo(SourceStream &s) const
438 {
439   s << expr1;
440   if (oper == OpBitAnd)
441     s << " & ";
442   else if (oper == OpBitXOr)
443     s << " ^ ";
444   else
445     s << " | ";
446   s << expr2;
447 }
448
449 void BinaryLogicalNode::streamTo(SourceStream &s) const
450 {
451   s << expr1 << (oper == OpAnd ? " && " : " || ") << expr2;
452 }
453
454 void ConditionalNode::streamTo(SourceStream &s) const
455 {
456   s << logical << " ? " << expr1 << " : " << expr2;
457 }
458
459 static void streamAssignmentOperatorTo(SourceStream &s, Operator oper)
460 {
461   const char *opStr;
462   switch (oper) {
463   case OpEqual:
464     opStr = " = ";
465     break;
466   case OpMultEq:
467     opStr = " *= ";
468     break;
469   case OpDivEq:
470     opStr = " /= ";
471     break;
472   case OpPlusEq:
473     opStr = " += ";
474     break;
475   case OpMinusEq:
476     opStr = " -= ";
477     break;
478   case OpLShift:
479     opStr = " <<= ";
480     break;
481   case OpRShift:
482     opStr = " >>= ";
483     break;
484   case OpURShift:
485     opStr = " >>>= ";
486     break;
487   case OpAndEq:
488     opStr = " &= ";
489     break;
490   case OpXOrEq:
491     opStr = " ^= ";
492     break;
493   case OpOrEq:
494     opStr = " |= ";
495     break;
496   case OpModEq:
497     opStr = " %= ";
498     break;
499   default:
500     opStr = " ?= ";
501   }
502   s << opStr;
503 }
504
505 void AssignResolveNode::streamTo(SourceStream &s) const
506 {
507   s << m_ident;
508   streamAssignmentOperatorTo(s, m_oper);
509   s << m_right;
510 }
511
512 void AssignBracketNode::streamTo(SourceStream &s) const
513 {
514   s << m_base << "[" << m_subscript << "]";
515   streamAssignmentOperatorTo(s, m_oper);
516   s << m_right;
517 }
518
519 void AssignDotNode::streamTo(SourceStream &s) const
520 {
521   s << m_base << "." << m_ident;
522   streamAssignmentOperatorTo(s, m_oper);
523   s << m_right;
524 }
525
526 void CommaNode::streamTo(SourceStream &s) const
527 {
528   s << expr1 << ", " << expr2;
529 }
530
531 void AssignExprNode::streamTo(SourceStream &s) const
532 {
533   s << " = " << expr;
534 }
535
536 void VarDeclNode::streamTo(SourceStream &s) const
537 {
538   s << ident << init;
539 }
540
541 void VarDeclListNode::streamTo(SourceStream &s) const
542 {
543   s << var;
544   for (VarDeclListNode *n = next.get(); n; n = n->next.get())
545     s << ", " << n->var;
546 }
547
548 void VarStatementNode::streamTo(SourceStream &s) const
549 {
550   s << SourceStream::Endl << "var " << next << ";";
551 }
552
553 void BlockNode::streamTo(SourceStream &s) const
554 {
555   s << SourceStream::Endl << "{" << SourceStream::Indent
556     << source << SourceStream::Unindent << SourceStream::Endl << "}";
557 }
558
559 void EmptyStatementNode::streamTo(SourceStream &s) const
560 {
561   s << SourceStream::Endl << ";";
562 }
563
564 void ExprStatementNode::streamTo(SourceStream &s) const
565 {
566   s << SourceStream::Endl << expr << ";";
567 }
568
569 void IfNode::streamTo(SourceStream &s) const
570 {
571   s << SourceStream::Endl << "if (" << expr << ")" << SourceStream::Indent
572     << statement1 << SourceStream::Unindent;
573   if (statement2)
574     s << SourceStream::Endl << "else" << SourceStream::Indent
575       << statement2 << SourceStream::Unindent;
576 }
577
578 void DoWhileNode::streamTo(SourceStream &s) const
579 {
580   s << SourceStream::Endl << "do " << SourceStream::Indent
581     << statement << SourceStream::Unindent << SourceStream::Endl
582     << "while (" << expr << ");";
583 }
584
585 void WhileNode::streamTo(SourceStream &s) const
586 {
587   s << SourceStream::Endl << "while (" << expr << ")" << SourceStream::Indent
588     << statement << SourceStream::Unindent;
589 }
590
591 void ForNode::streamTo(SourceStream &s) const
592 {
593   s << SourceStream::Endl << "for ("
594     << expr1  // TODO: doesn't properly do "var i = 0"
595     << "; " << expr2
596     << "; " << expr3
597     << ")" << SourceStream::Indent << statement << SourceStream::Unindent;
598 }
599
600 void ForInNode::streamTo(SourceStream &s) const
601 {
602   s << SourceStream::Endl << "for (";
603   if (varDecl)
604     s << "var " << varDecl;
605   else
606     s << lexpr;
607   
608   if (init)
609     s << " = " << init;
610   s << " in " << expr << ")" << SourceStream::Indent
611     << statement << SourceStream::Unindent;
612 }
613
614 void ContinueNode::streamTo(SourceStream &s) const
615 {
616   s << SourceStream::Endl << "continue";
617   if (!ident.isNull())
618     s << " " << ident;
619   s << ";";
620 }
621
622 void BreakNode::streamTo(SourceStream &s) const
623 {
624   s << SourceStream::Endl << "break";
625   if (!ident.isNull())
626     s << " " << ident;
627   s << ";";
628 }
629
630 void ReturnNode::streamTo(SourceStream &s) const
631 {
632   s << SourceStream::Endl << "return";
633   if (value)
634     s << " " << value;
635   s << ";";
636 }
637
638 void WithNode::streamTo(SourceStream &s) const
639 {
640   s << SourceStream::Endl << "with (" << expr << ") "
641     << statement;
642 }
643
644 void CaseClauseNode::streamTo(SourceStream &s) const
645 {
646   s << SourceStream::Endl;
647   if (expr)
648     s << "case " << expr;
649   else
650     s << "default";
651   s << ":" << SourceStream::Indent;
652   if (source)
653     s << source;
654   s << SourceStream::Unindent;
655 }
656
657 void ClauseListNode::streamTo(SourceStream &s) const
658 {
659   for (const ClauseListNode *n = this; n; n = n->getNext())
660     s << n->getClause();
661 }
662
663 void CaseBlockNode::streamTo(SourceStream &s) const
664 {
665   for (const ClauseListNode *n = list1.get(); n; n = n->getNext())
666     s << n->getClause();
667   if (def)
668     s << def;
669   for (const ClauseListNode *n = list2.get(); n; n = n->getNext())
670     s << n->getClause();
671 }
672
673 void SwitchNode::streamTo(SourceStream &s) const
674 {
675   s << SourceStream::Endl << "switch (" << expr << ") {"
676     << SourceStream::Indent << block << SourceStream::Unindent
677     << SourceStream::Endl << "}";
678 }
679
680 void LabelNode::streamTo(SourceStream &s) const
681 {
682   s << SourceStream::Endl << label << ":" << SourceStream::Indent
683     << statement << SourceStream::Unindent;
684 }
685
686 void ThrowNode::streamTo(SourceStream &s) const
687 {
688   s << SourceStream::Endl << "throw " << expr << ";";
689 }
690
691 void TryNode::streamTo(SourceStream &s) const
692 {
693   s << "try " << tryBlock;
694   if (catchBlock)
695     s << SourceStream::Endl << "catch (" << exceptionIdent << ")" << catchBlock;
696   if (finallyBlock)
697     s << SourceStream::Endl << "finally " << finallyBlock;
698 }
699
700 void ParameterNode::streamTo(SourceStream &s) const
701 {
702   s << id;
703   for (ParameterNode *n = next.get(); n; n = n->next.get())
704     s << ", " << n->id;
705 }
706
707 void FuncDeclNode::streamTo(SourceStream &s) const
708 {
709   s << SourceStream::Endl << "function " << ident << "(" << param << ")" << body;
710 }
711
712 void FuncExprNode::streamTo(SourceStream &s) const
713 {
714   s << "function " << ident << "(" << param << ")" << body;
715 }
716
717 void SourceElementsNode::streamTo(SourceStream &s) const
718 {
719   for (const SourceElementsNode *n = this; n; n = n->next.get())
720     s << n->node;
721 }