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

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

2008-10-30 Geoffrey Garen <[email protected]>

Reviewed by Oliver Hunt.


Fixed a small bit of https://bugs.webkit.org/show_bug.cgi?id=21962
AST uses way too much memory


Removed a word from StatementNode by nixing LabelStack and turning it
into a compile-time data structure managed by CodeGenerator.


v8 tests and SunSpider, run by Gavin, report no change.


  • VM/CodeGenerator.cpp: (JSC::CodeGenerator::CodeGenerator): (JSC::CodeGenerator::newLabelScope): (JSC::CodeGenerator::breakTarget): (JSC::CodeGenerator::continueTarget):
  • VM/CodeGenerator.h: Nixed the JumpContext system because it depended on a LabelStack in the AST, and it was a little cumbersome on the client side. Replaced with LabelScope, which tracks all break / continue information in the CodeGenerator, just like we track LabelIDs and other stacks of compile-time data.
  • kjs/LabelScope.h: Added. (JSC::LabelScope::): (JSC::LabelScope::LabelScope): (JSC::LabelScope::ref): (JSC::LabelScope::deref): (JSC::LabelScope::refCount): (JSC::LabelScope::breakTarget): (JSC::LabelScope::continueTarget): (JSC::LabelScope::type): (JSC::LabelScope::name): (JSC::LabelScope::scopeDepth): Simple abstraction for holding everything you might want to know about a break-able / continue-able scope.
  • kjs/LabelStack.cpp: Removed.
  • kjs/LabelStack.h: Removed.
  • kjs/grammar.y: No need to push labels at parse time -- we don't store LabelStacks in the AST anymore.
  • kjs/nodes.cpp: (JSC::DoWhileNode::emitCode): (JSC::WhileNode::emitCode): (JSC::ForNode::emitCode): (JSC::ForInNode::emitCode): (JSC::ContinueNode::emitCode): (JSC::BreakNode::emitCode): (JSC::SwitchNode::emitCode): (JSC::LabelNode::emitCode):
  • kjs/nodes.h: (JSC::StatementNode::): (JSC::LabelNode::): Use LabelScope where we used to use JumpContext. Simplified a bunch of code. Touched up label-related error messages a bit.
  • kjs/nodes2string.cpp: (JSC::LabelNode::streamTo): Updated for rename.
  • Property svn:eol-style set to native
File size: 22.8 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 JSC {
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 BooleanNode::streamTo(SourceStream& s) const
301{
302 s << (m_value ? "true" : "false");
303}
304
305void NumberNode::streamTo(SourceStream& s) const
306{
307 s << value();
308}
309
310void StringNode::streamTo(SourceStream& s) const
311{
312 s << '"' << escapeStringForPrettyPrinting(m_value.ustring()) << '"';
313}
314
315void RegExpNode::streamTo(SourceStream& s) const
316{
317 s << '/' << m_pattern << '/' << m_flags;
318}
319
320void ThisNode::streamTo(SourceStream& s) const
321{
322 s << "this";
323}
324
325void ResolveNode::streamTo(SourceStream& s) const
326{
327 s << m_ident;
328}
329
330void ElementNode::streamTo(SourceStream& s) const
331{
332 for (const ElementNode* n = this; n; n = n->m_next.get()) {
333 for (int i = 0; i < n->m_elision; i++)
334 s << ',';
335 s << PrecAssignment << n->m_node;
336 if (n->m_next)
337 s << ',';
338 }
339}
340
341void ArrayNode::streamTo(SourceStream& s) const
342{
343 s << '[' << m_element;
344 for (int i = 0; i < m_elision; i++)
345 s << ',';
346 // Parser consumes one elision comma if there's array elements
347 // present in the expression.
348 if (m_optional && m_element)
349 s << ',';
350 s << ']';
351}
352
353void ObjectLiteralNode::streamTo(SourceStream& s) const
354{
355 if (m_list)
356 s << "{ " << m_list << " }";
357 else
358 s << "{ }";
359}
360
361void PropertyListNode::streamTo(SourceStream& s) const
362{
363 s << m_node;
364 for (const PropertyListNode* n = m_next.get(); n; n = n->m_next.get())
365 s << ", " << n->m_node;
366}
367
368void PropertyNode::streamTo(SourceStream& s) const
369{
370 switch (m_type) {
371 case Constant: {
372 UString propertyName = name().ustring();
373 if (isParserRoundTripNumber(propertyName))
374 s << propertyName;
375 else
376 s << '"' << escapeStringForPrettyPrinting(propertyName) << '"';
377 s << ": " << PrecAssignment << m_assign;
378 break;
379 }
380 case Getter:
381 case Setter: {
382 const FuncExprNode* func = static_cast<const FuncExprNode*>(m_assign.get());
383 if (m_type == Getter)
384 s << "get ";
385 else
386 s << "set ";
387 s << escapeStringForPrettyPrinting(name().ustring())
388 << "(" << func->m_parameter << ')' << func->m_body;
389 break;
390 }
391 }
392}
393
394void BracketAccessorNode::streamTo(SourceStream& s) const
395{
396 bracketNodeStreamTo(s, m_base, m_subscript);
397}
398
399void DotAccessorNode::streamTo(SourceStream& s) const
400{
401 dotNodeStreamTo(s, m_base, m_ident);
402}
403
404void ArgumentListNode::streamTo(SourceStream& s) const
405{
406 s << PrecAssignment << m_expr;
407 for (ArgumentListNode* n = m_next.get(); n; n = n->m_next.get())
408 s << ", " << PrecAssignment << n->m_expr;
409}
410
411void ArgumentsNode::streamTo(SourceStream& s) const
412{
413 s << '(' << m_listNode << ')';
414}
415
416void NewExprNode::streamTo(SourceStream& s) const
417{
418 s << "new " << PrecMember << m_expr << m_args;
419}
420
421void EvalFunctionCallNode::streamTo(SourceStream& s) const
422{
423 s << "eval" << m_args;
424}
425
426void FunctionCallValueNode::streamTo(SourceStream& s) const
427{
428 s << PrecCall << m_expr << m_args;
429}
430
431void FunctionCallResolveNode::streamTo(SourceStream& s) const
432{
433 s << m_ident << m_args;
434}
435
436void FunctionCallBracketNode::streamTo(SourceStream& s) const
437{
438 bracketNodeStreamTo(s, m_base, m_subscript);
439 s << m_args;
440}
441
442void FunctionCallDotNode::streamTo(SourceStream& s) const
443{
444 dotNodeStreamTo(s, m_base, m_ident);
445 s << m_args;
446}
447
448void PostfixResolveNode::streamTo(SourceStream& s) const
449{
450 s << m_ident << operatorString(m_operator);
451}
452
453void PostfixBracketNode::streamTo(SourceStream& s) const
454{
455 bracketNodeStreamTo(s, m_base, m_subscript);
456 s << operatorString(m_operator);
457}
458
459void PostfixDotNode::streamTo(SourceStream& s) const
460{
461 dotNodeStreamTo(s, m_base, m_ident);
462 s << operatorString(m_operator);
463}
464
465void PostfixErrorNode::streamTo(SourceStream& s) const
466{
467 s << PrecLeftHandSide << m_expr;
468 if (m_operator == OpPlusPlus)
469 s << "++";
470 else
471 s << "--";
472}
473
474void DeleteResolveNode::streamTo(SourceStream& s) const
475{
476 s << "delete " << m_ident;
477}
478
479void DeleteBracketNode::streamTo(SourceStream& s) const
480{
481 s << "delete ";
482 bracketNodeStreamTo(s, m_base, m_subscript);
483}
484
485void DeleteDotNode::streamTo(SourceStream& s) const
486{
487 s << "delete ";
488 dotNodeStreamTo(s, m_base, m_ident);
489}
490
491void DeleteValueNode::streamTo(SourceStream& s) const
492{
493 s << "delete " << PrecUnary << m_expr;
494}
495
496void VoidNode::streamTo(SourceStream& s) const
497{
498 s << "void " << PrecUnary << m_expr;
499}
500
501void TypeOfValueNode::streamTo(SourceStream& s) const
502{
503 s << "typeof " << PrecUnary << m_expr;
504}
505
506void TypeOfResolveNode::streamTo(SourceStream& s) const
507{
508 s << "typeof " << m_ident;
509}
510
511void PrefixResolveNode::streamTo(SourceStream& s) const
512{
513 s << operatorString(m_operator) << m_ident;
514}
515
516void PrefixBracketNode::streamTo(SourceStream& s) const
517{
518 s << operatorString(m_operator);
519 bracketNodeStreamTo(s, m_base, m_subscript);
520}
521
522void PrefixDotNode::streamTo(SourceStream& s) const
523{
524 s << operatorString(m_operator);
525 dotNodeStreamTo(s, m_base, m_ident);
526}
527
528void PrefixErrorNode::streamTo(SourceStream& s) const
529{
530 if (m_operator == OpPlusPlus)
531 s << "++" << PrecUnary << m_expr;
532 else
533 s << "--" << PrecUnary << m_expr;
534}
535
536void UnaryPlusNode::streamTo(SourceStream& s) const
537{
538 s << "+ " << PrecUnary << m_expr;
539}
540
541void NegateNode::streamTo(SourceStream& s) const
542{
543 s << "- " << PrecUnary << m_expr;
544}
545
546void BitwiseNotNode::streamTo(SourceStream& s) const
547{
548 s << "~" << PrecUnary << m_expr;
549}
550
551void LogicalNotNode::streamTo(SourceStream& s) const
552{
553 s << "!" << PrecUnary << m_expr;
554}
555
556void MultNode::streamTo(SourceStream& s) const
557{
558 streamLeftAssociativeBinaryOperator(s, precedence(), "*", m_expr1, m_expr2);
559}
560
561void DivNode::streamTo(SourceStream& s) const
562{
563 streamLeftAssociativeBinaryOperator(s, precedence(), "/", m_expr1, m_expr2);
564}
565
566void ModNode::streamTo(SourceStream& s) const
567{
568 streamLeftAssociativeBinaryOperator(s, precedence(), "%", m_expr1, m_expr2);
569}
570
571void AddNode::streamTo(SourceStream& s) const
572{
573 streamLeftAssociativeBinaryOperator(s, precedence(), "+", m_expr1, m_expr2);
574}
575
576void SubNode::streamTo(SourceStream& s) const
577{
578 streamLeftAssociativeBinaryOperator(s, precedence(), "-", m_expr1, m_expr2);
579}
580
581void LeftShiftNode::streamTo(SourceStream& s) const
582{
583 streamLeftAssociativeBinaryOperator(s, precedence(), "<<", m_expr1, m_expr2);
584}
585
586void RightShiftNode::streamTo(SourceStream& s) const
587{
588 streamLeftAssociativeBinaryOperator(s, precedence(), ">>", m_expr1, m_expr2);
589}
590
591void UnsignedRightShiftNode::streamTo(SourceStream& s) const
592{
593 streamLeftAssociativeBinaryOperator(s, precedence(), ">>>", m_expr1, m_expr2);
594}
595
596void LessNode::streamTo(SourceStream& s) const
597{
598 streamLeftAssociativeBinaryOperator(s, precedence(), "<", m_expr1, m_expr2);
599}
600
601void GreaterNode::streamTo(SourceStream& s) const
602{
603 streamLeftAssociativeBinaryOperator(s, precedence(), ">", m_expr1, m_expr2);
604}
605
606void LessEqNode::streamTo(SourceStream& s) const
607{
608 streamLeftAssociativeBinaryOperator(s, precedence(), "<=", m_expr1, m_expr2);
609}
610
611void GreaterEqNode::streamTo(SourceStream& s) const
612{
613 streamLeftAssociativeBinaryOperator(s, precedence(), ">=", m_expr1, m_expr2);
614}
615
616void InstanceOfNode::streamTo(SourceStream& s) const
617{
618 streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", m_expr1, m_expr2);
619}
620
621void InNode::streamTo(SourceStream& s) const
622{
623 streamLeftAssociativeBinaryOperator(s, precedence(), "in", m_expr1, m_expr2);
624}
625
626void EqualNode::streamTo(SourceStream& s) const
627{
628 streamLeftAssociativeBinaryOperator(s, precedence(), "==", m_expr1, m_expr2);
629}
630
631void NotEqualNode::streamTo(SourceStream& s) const
632{
633 streamLeftAssociativeBinaryOperator(s, precedence(), "!=", m_expr1, m_expr2);
634}
635
636void StrictEqualNode::streamTo(SourceStream& s) const
637{
638 streamLeftAssociativeBinaryOperator(s, precedence(), "===", m_expr1, m_expr2);
639}
640
641void NotStrictEqualNode::streamTo(SourceStream& s) const
642{
643 streamLeftAssociativeBinaryOperator(s, precedence(), "!==", m_expr1, m_expr2);
644}
645
646void BitAndNode::streamTo(SourceStream& s) const
647{
648 streamLeftAssociativeBinaryOperator(s, precedence(), "&", m_expr1, m_expr2);
649}
650
651void BitXOrNode::streamTo(SourceStream& s) const
652{
653 streamLeftAssociativeBinaryOperator(s, precedence(), "^", m_expr1, m_expr2);
654}
655
656void BitOrNode::streamTo(SourceStream& s) const
657{
658 streamLeftAssociativeBinaryOperator(s, precedence(), "|", m_expr1, m_expr2);
659}
660
661void LogicalOpNode::streamTo(SourceStream& s) const
662{
663 streamLeftAssociativeBinaryOperator(s, precedence(), (m_operator == OpLogicalAnd) ? "&&" : "||", m_expr1, m_expr2);
664}
665
666void ConditionalNode::streamTo(SourceStream& s) const
667{
668 s << PrecLogicalOr << m_logical
669 << " ? " << PrecAssignment << m_expr1
670 << " : " << PrecAssignment << m_expr2;
671}
672
673void ReadModifyResolveNode::streamTo(SourceStream& s) const
674{
675 s << m_ident << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
676}
677
678void AssignResolveNode::streamTo(SourceStream& s) const
679{
680 s << m_ident << " = " << PrecAssignment << m_right;
681}
682
683void ReadModifyBracketNode::streamTo(SourceStream& s) const
684{
685 bracketNodeStreamTo(s, m_base, m_subscript);
686 s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
687}
688
689void AssignBracketNode::streamTo(SourceStream& s) const
690{
691 bracketNodeStreamTo(s, m_base, m_subscript);
692 s << " = " << PrecAssignment << m_right;
693}
694
695void ReadModifyDotNode::streamTo(SourceStream& s) const
696{
697 dotNodeStreamTo(s, m_base, m_ident);
698 s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
699}
700
701void AssignDotNode::streamTo(SourceStream& s) const
702{
703 dotNodeStreamTo(s, m_base, m_ident);
704 s << " = " << PrecAssignment << m_right;
705}
706
707void AssignErrorNode::streamTo(SourceStream& s) const
708{
709 s << PrecLeftHandSide << m_left << ' '
710 << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
711}
712
713void CommaNode::streamTo(SourceStream& s) const
714{
715 s << PrecAssignment << m_expr1 << ", " << PrecAssignment << m_expr2;
716}
717
718void ConstDeclNode::streamTo(SourceStream& s) const
719{
720 s << m_ident;
721 if (m_init)
722 s << " = " << PrecAssignment << m_init;
723 for (ConstDeclNode* n = m_next.get(); n; n = n->m_next.get()) {
724 s << ", " << n->m_ident;
725 if (n->m_init)
726 s << " = " << PrecAssignment << n->m_init;
727 }
728}
729
730void ConstStatementNode::streamTo(SourceStream& s) const
731{
732 s << Endl << "const " << m_next << ';';
733}
734
735static inline void statementListStreamTo(const Vector<RefPtr<StatementNode> >& nodes, SourceStream& s)
736{
737 for (Vector<RefPtr<StatementNode> >::const_iterator ptr = nodes.begin(); ptr != nodes.end(); ptr++)
738 s << *ptr;
739}
740
741void BlockNode::streamTo(SourceStream& s) const
742{
743 s << Endl << "{" << Indent;
744 statementListStreamTo(m_children, s);
745 s << Unindent << Endl << "}";
746}
747
748void ScopeNode::streamTo(SourceStream& s) const
749{
750 s << Endl << "{" << Indent;
751
752 bool printedVar = false;
753 for (size_t i = 0; i < m_varStack.size(); ++i) {
754 if (m_varStack[i].second == 0) {
755 if (!printedVar) {
756 s << Endl << "var ";
757 printedVar = true;
758 } else
759 s << ", ";
760 s << m_varStack[i].first;
761 }
762 }
763 if (printedVar)
764 s << ';';
765
766 statementListStreamTo(m_children, s);
767 s << Unindent << Endl << "}";
768}
769
770void EmptyStatementNode::streamTo(SourceStream& s) const
771{
772 s << Endl << ';';
773}
774
775void DebuggerStatementNode::streamTo(SourceStream& s) const
776{
777 s << Endl << "debugger;";
778}
779
780void ExprStatementNode::streamTo(SourceStream& s) const
781{
782 s << Endl << m_expr << ';';
783}
784
785void VarStatementNode::streamTo(SourceStream& s) const
786{
787 s << Endl << "var " << m_expr << ';';
788}
789
790void IfNode::streamTo(SourceStream& s) const
791{
792 s << Endl << "if (" << m_condition << ')' << Indent << m_ifBlock << Unindent;
793}
794
795void IfElseNode::streamTo(SourceStream& s) const
796{
797 IfNode::streamTo(s);
798 s << Endl << "else" << Indent << m_elseBlock << Unindent;
799}
800
801void DoWhileNode::streamTo(SourceStream& s) const
802{
803 s << Endl << "do " << Indent << m_statement << Unindent << Endl
804 << "while (" << m_expr << ");";
805}
806
807void WhileNode::streamTo(SourceStream& s) const
808{
809 s << Endl << "while (" << m_expr << ')' << Indent << m_statement << Unindent;
810}
811
812void ForNode::streamTo(SourceStream& s) const
813{
814 s << Endl << "for ("
815 << (m_expr1WasVarDecl ? "var " : "")
816 << m_expr1
817 << "; " << m_expr2
818 << "; " << m_expr3
819 << ')' << Indent << m_statement << Unindent;
820}
821
822void ForInNode::streamTo(SourceStream& s) const
823{
824 s << Endl << "for (";
825 if (m_identIsVarDecl) {
826 s << "var ";
827 if (m_init)
828 s << m_init;
829 else
830 s << PrecLeftHandSide << m_lexpr;
831 } else
832 s << PrecLeftHandSide << m_lexpr;
833
834 s << " in " << m_expr << ')' << Indent << m_statement << Unindent;
835}
836
837void ContinueNode::streamTo(SourceStream& s) const
838{
839 s << Endl << "continue";
840 if (!m_ident.isNull())
841 s << ' ' << m_ident;
842 s << ';';
843}
844
845void BreakNode::streamTo(SourceStream& s) const
846{
847 s << Endl << "break";
848 if (!m_ident.isNull())
849 s << ' ' << m_ident;
850 s << ';';
851}
852
853void ReturnNode::streamTo(SourceStream& s) const
854{
855 s << Endl << "return";
856 if (m_value)
857 s << ' ' << m_value;
858 s << ';';
859}
860
861void WithNode::streamTo(SourceStream& s) const
862{
863 s << Endl << "with (" << m_expr << ") " << m_statement;
864}
865
866void CaseClauseNode::streamTo(SourceStream& s) const
867{
868 s << Endl;
869 if (m_expr)
870 s << "case " << m_expr;
871 else
872 s << "default";
873 s << ":" << Indent;
874 statementListStreamTo(m_children, s);
875 s << Unindent;
876}
877
878void ClauseListNode::streamTo(SourceStream& s) const
879{
880 for (const ClauseListNode* n = this; n; n = n->getNext())
881 s << n->getClause();
882}
883
884void CaseBlockNode::streamTo(SourceStream& s) const
885{
886 for (const ClauseListNode* n = m_list1.get(); n; n = n->getNext())
887 s << n->getClause();
888 s << m_defaultClause;
889 for (const ClauseListNode* n = m_list2.get(); n; n = n->getNext())
890 s << n->getClause();
891}
892
893void SwitchNode::streamTo(SourceStream& s) const
894{
895 s << Endl << "switch (" << m_expr << ") {"
896 << Indent << m_block << Unindent
897 << Endl << "}";
898}
899
900void LabelNode::streamTo(SourceStream& s) const
901{
902 s << Endl << m_name << ":" << Indent << m_statement << Unindent;
903}
904
905void ThrowNode::streamTo(SourceStream& s) const
906{
907 s << Endl << "throw " << m_expr << ';';
908}
909
910void TryNode::streamTo(SourceStream& s) const
911{
912 s << Endl << "try " << m_tryBlock;
913 if (m_catchBlock)
914 s << Endl << "catch (" << m_exceptionIdent << ')' << m_catchBlock;
915 if (m_finallyBlock)
916 s << Endl << "finally " << m_finallyBlock;
917}
918
919void ParameterNode::streamTo(SourceStream& s) const
920{
921 s << m_ident;
922 for (ParameterNode* n = m_next.get(); n; n = n->m_next.get())
923 s << ", " << n->m_ident;
924}
925
926void FuncDeclNode::streamTo(SourceStream& s) const
927{
928 s << Endl << "function " << m_ident << '(' << m_parameter << ')' << m_body;
929}
930
931void FuncExprNode::streamTo(SourceStream& s) const
932{
933 s << "function " << m_ident << '(' << m_parameter << ')' << m_body;
934}
935
936} // namespace JSC
Note: See TracBrowser for help on using the repository browser.