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

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

2008-06-15 Cameron Zwarich <[email protected]>

Reviewed by Maciej.

Bug 19484: More instructions needs to use temporary registers
<https://bugs.webkit.org/show_bug.cgi?id=19484>

Fix codegen for all binary operations so that temporaries are used if
necessary. This was done by making BinaryOpNode and ReverseBinaryOpNode
subclasses of ExpressionNode, and eliminating the custom emitCode()
methods for the individual node classes.

This only adds 3 new instructions to SunSpider code, and there is no
difference in SunSpider execution time.

JavaScriptCore:

  • VM/CodeGenerator.cpp: (KJS::CodeGenerator::emitBitNot): (KJS::CodeGenerator::emitBinaryOp):
  • VM/CodeGenerator.h:
  • kjs/grammar.y:
  • kjs/nodes.cpp: (KJS::PreIncResolveNode::emitCode): (KJS::PreDecResolveNode::emitCode): (KJS::BinaryOpNode::emitCode): (KJS::ReverseBinaryOpNode::emitCode): (KJS::emitReadModifyAssignment): (KJS::CaseBlockNode::emitCodeForBlock):
  • kjs/nodes.h: (KJS::BinaryOpNode::BinaryOpNode): (KJS::ReverseBinaryOpNode::ReverseBinaryOpNode): (KJS::MultNode::): (KJS::DivNode::): (KJS::DivNode::precedence): (KJS::ModNode::): (KJS::ModNode::precedence): (KJS::AddNode::): (KJS::AddNode::precedence): (KJS::SubNode::): (KJS::SubNode::precedence): (KJS::LeftShiftNode::): (KJS::LeftShiftNode::precedence): (KJS::RightShiftNode::): (KJS::RightShiftNode::precedence): (KJS::UnsignedRightShiftNode::): (KJS::UnsignedRightShiftNode::precedence): (KJS::LessNode::): (KJS::LessNode::precedence): (KJS::GreaterNode::): (KJS::GreaterNode::precedence): (KJS::LessEqNode::): (KJS::LessEqNode::precedence): (KJS::GreaterEqNode::): (KJS::GreaterEqNode::precedence): (KJS::InstanceOfNode::): (KJS::InstanceOfNode::precedence): (KJS::InNode::): (KJS::InNode::precedence): (KJS::EqualNode::): (KJS::EqualNode::precedence): (KJS::NotEqualNode::): (KJS::NotEqualNode::precedence): (KJS::StrictEqualNode::): (KJS::StrictEqualNode::precedence): (KJS::NotStrictEqualNode::): (KJS::NotStrictEqualNode::precedence): (KJS::BitAndNode::): (KJS::BitAndNode::precedence): (KJS::BitOrNode::): (KJS::BitOrNode::precedence): (KJS::BitXOrNode::): (KJS::BitXOrNode::precedence):
  • kjs/nodes2string.cpp: (KJS::LessNode::streamTo): (KJS::GreaterNode::streamTo): (KJS::LessEqNode::streamTo): (KJS::GreaterEqNode::streamTo): (KJS::InstanceOfNode::streamTo): (KJS::InNode::streamTo): (KJS::EqualNode::streamTo): (KJS::NotEqualNode::streamTo): (KJS::StrictEqualNode::streamTo): (KJS::NotStrictEqualNode::streamTo): (KJS::BitAndNode::streamTo): (KJS::BitXOrNode::streamTo): (KJS::BitOrNode::streamTo):

LayoutTests:

  • fast/js/codegen-temporaries-expected.txt:
  • fast/js/resources/codegen-temporaries.js:
  • 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 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) << '"';
313}
314
315void RegExpNode::streamTo(SourceStream& s) const
316{
317 s << '/' << m_regExp->pattern() << '/' << m_regExp->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 PostIncResolveNode::streamTo(SourceStream& s) const
449{
450 s << m_ident << "++";
451}
452
453void PostDecResolveNode::streamTo(SourceStream& s) const
454{
455 s << m_ident << "--";
456}
457
458void PostIncBracketNode::streamTo(SourceStream& s) const
459{
460 bracketNodeStreamTo(s, m_base, m_subscript);
461 s << "++";
462}
463
464void PostDecBracketNode::streamTo(SourceStream& s) const
465{
466 bracketNodeStreamTo(s, m_base, m_subscript);
467 s << "--";
468}
469
470void PostIncDotNode::streamTo(SourceStream& s) const
471{
472 dotNodeStreamTo(s, m_base, m_ident);
473 s << "++";
474}
475
476void PostDecDotNode::streamTo(SourceStream& s) const
477{
478 dotNodeStreamTo(s, m_base, m_ident);
479 s << "--";
480}
481
482void PostfixErrorNode::streamTo(SourceStream& s) const
483{
484 s << PrecLeftHandSide << m_expr;
485 if (m_operator == OpPlusPlus)
486 s << "++";
487 else
488 s << "--";
489}
490
491void DeleteResolveNode::streamTo(SourceStream& s) const
492{
493 s << "delete " << m_ident;
494}
495
496void DeleteBracketNode::streamTo(SourceStream& s) const
497{
498 s << "delete ";
499 bracketNodeStreamTo(s, m_base, m_subscript);
500}
501
502void DeleteDotNode::streamTo(SourceStream& s) const
503{
504 s << "delete ";
505 dotNodeStreamTo(s, m_base, m_ident);
506}
507
508void DeleteValueNode::streamTo(SourceStream& s) const
509{
510 s << "delete " << PrecUnary << m_expr;
511}
512
513void VoidNode::streamTo(SourceStream& s) const
514{
515 s << "void " << PrecUnary << m_expr;
516}
517
518void TypeOfValueNode::streamTo(SourceStream& s) const
519{
520 s << "typeof " << PrecUnary << m_expr;
521}
522
523void TypeOfResolveNode::streamTo(SourceStream& s) const
524{
525 s << "typeof " << m_ident;
526}
527
528void PreIncResolveNode::streamTo(SourceStream& s) const
529{
530 s << "++" << m_ident;
531}
532
533void PreDecResolveNode::streamTo(SourceStream& s) const
534{
535 s << "--" << m_ident;
536}
537
538void PreIncBracketNode::streamTo(SourceStream& s) const
539{
540 s << "++";
541 bracketNodeStreamTo(s, m_base, m_subscript);
542}
543
544void PreDecBracketNode::streamTo(SourceStream& s) const
545{
546 s << "--";
547 bracketNodeStreamTo(s, m_base, m_subscript);
548}
549
550void PreIncDotNode::streamTo(SourceStream& s) const
551{
552 s << "++";
553 dotNodeStreamTo(s, m_base, m_ident);
554}
555
556void PreDecDotNode::streamTo(SourceStream& s) const
557{
558 s << "--";
559 dotNodeStreamTo(s, m_base, m_ident);
560}
561
562void PrefixErrorNode::streamTo(SourceStream& s) const
563{
564 if (m_operator == OpPlusPlus)
565 s << "++" << PrecUnary << m_expr;
566 else
567 s << "--" << PrecUnary << m_expr;
568}
569
570void UnaryPlusNode::streamTo(SourceStream& s) const
571{
572 s << "+ " << PrecUnary << m_expr;
573}
574
575void NegateNode::streamTo(SourceStream& s) const
576{
577 s << "- " << PrecUnary << m_expr;
578}
579
580void BitwiseNotNode::streamTo(SourceStream& s) const
581{
582 s << "~" << PrecUnary << m_expr;
583}
584
585void LogicalNotNode::streamTo(SourceStream& s) const
586{
587 s << "!" << PrecUnary << m_expr;
588}
589
590void MultNode::streamTo(SourceStream& s) const
591{
592 streamLeftAssociativeBinaryOperator(s, precedence(), "*", m_term1, m_term2);
593}
594
595void DivNode::streamTo(SourceStream& s) const
596{
597 streamLeftAssociativeBinaryOperator(s, precedence(), "/", m_term1, m_term2);
598}
599
600void ModNode::streamTo(SourceStream& s) const
601{
602 streamLeftAssociativeBinaryOperator(s, precedence(), "%", m_term1, m_term2);
603}
604
605void AddNode::streamTo(SourceStream& s) const
606{
607 streamLeftAssociativeBinaryOperator(s, precedence(), "+", m_term1, m_term2);
608}
609
610void SubNode::streamTo(SourceStream& s) const
611{
612 streamLeftAssociativeBinaryOperator(s, precedence(), "-", m_term1, m_term2);
613}
614
615void LeftShiftNode::streamTo(SourceStream& s) const
616{
617 streamLeftAssociativeBinaryOperator(s, precedence(), "<<", m_term1, m_term2);
618}
619
620void RightShiftNode::streamTo(SourceStream& s) const
621{
622 streamLeftAssociativeBinaryOperator(s, precedence(), ">>", m_term1, m_term2);
623}
624
625void UnsignedRightShiftNode::streamTo(SourceStream& s) const
626{
627 streamLeftAssociativeBinaryOperator(s, precedence(), ">>>", m_term1, m_term2);
628}
629
630void LessNode::streamTo(SourceStream& s) const
631{
632 streamLeftAssociativeBinaryOperator(s, precedence(), "<", m_term1, m_term2);
633}
634
635void GreaterNode::streamTo(SourceStream& s) const
636{
637 streamLeftAssociativeBinaryOperator(s, precedence(), ">", m_term1, m_term2);
638}
639
640void LessEqNode::streamTo(SourceStream& s) const
641{
642 streamLeftAssociativeBinaryOperator(s, precedence(), "<=", m_term1, m_term2);
643}
644
645void GreaterEqNode::streamTo(SourceStream& s) const
646{
647 streamLeftAssociativeBinaryOperator(s, precedence(), ">=", m_term1, m_term2);
648}
649
650void InstanceOfNode::streamTo(SourceStream& s) const
651{
652 streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", m_term1, m_term2);
653}
654
655void InNode::streamTo(SourceStream& s) const
656{
657 streamLeftAssociativeBinaryOperator(s, precedence(), "in", m_term1, m_term2);
658}
659
660void EqualNode::streamTo(SourceStream& s) const
661{
662 streamLeftAssociativeBinaryOperator(s, precedence(), "==", m_term1, m_term2);
663}
664
665void NotEqualNode::streamTo(SourceStream& s) const
666{
667 streamLeftAssociativeBinaryOperator(s, precedence(), "!=", m_term1, m_term2);
668}
669
670void StrictEqualNode::streamTo(SourceStream& s) const
671{
672 streamLeftAssociativeBinaryOperator(s, precedence(), "===", m_term1, m_term2);
673}
674
675void NotStrictEqualNode::streamTo(SourceStream& s) const
676{
677 streamLeftAssociativeBinaryOperator(s, precedence(), "!==", m_term1, m_term2);
678}
679
680void BitAndNode::streamTo(SourceStream& s) const
681{
682 streamLeftAssociativeBinaryOperator(s, precedence(), "&", m_term1, m_term2);
683}
684
685void BitXOrNode::streamTo(SourceStream& s) const
686{
687 streamLeftAssociativeBinaryOperator(s, precedence(), "^", m_term1, m_term2);
688}
689
690void BitOrNode::streamTo(SourceStream& s) const
691{
692 streamLeftAssociativeBinaryOperator(s, precedence(), "|", m_term1, m_term2);
693}
694
695void LogicalAndNode::streamTo(SourceStream& s) const
696{
697 streamLeftAssociativeBinaryOperator(s, precedence(), "&&", m_expr1, m_expr2);
698}
699
700void LogicalOrNode::streamTo(SourceStream& s) const
701{
702 streamLeftAssociativeBinaryOperator(s, precedence(), "||", m_expr1, m_expr2);
703}
704
705void ConditionalNode::streamTo(SourceStream& s) const
706{
707 s << PrecLogicalOr << m_logical
708 << " ? " << PrecAssignment << m_expr1
709 << " : " << PrecAssignment << m_expr2;
710}
711
712void ReadModifyResolveNode::streamTo(SourceStream& s) const
713{
714 s << m_ident << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
715}
716
717void AssignResolveNode::streamTo(SourceStream& s) const
718{
719 s << m_ident << " = " << PrecAssignment << m_right;
720}
721
722void ReadModifyBracketNode::streamTo(SourceStream& s) const
723{
724 bracketNodeStreamTo(s, m_base, m_subscript);
725 s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
726}
727
728void AssignBracketNode::streamTo(SourceStream& s) const
729{
730 bracketNodeStreamTo(s, m_base, m_subscript);
731 s << " = " << PrecAssignment << m_right;
732}
733
734void ReadModifyDotNode::streamTo(SourceStream& s) const
735{
736 dotNodeStreamTo(s, m_base, m_ident);
737 s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
738}
739
740void AssignDotNode::streamTo(SourceStream& s) const
741{
742 dotNodeStreamTo(s, m_base, m_ident);
743 s << " = " << PrecAssignment << m_right;
744}
745
746void AssignErrorNode::streamTo(SourceStream& s) const
747{
748 s << PrecLeftHandSide << m_left << ' '
749 << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
750}
751
752void CommaNode::streamTo(SourceStream& s) const
753{
754 s << PrecAssignment << m_expr1 << ", " << PrecAssignment << m_expr2;
755}
756
757void ConstDeclNode::streamTo(SourceStream& s) const
758{
759 s << m_ident;
760 if (m_init)
761 s << " = " << PrecAssignment << m_init;
762 for (ConstDeclNode* n = m_next.get(); n; n = n->m_next.get()) {
763 s << ", " << n->m_ident;
764 if (n->m_init)
765 s << " = " << PrecAssignment << n->m_init;
766 }
767}
768
769void ConstStatementNode::streamTo(SourceStream& s) const
770{
771 s << Endl << "const " << m_next << ';';
772}
773
774static inline void statementListStreamTo(const Vector<RefPtr<StatementNode> >& nodes, SourceStream& s)
775{
776 for (Vector<RefPtr<StatementNode> >::const_iterator ptr = nodes.begin(); ptr != nodes.end(); ptr++)
777 s << *ptr;
778}
779
780void BlockNode::streamTo(SourceStream& s) const
781{
782 s << Endl << "{" << Indent;
783 statementListStreamTo(m_children, s);
784 s << Unindent << Endl << "}";
785}
786
787void ScopeNode::streamTo(SourceStream& s) const
788{
789 s << Endl << "{" << Indent;
790
791 bool printedVar = false;
792 for (size_t i = 0; i < m_varStack.size(); ++i) {
793 if (m_varStack[i].second == 0) {
794 if (!printedVar) {
795 s << Endl << "var ";
796 printedVar = true;
797 } else
798 s << ", ";
799 s << m_varStack[i].first;
800 }
801 }
802 if (printedVar)
803 s << ';';
804
805 statementListStreamTo(m_children, s);
806 s << Unindent << Endl << "}";
807}
808
809void EmptyStatementNode::streamTo(SourceStream& s) const
810{
811 s << Endl << ';';
812}
813
814void DebuggerStatementNode::streamTo(SourceStream& s) const
815{
816 s << Endl << "debugger;";
817}
818
819void ExprStatementNode::streamTo(SourceStream& s) const
820{
821 s << Endl << m_expr << ';';
822}
823
824void VarStatementNode::streamTo(SourceStream& s) const
825{
826 s << Endl << "var " << m_expr << ';';
827}
828
829void IfNode::streamTo(SourceStream& s) const
830{
831 s << Endl << "if (" << m_condition << ')' << Indent << m_ifBlock << Unindent;
832}
833
834void IfElseNode::streamTo(SourceStream& s) const
835{
836 IfNode::streamTo(s);
837 s << Endl << "else" << Indent << m_elseBlock << Unindent;
838}
839
840void DoWhileNode::streamTo(SourceStream& s) const
841{
842 s << Endl << "do " << Indent << m_statement << Unindent << Endl
843 << "while (" << m_expr << ");";
844}
845
846void WhileNode::streamTo(SourceStream& s) const
847{
848 s << Endl << "while (" << m_expr << ')' << Indent << m_statement << Unindent;
849}
850
851void ForNode::streamTo(SourceStream& s) const
852{
853 s << Endl << "for ("
854 << (m_expr1WasVarDecl ? "var " : "")
855 << m_expr1
856 << "; " << m_expr2
857 << "; " << m_expr3
858 << ')' << Indent << m_statement << Unindent;
859}
860
861void ForInNode::streamTo(SourceStream& s) const
862{
863 s << Endl << "for (";
864 if (m_identIsVarDecl) {
865 s << "var ";
866 if (m_init)
867 s << m_init;
868 else
869 s << PrecLeftHandSide << m_lexpr;
870 } else
871 s << PrecLeftHandSide << m_lexpr;
872
873 s << " in " << m_expr << ')' << Indent << m_statement << Unindent;
874}
875
876void ContinueNode::streamTo(SourceStream& s) const
877{
878 s << Endl << "continue";
879 if (!m_ident.isNull())
880 s << ' ' << m_ident;
881 s << ';';
882}
883
884void BreakNode::streamTo(SourceStream& s) const
885{
886 s << Endl << "break";
887 if (!m_ident.isNull())
888 s << ' ' << m_ident;
889 s << ';';
890}
891
892void ReturnNode::streamTo(SourceStream& s) const
893{
894 s << Endl << "return";
895 if (m_value)
896 s << ' ' << m_value;
897 s << ';';
898}
899
900void WithNode::streamTo(SourceStream& s) const
901{
902 s << Endl << "with (" << m_expr << ") " << m_statement;
903}
904
905void CaseClauseNode::streamTo(SourceStream& s) const
906{
907 s << Endl;
908 if (m_expr)
909 s << "case " << m_expr;
910 else
911 s << "default";
912 s << ":" << Indent;
913 statementListStreamTo(m_children, s);
914 s << Unindent;
915}
916
917void ClauseListNode::streamTo(SourceStream& s) const
918{
919 for (const ClauseListNode* n = this; n; n = n->getNext())
920 s << n->getClause();
921}
922
923void CaseBlockNode::streamTo(SourceStream& s) const
924{
925 for (const ClauseListNode* n = m_list1.get(); n; n = n->getNext())
926 s << n->getClause();
927 s << m_defaultClause;
928 for (const ClauseListNode* n = m_list2.get(); n; n = n->getNext())
929 s << n->getClause();
930}
931
932void SwitchNode::streamTo(SourceStream& s) const
933{
934 s << Endl << "switch (" << m_expr << ") {"
935 << Indent << m_block << Unindent
936 << Endl << "}";
937}
938
939void LabelNode::streamTo(SourceStream& s) const
940{
941 s << Endl << m_label << ":" << Indent << m_statement << Unindent;
942}
943
944void ThrowNode::streamTo(SourceStream& s) const
945{
946 s << Endl << "throw " << m_expr << ';';
947}
948
949void TryNode::streamTo(SourceStream& s) const
950{
951 s << Endl << "try " << m_tryBlock;
952 if (m_catchBlock)
953 s << Endl << "catch (" << m_exceptionIdent << ')' << m_catchBlock;
954 if (m_finallyBlock)
955 s << Endl << "finally " << m_finallyBlock;
956}
957
958void ParameterNode::streamTo(SourceStream& s) const
959{
960 s << m_ident;
961 for (ParameterNode* n = m_next.get(); n; n = n->m_next.get())
962 s << ", " << n->m_ident;
963}
964
965void FuncDeclNode::streamTo(SourceStream& s) const
966{
967 s << Endl << "function " << m_ident << '(' << m_parameter << ')' << m_body;
968}
969
970void FuncExprNode::streamTo(SourceStream& s) const
971{
972 s << "function " << m_ident << '(' << m_parameter << ')' << m_body;
973}
974
975} // namespace KJS
Note: See TracBrowser for help on using the repository browser.