source: webkit/trunk/JavaScriptCore/kjs/nodes2string.cpp@ 31148

Last change on this file since 31148 was 31148, checked in by [email protected], 17 years ago

Bug 17929: Incorrect decompilation with |const|, comma
http://bugs.webkit.org/show_bug.cgi?id=17929

Reviewed by Mark Rowe

There were actually two bugs here. First we weren't correctly handling const
nodes with multiple declarations. The second issue was caused by us not
giving the correct precedence to the initialisers.

  • Property svn:eol-style set to native
File size: 23.4 KB
Line 
1/*
2 * Copyright (C) 2002 Harri Porten ([email protected])
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Eric Seidel <[email protected]>
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#include <wtf/MathExtras.h>
27#include <wtf/StringExtras.h>
28#include <wtf/unicode/Unicode.h>
29
30using namespace WTF;
31using namespace Unicode;
32
33namespace KJS {
34
35// A simple text streaming class that helps with code indentation.
36
37enum EndlType { Endl };
38enum IndentType { Indent };
39enum UnindentType { Unindent };
40enum DotExprType { DotExpr };
41
42class SourceStream {
43public:
44 SourceStream()
45 : m_numberNeedsParens(false)
46 , m_atStartOfStatement(true)
47 , m_precedence(PrecExpression)
48 {
49 }
50
51 UString toString() const { return m_string; }
52
53 SourceStream& operator<<(const Identifier&);
54 SourceStream& operator<<(const UString&);
55 SourceStream& operator<<(const char*);
56 SourceStream& operator<<(double);
57 SourceStream& operator<<(char);
58 SourceStream& operator<<(EndlType);
59 SourceStream& operator<<(IndentType);
60 SourceStream& operator<<(UnindentType);
61 SourceStream& operator<<(DotExprType);
62 SourceStream& operator<<(Precedence);
63 SourceStream& operator<<(const Node*);
64 template <typename T> SourceStream& operator<<(const RefPtr<T>& n) { return *this << n.get(); }
65
66private:
67 UString m_string;
68 UString m_spacesForIndentation;
69 bool m_numberNeedsParens;
70 bool m_atStartOfStatement;
71 Precedence m_precedence;
72};
73
74// --------
75
76static UString escapeStringForPrettyPrinting(const UString& s)
77{
78 UString escapedString;
79
80 for (int i = 0; i < s.size(); i++) {
81 UChar c = s.data()[i];
82 switch (c) {
83 case '\"':
84 escapedString += "\\\"";
85 break;
86 case '\n':
87 escapedString += "\\n";
88 break;
89 case '\r':
90 escapedString += "\\r";
91 break;
92 case '\t':
93 escapedString += "\\t";
94 break;
95 case '\\':
96 escapedString += "\\\\";
97 break;
98 default:
99 if (c < 128 && isPrintableChar(c))
100 escapedString.append(c);
101 else {
102 char hexValue[7];
103 snprintf(hexValue, 7, "\\u%04x", c);
104 escapedString += hexValue;
105 }
106 }
107 }
108
109 return escapedString;
110}
111
112static const char* operatorString(Operator oper)
113{
114 switch (oper) {
115 case OpEqual:
116 return "=";
117 case OpMultEq:
118 return "*=";
119 case OpDivEq:
120 return "/=";
121 case OpPlusEq:
122 return "+=";
123 case OpMinusEq:
124 return "-=";
125 case OpLShift:
126 return "<<=";
127 case OpRShift:
128 return ">>=";
129 case OpURShift:
130 return ">>>=";
131 case OpAndEq:
132 return "&=";
133 case OpXOrEq:
134 return "^=";
135 case OpOrEq:
136 return "|=";
137 case OpModEq:
138 return "%=";
139 case OpPlusPlus:
140 return "++";
141 case OpMinusMinus:
142 return "--";
143 }
144 ASSERT_NOT_REACHED();
145 return "???";
146}
147
148static bool isParserRoundTripNumber(const UString& string)
149{
150 double number = string.toDouble(false, false);
151 if (isnan(number) || isinf(number))
152 return false;
153 return string == UString::from(number);
154}
155
156// --------
157
158SourceStream& SourceStream::operator<<(char c)
159{
160 m_numberNeedsParens = false;
161 m_atStartOfStatement = false;
162 // use unsigned char to zero-extend instead of sign-extend
163 UChar ch(static_cast<unsigned char>(c));
164 m_string.append(ch);
165 return *this;
166}
167
168SourceStream& SourceStream::operator<<(const char* s)
169{
170 m_numberNeedsParens = false;
171 m_atStartOfStatement = false;
172 m_string += s;
173 return *this;
174}
175
176SourceStream& SourceStream::operator<<(double value)
177{
178 bool needParens = m_numberNeedsParens;
179 m_numberNeedsParens = false;
180 m_atStartOfStatement = false;
181
182 if (needParens)
183 m_string.append('(');
184 m_string += UString::from(value);
185 if (needParens)
186 m_string.append(')');
187
188 return *this;
189}
190
191SourceStream& SourceStream::operator<<(const UString& s)
192{
193 m_numberNeedsParens = false;
194 m_atStartOfStatement = false;
195 m_string += s;
196 return *this;
197}
198
199SourceStream& SourceStream::operator<<(const Identifier& s)
200{
201 m_numberNeedsParens = false;
202 m_atStartOfStatement = false;
203 m_string += s.ustring();
204 return *this;
205}
206
207SourceStream& SourceStream::operator<<(const Node* n)
208{
209 bool needParens = (m_precedence != PrecExpression && n->precedence() > m_precedence) || (m_atStartOfStatement && n->needsParensIfLeftmost());
210 m_precedence = PrecExpression;
211 if (!n)
212 return *this;
213 if (needParens) {
214 m_numberNeedsParens = false;
215 m_string.append('(');
216 }
217 n->streamTo(*this);
218 if (needParens)
219 m_string.append(')');
220 return *this;
221}
222
223SourceStream& SourceStream::operator<<(EndlType)
224{
225 m_numberNeedsParens = false;
226 m_atStartOfStatement = true;
227 m_string.append('\n');
228 m_string.append(m_spacesForIndentation);
229 return *this;
230}
231
232SourceStream& SourceStream::operator<<(IndentType)
233{
234 m_numberNeedsParens = false;
235 m_atStartOfStatement = false;
236 m_spacesForIndentation += " ";
237 return *this;
238}
239
240SourceStream& SourceStream::operator<<(UnindentType)
241{
242 m_numberNeedsParens = false;
243 m_atStartOfStatement = false;
244 m_spacesForIndentation = m_spacesForIndentation.substr(0, m_spacesForIndentation.size() - 2);
245 return *this;
246}
247
248inline SourceStream& SourceStream::operator<<(DotExprType)
249{
250 m_numberNeedsParens = true;
251 return *this;
252}
253
254inline SourceStream& SourceStream::operator<<(Precedence precedence)
255{
256 m_precedence = precedence;
257 return *this;
258}
259
260static void streamLeftAssociativeBinaryOperator(SourceStream& s, Precedence precedence,
261 const char* operatorString, const Node* left, const Node* right)
262{
263 s << precedence << left
264 << ' ' << operatorString << ' '
265 << static_cast<Precedence>(precedence - 1) << right;
266}
267
268template <typename T> static inline void streamLeftAssociativeBinaryOperator(SourceStream& s,
269 Precedence p, const char* o, const RefPtr<T>& l, const RefPtr<T>& r)
270{
271 streamLeftAssociativeBinaryOperator(s, p, o, l.get(), r.get());
272}
273
274static inline void bracketNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const RefPtr<ExpressionNode>& subscript)
275{
276 s << PrecCall << base.get() << "[" << subscript.get() << "]";
277}
278
279static inline void dotNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const Identifier& ident)
280{
281 s << DotExpr << PrecCall << base.get() << "." << ident;
282}
283
284// --------
285
286UString Node::toString() const
287{
288 SourceStream stream;
289 streamTo(stream);
290 return stream.toString();
291}
292
293// --------
294
295void NullNode::streamTo(SourceStream& s) const
296{
297 s << "null";
298}
299
300void FalseNode::streamTo(SourceStream& s) const
301{
302 s << "false";
303}
304
305void TrueNode::streamTo(SourceStream& s) const
306{
307 s << "true";
308}
309
310void PlaceholderTrueNode::streamTo(SourceStream&) const
311{
312}
313
314void NumberNode::streamTo(SourceStream& s) const
315{
316 s << value();
317}
318
319void StringNode::streamTo(SourceStream& s) const
320{
321 s << '"' << escapeStringForPrettyPrinting(m_value) << '"';
322}
323
324void RegExpNode::streamTo(SourceStream& s) const
325{
326 s << '/' << m_regExp->pattern() << '/' << m_regExp->flags();
327}
328
329void ThisNode::streamTo(SourceStream& s) const
330{
331 s << "this";
332}
333
334void ResolveNode::streamTo(SourceStream& s) const
335{
336 s << m_ident;
337}
338
339void ElementNode::streamTo(SourceStream& s) const
340{
341 for (const ElementNode* n = this; n; n = n->m_next.get()) {
342 for (int i = 0; i < n->m_elision; i++)
343 s << ',';
344 s << PrecAssignment << n->m_node;
345 if (n->m_next)
346 s << ',';
347 }
348}
349
350void ArrayNode::streamTo(SourceStream& s) const
351{
352 s << '[' << m_element;
353 for (int i = 0; i < m_elision; i++)
354 s << ',';
355 // Parser consumes one elision comma if there's array elements
356 // present in the expression.
357 if (m_optional && m_element)
358 s << ',';
359 s << ']';
360}
361
362void ObjectLiteralNode::streamTo(SourceStream& s) const
363{
364 if (m_list)
365 s << "{ " << m_list << " }";
366 else
367 s << "{ }";
368}
369
370void PropertyListNode::streamTo(SourceStream& s) const
371{
372 s << m_node;
373 for (const PropertyListNode* n = m_next.get(); n; n = n->m_next.get())
374 s << ", " << n->m_node;
375}
376
377void PropertyNode::streamTo(SourceStream& s) const
378{
379 switch (m_type) {
380 case Constant: {
381 UString propertyName = name().ustring();
382 if (isParserRoundTripNumber(propertyName))
383 s << propertyName;
384 else
385 s << '"' << escapeStringForPrettyPrinting(propertyName) << '"';
386 s << ": " << PrecAssignment << m_assign;
387 break;
388 }
389 case Getter:
390 case Setter: {
391 const FuncExprNode* func = static_cast<const FuncExprNode*>(m_assign.get());
392 if (m_type == Getter)
393 s << "get ";
394 else
395 s << "set ";
396 s << escapeStringForPrettyPrinting(name().ustring())
397 << "(" << func->m_parameter << ')' << func->m_body;
398 break;
399 }
400 }
401}
402
403void BracketAccessorNode::streamTo(SourceStream& s) const
404{
405 bracketNodeStreamTo(s, m_base, m_subscript);
406}
407
408void DotAccessorNode::streamTo(SourceStream& s) const
409{
410 dotNodeStreamTo(s, m_base, m_ident);
411}
412
413void ArgumentListNode::streamTo(SourceStream& s) const
414{
415 s << PrecAssignment << m_expr;
416 for (ArgumentListNode* n = m_next.get(); n; n = n->m_next.get())
417 s << ", " << PrecAssignment << n->m_expr;
418}
419
420void ArgumentsNode::streamTo(SourceStream& s) const
421{
422 s << '(' << m_listNode << ')';
423}
424
425void NewExprNode::streamTo(SourceStream& s) const
426{
427 s << "new " << PrecMember << m_expr << m_args;
428}
429
430void EvalFunctionCallNode::streamTo(SourceStream& s) const
431{
432 s << "eval" << m_args;
433}
434
435void FunctionCallValueNode::streamTo(SourceStream& s) const
436{
437 s << PrecCall << m_expr << m_args;
438}
439
440void FunctionCallResolveNode::streamTo(SourceStream& s) const
441{
442 s << m_ident << m_args;
443}
444
445void FunctionCallBracketNode::streamTo(SourceStream& s) const
446{
447 bracketNodeStreamTo(s, m_base, m_subscript);
448 s << m_args;
449}
450
451void FunctionCallDotNode::streamTo(SourceStream& s) const
452{
453 dotNodeStreamTo(s, m_base, m_ident);
454 s << m_args;
455}
456
457void PostIncResolveNode::streamTo(SourceStream& s) const
458{
459 s << m_ident << "++";
460}
461
462void PostDecResolveNode::streamTo(SourceStream& s) const
463{
464 s << m_ident << "--";
465}
466
467void PostIncBracketNode::streamTo(SourceStream& s) const
468{
469 bracketNodeStreamTo(s, m_base, m_subscript);
470 s << "++";
471}
472
473void PostDecBracketNode::streamTo(SourceStream& s) const
474{
475 bracketNodeStreamTo(s, m_base, m_subscript);
476 s << "--";
477}
478
479void PostIncDotNode::streamTo(SourceStream& s) const
480{
481 dotNodeStreamTo(s, m_base, m_ident);
482 s << "++";
483}
484
485void PostDecDotNode::streamTo(SourceStream& s) const
486{
487 dotNodeStreamTo(s, m_base, m_ident);
488 s << "--";
489}
490
491void PostfixErrorNode::streamTo(SourceStream& s) const
492{
493 s << PrecLeftHandSide << m_expr;
494 if (m_operator == OpPlusPlus)
495 s << "++";
496 else
497 s << "--";
498}
499
500void DeleteResolveNode::streamTo(SourceStream& s) const
501{
502 s << "delete " << m_ident;
503}
504
505void DeleteBracketNode::streamTo(SourceStream& s) const
506{
507 s << "delete ";
508 bracketNodeStreamTo(s, m_base, m_subscript);
509}
510
511void DeleteDotNode::streamTo(SourceStream& s) const
512{
513 s << "delete ";
514 dotNodeStreamTo(s, m_base, m_ident);
515}
516
517void DeleteValueNode::streamTo(SourceStream& s) const
518{
519 s << "delete " << PrecUnary << m_expr;
520}
521
522void VoidNode::streamTo(SourceStream& s) const
523{
524 s << "void " << PrecUnary << m_expr;
525}
526
527void TypeOfValueNode::streamTo(SourceStream& s) const
528{
529 s << "typeof " << PrecUnary << m_expr;
530}
531
532void TypeOfResolveNode::streamTo(SourceStream& s) const
533{
534 s << "typeof " << m_ident;
535}
536
537void PreIncResolveNode::streamTo(SourceStream& s) const
538{
539 s << "++" << m_ident;
540}
541
542void PreDecResolveNode::streamTo(SourceStream& s) const
543{
544 s << "--" << m_ident;
545}
546
547void PreIncBracketNode::streamTo(SourceStream& s) const
548{
549 s << "++";
550 bracketNodeStreamTo(s, m_base, m_subscript);
551}
552
553void PreDecBracketNode::streamTo(SourceStream& s) const
554{
555 s << "--";
556 bracketNodeStreamTo(s, m_base, m_subscript);
557}
558
559void PreIncDotNode::streamTo(SourceStream& s) const
560{
561 s << "++";
562 dotNodeStreamTo(s, m_base, m_ident);
563}
564
565void PreDecDotNode::streamTo(SourceStream& s) const
566{
567 s << "--";
568 dotNodeStreamTo(s, m_base, m_ident);
569}
570
571void PrefixErrorNode::streamTo(SourceStream& s) const
572{
573 if (m_operator == OpPlusPlus)
574 s << "++" << PrecUnary << m_expr;
575 else
576 s << "--" << PrecUnary << m_expr;
577}
578
579void UnaryPlusNode::streamTo(SourceStream& s) const
580{
581 s << "+ " << PrecUnary << m_expr;
582}
583
584void NegateNode::streamTo(SourceStream& s) const
585{
586 s << "- " << PrecUnary << m_expr;
587}
588
589void BitwiseNotNode::streamTo(SourceStream& s) const
590{
591 s << "~" << PrecUnary << m_expr;
592}
593
594void LogicalNotNode::streamTo(SourceStream& s) const
595{
596 s << "!" << PrecUnary << m_expr;
597}
598
599void MultNode::streamTo(SourceStream& s) const
600{
601 streamLeftAssociativeBinaryOperator(s, precedence(), "*", m_term1, m_term2);
602}
603
604void DivNode::streamTo(SourceStream& s) const
605{
606 streamLeftAssociativeBinaryOperator(s, precedence(), "/", m_term1, m_term2);
607}
608
609void ModNode::streamTo(SourceStream& s) const
610{
611 streamLeftAssociativeBinaryOperator(s, precedence(), "%", m_term1, m_term2);
612}
613
614void AddNode::streamTo(SourceStream& s) const
615{
616 streamLeftAssociativeBinaryOperator(s, precedence(), "+", m_term1, m_term2);
617}
618
619void SubNode::streamTo(SourceStream& s) const
620{
621 streamLeftAssociativeBinaryOperator(s, precedence(), "-", m_term1, m_term2);
622}
623
624void LeftShiftNode::streamTo(SourceStream& s) const
625{
626 streamLeftAssociativeBinaryOperator(s, precedence(), "<<", m_term1, m_term2);
627}
628
629void RightShiftNode::streamTo(SourceStream& s) const
630{
631 streamLeftAssociativeBinaryOperator(s, precedence(), ">>", m_term1, m_term2);
632}
633
634void UnsignedRightShiftNode::streamTo(SourceStream& s) const
635{
636 streamLeftAssociativeBinaryOperator(s, precedence(), ">>>", m_term1, m_term2);
637}
638
639void LessNode::streamTo(SourceStream& s) const
640{
641 streamLeftAssociativeBinaryOperator(s, precedence(), "<", m_expr1, m_expr2);
642}
643
644void GreaterNode::streamTo(SourceStream& s) const
645{
646 streamLeftAssociativeBinaryOperator(s, precedence(), ">", m_expr1, m_expr2);
647}
648
649void LessEqNode::streamTo(SourceStream& s) const
650{
651 streamLeftAssociativeBinaryOperator(s, precedence(), "<=", m_expr1, m_expr2);
652}
653
654void GreaterEqNode::streamTo(SourceStream& s) const
655{
656 streamLeftAssociativeBinaryOperator(s, precedence(), ">=", m_expr1, m_expr2);
657}
658
659void InstanceOfNode::streamTo(SourceStream& s) const
660{
661 streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", m_expr1, m_expr2);
662}
663
664void InNode::streamTo(SourceStream& s) const
665{
666 streamLeftAssociativeBinaryOperator(s, precedence(), "in", m_expr1, m_expr2);
667}
668
669void EqualNode::streamTo(SourceStream& s) const
670{
671 streamLeftAssociativeBinaryOperator(s, precedence(), "==", m_expr1, m_expr2);
672}
673
674void NotEqualNode::streamTo(SourceStream& s) const
675{
676 streamLeftAssociativeBinaryOperator(s, precedence(), "!=", m_expr1, m_expr2);
677}
678
679void StrictEqualNode::streamTo(SourceStream& s) const
680{
681 streamLeftAssociativeBinaryOperator(s, precedence(), "===", m_expr1, m_expr2);
682}
683
684void NotStrictEqualNode::streamTo(SourceStream& s) const
685{
686 streamLeftAssociativeBinaryOperator(s, precedence(), "!==", m_expr1, m_expr2);
687}
688
689void BitAndNode::streamTo(SourceStream& s) const
690{
691 streamLeftAssociativeBinaryOperator(s, precedence(), "&", m_expr1, m_expr2);
692}
693
694void BitXOrNode::streamTo(SourceStream& s) const
695{
696 streamLeftAssociativeBinaryOperator(s, precedence(), "^", m_expr1, m_expr2);
697}
698
699void BitOrNode::streamTo(SourceStream& s) const
700{
701 streamLeftAssociativeBinaryOperator(s, precedence(), "|", m_expr1, m_expr2);
702}
703
704void LogicalAndNode::streamTo(SourceStream& s) const
705{
706 streamLeftAssociativeBinaryOperator(s, precedence(), "&&", m_expr1, m_expr2);
707}
708
709void LogicalOrNode::streamTo(SourceStream& s) const
710{
711 streamLeftAssociativeBinaryOperator(s, precedence(), "||", m_expr1, m_expr2);
712}
713
714void ConditionalNode::streamTo(SourceStream& s) const
715{
716 s << PrecLogicalOr << m_logical
717 << " ? " << PrecAssignment << m_expr1
718 << " : " << PrecAssignment << m_expr2;
719}
720
721void ReadModifyResolveNode::streamTo(SourceStream& s) const
722{
723 s << m_ident << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
724}
725
726void AssignResolveNode::streamTo(SourceStream& s) const
727{
728 s << m_ident << " = " << PrecAssignment << m_right;
729}
730
731void ReadModifyBracketNode::streamTo(SourceStream& s) const
732{
733 bracketNodeStreamTo(s, m_base, m_subscript);
734 s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
735}
736
737void AssignBracketNode::streamTo(SourceStream& s) const
738{
739 bracketNodeStreamTo(s, m_base, m_subscript);
740 s << " = " << PrecAssignment << m_right;
741}
742
743void ReadModifyDotNode::streamTo(SourceStream& s) const
744{
745 dotNodeStreamTo(s, m_base, m_ident);
746 s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
747}
748
749void AssignDotNode::streamTo(SourceStream& s) const
750{
751 dotNodeStreamTo(s, m_base, m_ident);
752 s << " = " << PrecAssignment << m_right;
753}
754
755void AssignErrorNode::streamTo(SourceStream& s) const
756{
757 s << PrecLeftHandSide << m_left << ' '
758 << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
759}
760
761void CommaNode::streamTo(SourceStream& s) const
762{
763 s << PrecAssignment << m_expr1 << ", " << PrecAssignment << m_expr2;
764}
765
766void ConstDeclNode::streamTo(SourceStream& s) const
767{
768 s << m_ident;
769 if (m_init)
770 s << " = " << PrecAssignment << m_init;
771 for (ConstDeclNode* n = m_next.get(); n; n = n->m_next.get()) {
772 s << ", " << n->m_ident;
773 if (m_init)
774 s << " = " << PrecAssignment << n->m_init;
775 }
776}
777
778void ConstStatementNode::streamTo(SourceStream& s) const
779{
780 s << Endl << "const " << m_next << ';';
781}
782
783static inline void statementListStreamTo(const Vector<RefPtr<StatementNode> >& nodes, SourceStream& s)
784{
785 for (Vector<RefPtr<StatementNode> >::const_iterator ptr = nodes.begin(); ptr != nodes.end(); ptr++)
786 s << *ptr;
787}
788
789void BlockNode::streamTo(SourceStream& s) const
790{
791 s << Endl << "{" << Indent;
792 statementListStreamTo(m_children, s);
793 s << Unindent << Endl << "}";
794}
795
796void ScopeNode::streamTo(SourceStream& s) const
797{
798 s << Endl << "{" << Indent;
799
800 bool printedVar = false;
801 for (size_t i = 0; i < m_varStack.size(); ++i) {
802 if (m_varStack[i].second == 0) {
803 if (!printedVar) {
804 s << Endl << "var ";
805 printedVar = true;
806 } else
807 s << ", ";
808 s << m_varStack[i].first;
809 }
810 }
811 if (printedVar)
812 s << ';';
813
814 statementListStreamTo(m_children, s);
815 s << Unindent << Endl << "}";
816}
817
818void EmptyStatementNode::streamTo(SourceStream& s) const
819{
820 s << Endl << ';';
821}
822
823void ExprStatementNode::streamTo(SourceStream& s) const
824{
825 s << Endl << m_expr << ';';
826}
827
828void VarStatementNode::streamTo(SourceStream& s) const
829{
830 s << Endl << "var " << m_expr << ';';
831}
832
833void IfNode::streamTo(SourceStream& s) const
834{
835 s << Endl << "if (" << m_condition << ')' << Indent << m_ifBlock << Unindent;
836}
837
838void IfElseNode::streamTo(SourceStream& s) const
839{
840 IfNode::streamTo(s);
841 s << Endl << "else" << Indent << m_elseBlock << Unindent;
842}
843
844void DoWhileNode::streamTo(SourceStream& s) const
845{
846 s << Endl << "do " << Indent << m_statement << Unindent << Endl
847 << "while (" << m_expr << ");";
848}
849
850void WhileNode::streamTo(SourceStream& s) const
851{
852 s << Endl << "while (" << m_expr << ')' << Indent << m_statement << Unindent;
853}
854
855void ForNode::streamTo(SourceStream& s) const
856{
857 s << Endl << "for ("
858 << (m_expr1WasVarDecl ? "var " : "")
859 << m_expr1
860 << "; " << m_expr2
861 << "; " << m_expr3
862 << ')' << Indent << m_statement << Unindent;
863}
864
865void ForInNode::streamTo(SourceStream& s) const
866{
867 s << Endl << "for (";
868 if (m_identIsVarDecl) {
869 s << "var ";
870 if (m_init)
871 s << m_init;
872 else
873 s << PrecLeftHandSide << m_lexpr;
874 } else
875 s << PrecLeftHandSide << m_lexpr;
876
877 s << " in " << m_expr << ')' << Indent << m_statement << Unindent;
878}
879
880void ContinueNode::streamTo(SourceStream& s) const
881{
882 s << Endl << "continue";
883 if (!m_ident.isNull())
884 s << ' ' << m_ident;
885 s << ';';
886}
887
888void BreakNode::streamTo(SourceStream& s) const
889{
890 s << Endl << "break";
891 if (!m_ident.isNull())
892 s << ' ' << m_ident;
893 s << ';';
894}
895
896void ReturnNode::streamTo(SourceStream& s) const
897{
898 s << Endl << "return";
899 if (m_value)
900 s << ' ' << m_value;
901 s << ';';
902}
903
904void WithNode::streamTo(SourceStream& s) const
905{
906 s << Endl << "with (" << m_expr << ") " << m_statement;
907}
908
909void CaseClauseNode::streamTo(SourceStream& s) const
910{
911 s << Endl;
912 if (m_expr)
913 s << "case " << m_expr;
914 else
915 s << "default";
916 s << ":" << Indent;
917 statementListStreamTo(m_children, s);
918 s << Unindent;
919}
920
921void ClauseListNode::streamTo(SourceStream& s) const
922{
923 for (const ClauseListNode* n = this; n; n = n->getNext())
924 s << n->getClause();
925}
926
927void CaseBlockNode::streamTo(SourceStream& s) const
928{
929 for (const ClauseListNode* n = m_list1.get(); n; n = n->getNext())
930 s << n->getClause();
931 s << m_defaultClause;
932 for (const ClauseListNode* n = m_list2.get(); n; n = n->getNext())
933 s << n->getClause();
934}
935
936void SwitchNode::streamTo(SourceStream& s) const
937{
938 s << Endl << "switch (" << m_expr << ") {"
939 << Indent << m_block << Unindent
940 << Endl << "}";
941}
942
943void LabelNode::streamTo(SourceStream& s) const
944{
945 s << Endl << m_label << ":" << Indent << m_statement << Unindent;
946}
947
948void ThrowNode::streamTo(SourceStream& s) const
949{
950 s << Endl << "throw " << m_expr << ';';
951}
952
953void TryNode::streamTo(SourceStream& s) const
954{
955 s << Endl << "try " << m_tryBlock;
956 if (m_catchBlock)
957 s << Endl << "catch (" << m_exceptionIdent << ')' << m_catchBlock;
958 if (m_finallyBlock)
959 s << Endl << "finally " << m_finallyBlock;
960}
961
962void ParameterNode::streamTo(SourceStream& s) const
963{
964 s << m_ident;
965 for (ParameterNode* n = m_next.get(); n; n = n->m_next.get())
966 s << ", " << n->m_ident;
967}
968
969void FuncDeclNode::streamTo(SourceStream& s) const
970{
971 s << Endl << "function " << m_ident << '(' << m_parameter << ')' << m_body;
972}
973
974void FuncExprNode::streamTo(SourceStream& s) const
975{
976 s << "function " << m_ident << '(' << m_parameter << ')' << m_body;
977}
978
979} // namespace KJS
Note: See TracBrowser for help on using the repository browser.