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