caff9f19aa8ebc75dde1679d0261b111a8893a65
[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
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 AssignExprNode::streamTo(SourceStream &s) const
527 {
528   s << " = " << expr;
529 }
530
531 void VarDeclNode::streamTo(SourceStream &s) const
532 {
533   s << ident << init;
534 }
535
536 void VarDeclListNode::streamTo(SourceStream &s) const
537 {
538   s << var;
539   for (VarDeclListNode *n = next.get(); n; n = n->next.get())
540     s << ", " << n->var;
541 }
542
543 void VarStatementNode::streamTo(SourceStream &s) const
544 {
545   s << SourceStream::Endl << "var " << next << ";";
546 }
547
548 void BlockNode::streamTo(SourceStream &s) const
549 {
550   s << SourceStream::Endl << "{" << SourceStream::Indent
551     << source << SourceStream::Unindent << SourceStream::Endl << "}";
552 }
553
554 void EmptyStatementNode::streamTo(SourceStream &s) const
555 {
556   s << SourceStream::Endl << ";";
557 }
558
559 void ExprStatementNode::streamTo(SourceStream &s) const
560 {
561   s << SourceStream::Endl << expr << ";";
562 }
563
564 void IfNode::streamTo(SourceStream &s) const
565 {
566   s << SourceStream::Endl << "if (" << expr << ")" << SourceStream::Indent
567     << statement1 << SourceStream::Unindent;
568   if (statement2)
569     s << SourceStream::Endl << "else" << SourceStream::Indent
570       << statement2 << SourceStream::Unindent;
571 }
572
573 void DoWhileNode::streamTo(SourceStream &s) const
574 {
575   s << SourceStream::Endl << "do " << SourceStream::Indent
576     << statement << SourceStream::Unindent << SourceStream::Endl
577     << "while (" << expr << ");";
578 }
579
580 void WhileNode::streamTo(SourceStream &s) const
581 {
582   s << SourceStream::Endl << "while (" << expr << ")" << SourceStream::Indent
583     << statement << SourceStream::Unindent;
584 }
585
586 void ForNode::streamTo(SourceStream &s) const
587 {
588   s << SourceStream::Endl << "for ("
589     << expr1  // TODO: doesn't properly do "var i = 0"
590     << "; " << expr2
591     << "; " << expr3
592     << ")" << SourceStream::Indent << statement << SourceStream::Unindent;
593 }
594
595 void ForInNode::streamTo(SourceStream &s) const
596 {
597   s << SourceStream::Endl << "for (";
598   if (varDecl)
599     s << "var " << varDecl;
600   else
601     s << lexpr;
602   
603   if (init)
604     s << " = " << init;
605   s << " in " << expr << ")" << SourceStream::Indent
606     << statement << SourceStream::Unindent;
607 }
608
609 void ContinueNode::streamTo(SourceStream &s) const
610 {
611   s << SourceStream::Endl << "continue";
612   if (!ident.isNull())
613     s << " " << ident;
614   s << ";";
615 }
616
617 void BreakNode::streamTo(SourceStream &s) const
618 {
619   s << SourceStream::Endl << "break";
620   if (!ident.isNull())
621     s << " " << ident;
622   s << ";";
623 }
624
625 void ReturnNode::streamTo(SourceStream &s) const
626 {
627   s << SourceStream::Endl << "return";
628   if (value)
629     s << " " << value;
630   s << ";";
631 }
632
633 void WithNode::streamTo(SourceStream &s) const
634 {
635   s << SourceStream::Endl << "with (" << expr << ") "
636     << statement;
637 }
638
639 void CaseClauseNode::streamTo(SourceStream &s) const
640 {
641   s << SourceStream::Endl;
642   if (expr)
643     s << "case " << expr;
644   else
645     s << "default";
646   s << ":" << SourceStream::Indent;
647   if (source)
648     s << source;
649   s << SourceStream::Unindent;
650 }
651
652 void ClauseListNode::streamTo(SourceStream &s) const
653 {
654   for (const ClauseListNode *n = this; n; n = n->getNext())
655     s << n->getClause();
656 }
657
658 void CaseBlockNode::streamTo(SourceStream &s) const
659 {
660   for (const ClauseListNode *n = list1.get(); n; n = n->getNext())
661     s << n->getClause();
662   if (def)
663     s << def;
664   for (const ClauseListNode *n = list2.get(); n; n = n->getNext())
665     s << n->getClause();
666 }
667
668 void SwitchNode::streamTo(SourceStream &s) const
669 {
670   s << SourceStream::Endl << "switch (" << expr << ") {"
671     << SourceStream::Indent << block << SourceStream::Unindent
672     << SourceStream::Endl << "}";
673 }
674
675 void LabelNode::streamTo(SourceStream &s) const
676 {
677   s << SourceStream::Endl << label << ":" << SourceStream::Indent
678     << statement << SourceStream::Unindent;
679 }
680
681 void ThrowNode::streamTo(SourceStream &s) const
682 {
683   s << SourceStream::Endl << "throw " << expr << ";";
684 }
685
686 void TryNode::streamTo(SourceStream &s) const
687 {
688   s << "try " << tryBlock;
689   if (catchBlock)
690     s << SourceStream::Endl << "catch (" << exceptionIdent << ")" << catchBlock;
691   if (finallyBlock)
692     s << SourceStream::Endl << "finally " << finallyBlock;
693 }
694
695 void ParameterNode::streamTo(SourceStream &s) const
696 {
697   s << id;
698   for (ParameterNode *n = next.get(); n; n = n->next.get())
699     s << ", " << n->id;
700 }
701
702 void FuncDeclNode::streamTo(SourceStream &s) const
703 {
704   s << SourceStream::Endl << "function " << ident << "(" << param << ")" << body;
705 }
706
707 void FuncExprNode::streamTo(SourceStream &s) const
708 {
709   s << "function " << ident << "(" << param << ")" << body;
710 }
711
712 void SourceElementsNode::streamTo(SourceStream &s) const
713 {
714   for (const SourceElementsNode *n = this; n; n = n->next.get())
715     s << n->node;
716 }