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

Last change on this file since 15118 was 14502, checked in by andersca, 19 years ago

JavaScriptCore:

2006-05-20 Anders Carlsson <[email protected]>

Reviewed by Geoff.

http://bugzilla.opendarwin.org/show_bug.cgi?id=8993
Support function declaration in case statements


  • kjs/grammar.y: Get rid of StatementList and use SourceElements instead.


  • kjs/nodes.cpp: (CaseClauseNode::evalStatements): (CaseClauseNode::processVarDecls): (CaseClauseNode::processFuncDecl): (ClauseListNode::processFuncDecl): (CaseBlockNode::processFuncDecl): (SwitchNode::processFuncDecl):
  • kjs/nodes.h: (KJS::CaseClauseNode::CaseClauseNode): (KJS::ClauseListNode::ClauseListNode): (KJS::ClauseListNode::getClause): (KJS::ClauseListNode::getNext): (KJS::ClauseListNode::releaseNext): (KJS::SwitchNode::SwitchNode): Add processFuncDecl for the relevant nodes.
  • kjs/nodes2string.cpp: (CaseClauseNode::streamTo): next got renamed to source.

LayoutTests:

2006-05-20 Anders Carlsson <[email protected]>

Reviewed by Geoff.

  • fast/js/function-declarations-in-switch-statement-expected.txt: Added.
  • fast/js/function-declarations-in-switch-statement.html: Added.
  • fast/js/resources/function-declarations-in-switch-statement.js: Added.
  • Property svn:eol-style set to native
File size: 14.3 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 2002 Harri Porten ([email protected])
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
26namespace 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
50using namespace KJS;
51
52SourceStream& SourceStream::operator<<(char c)
53{
54 str += UString(c);
55 return *this;
56}
57
58SourceStream& SourceStream::operator<<(const char *s)
59{
60 str += UString(s);
61 return *this;
62}
63
64SourceStream& SourceStream::operator<<(const UString &s)
65{
66 str += s;
67 return *this;
68}
69
70SourceStream& SourceStream::operator<<(const Identifier &s)
71{
72 str += s.ustring();
73 return *this;
74}
75
76SourceStream& SourceStream::operator<<(const Node *n)
77{
78 if (n)
79 n->streamTo(*this);
80 return *this;
81}
82
83SourceStream& 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
100UString Node::toString() const
101{
102 SourceStream str;
103 streamTo(str);
104
105 return str.toString();
106}
107
108void NullNode::streamTo(SourceStream &s) const { s << "null"; }
109
110void BooleanNode::streamTo(SourceStream &s) const
111{
112 s << (value ? "true" : "false");
113}
114
115void NumberNode::streamTo(SourceStream &s) const { s << UString::from(value); }
116
117void StringNode::streamTo(SourceStream &s) const
118{
119 s << '"' << value << '"';
120}
121
122void RegExpNode::streamTo(SourceStream &s) const { s << pattern; }
123
124void ThisNode::streamTo(SourceStream &s) const { s << "this"; }
125
126void ResolveNode::streamTo(SourceStream &s) const { s << ident; }
127
128void GroupNode::streamTo(SourceStream &s) const
129{
130 s << "(" << group << ")";
131}
132
133void 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
142void ArrayNode::streamTo(SourceStream &s) const
143{
144 s << "[" << element;
145 for (int i = 0; i < elision; i++)
146 s << ",";
147 s << "]";
148}
149
150void ObjectLiteralNode::streamTo(SourceStream &s) const
151{
152 if (list)
153 s << "{ " << list << " }";
154 else
155 s << "{ }";
156}
157
158void 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
166void 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
186void PropertyNameNode::streamTo(SourceStream &s) const
187{
188 if (str.isNull())
189 s << UString::from(numeric);
190 else
191 s << str;
192}
193
194void BracketAccessorNode::streamTo(SourceStream &s) const
195{
196 s << expr1 << "[" << expr2 << "]";
197}
198
199void DotAccessorNode::streamTo(SourceStream &s) const
200{
201 s << expr << "." << ident;
202}
203
204void 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
211void ArgumentsNode::streamTo(SourceStream &s) const
212{
213 s << "(" << list << ")";
214}
215
216void NewExprNode::streamTo(SourceStream &s) const
217{
218 s << "new " << expr << args;
219}
220
221void FunctionCallValueNode::streamTo(SourceStream &s) const
222{
223 s << expr << args;
224}
225
226void FunctionCallResolveNode::streamTo(SourceStream &s) const
227{
228 s << ident << args;
229}
230
231void FunctionCallBracketNode::streamTo(SourceStream &s) const
232{
233 s << base << "[" << subscript << "]" << args;
234}
235
236void FunctionCallParenBracketNode::streamTo(SourceStream &s) const
237{
238 s << "(" << base << "[" << subscript << "])" << args;
239}
240
241void FunctionCallDotNode::streamTo(SourceStream &s) const
242{
243 s << base << "." << ident << args;
244}
245
246void FunctionCallParenDotNode::streamTo(SourceStream &s) const
247{
248 s << "(" << base << "." << ident << ")" << args;
249}
250
251void PostfixResolveNode::streamTo(SourceStream &s) const
252{
253 s << m_ident;
254 if (m_oper == OpPlusPlus)
255 s << "++";
256 else
257 s << "--";
258}
259
260void 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
269void 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
278void DeleteResolveNode::streamTo(SourceStream &s) const
279{
280 s << "delete " << m_ident;
281}
282
283void DeleteBracketNode::streamTo(SourceStream &s) const
284{
285 s << "delete " << m_base << "[" << m_subscript << "]";
286}
287
288void DeleteDotNode::streamTo(SourceStream &s) const
289{
290 s << "delete " << m_base << "." << m_ident;
291}
292
293void DeleteValueNode::streamTo(SourceStream &s) const
294{
295 s << "delete " << m_expr;
296}
297
298void VoidNode::streamTo(SourceStream &s) const
299{
300 s << "void " << expr;
301}
302
303void TypeOfValueNode::streamTo(SourceStream &s) const
304{
305 s << "typeof " << m_expr;
306}
307
308void TypeOfResolveNode::streamTo(SourceStream &s) const
309{
310 s << "typeof " << m_ident;
311}
312
313void PrefixResolveNode::streamTo(SourceStream &s) const
314{
315 if (m_oper == OpPlusPlus)
316 s << "++";
317 else
318 s << "--";
319 s << m_ident;
320}
321
322void 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
331void 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
340void UnaryPlusNode::streamTo(SourceStream &s) const
341{
342 s << "+" << expr;
343}
344
345void NegateNode::streamTo(SourceStream &s) const
346{
347 s << "-" << expr;
348}
349
350void BitwiseNotNode::streamTo(SourceStream &s) const
351{
352 s << "~" << expr;
353}
354
355void LogicalNotNode::streamTo(SourceStream &s) const
356{
357 s << "!" << expr;
358}
359
360void MultNode::streamTo(SourceStream &s) const
361{
362 s << term1 << oper << term2;
363}
364
365void AddNode::streamTo(SourceStream &s) const
366{
367 s << term1 << oper << term2;
368}
369
370void 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
382void 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
410void 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
432void 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
444void BinaryLogicalNode::streamTo(SourceStream &s) const
445{
446 s << expr1 << (oper == OpAnd ? " && " : " || ") << expr2;
447}
448
449void ConditionalNode::streamTo(SourceStream &s) const
450{
451 s << logical << " ? " << expr1 << " : " << expr2;
452}
453
454static 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
500void AssignResolveNode::streamTo(SourceStream &s) const
501{
502 s << m_ident;
503 streamAssignmentOperatorTo(s, m_oper);
504 s << m_right;
505}
506
507void AssignBracketNode::streamTo(SourceStream &s) const
508{
509 s << m_base << "[" << m_subscript << "]";
510 streamAssignmentOperatorTo(s, m_oper);
511 s << m_right;
512}
513
514void AssignDotNode::streamTo(SourceStream &s) const
515{
516 s << m_base << "." << m_ident;
517 streamAssignmentOperatorTo(s, m_oper);
518 s << m_right;
519}
520
521void CommaNode::streamTo(SourceStream &s) const
522{
523 s << expr1 << ", " << expr2;
524}
525
526void AssignExprNode::streamTo(SourceStream &s) const
527{
528 s << " = " << expr;
529}
530
531void VarDeclNode::streamTo(SourceStream &s) const
532{
533 s << ident << init;
534}
535
536void 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
543void VarStatementNode::streamTo(SourceStream &s) const
544{
545 s << SourceStream::Endl << "var " << next << ";";
546}
547
548void BlockNode::streamTo(SourceStream &s) const
549{
550 s << SourceStream::Endl << "{" << SourceStream::Indent
551 << source << SourceStream::Unindent << SourceStream::Endl << "}";
552}
553
554void EmptyStatementNode::streamTo(SourceStream &s) const
555{
556 s << SourceStream::Endl << ";";
557}
558
559void ExprStatementNode::streamTo(SourceStream &s) const
560{
561 s << SourceStream::Endl << expr << ";";
562}
563
564void 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
573void DoWhileNode::streamTo(SourceStream &s) const
574{
575 s << SourceStream::Endl << "do " << SourceStream::Indent
576 << statement << SourceStream::Unindent << SourceStream::Endl
577 << "while (" << expr << ");";
578}
579
580void WhileNode::streamTo(SourceStream &s) const
581{
582 s << SourceStream::Endl << "while (" << expr << ")" << SourceStream::Indent
583 << statement << SourceStream::Unindent;
584}
585
586void 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
595void 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
609void ContinueNode::streamTo(SourceStream &s) const
610{
611 s << SourceStream::Endl << "continue";
612 if (!ident.isNull())
613 s << " " << ident;
614 s << ";";
615}
616
617void BreakNode::streamTo(SourceStream &s) const
618{
619 s << SourceStream::Endl << "break";
620 if (!ident.isNull())
621 s << " " << ident;
622 s << ";";
623}
624
625void ReturnNode::streamTo(SourceStream &s) const
626{
627 s << SourceStream::Endl << "return";
628 if (value)
629 s << " " << value;
630 s << ";";
631}
632
633void WithNode::streamTo(SourceStream &s) const
634{
635 s << SourceStream::Endl << "with (" << expr << ") "
636 << statement;
637}
638
639void 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
652void ClauseListNode::streamTo(SourceStream &s) const
653{
654 for (const ClauseListNode *n = this; n; n = n->getNext())
655 s << n->getClause();
656}
657
658void 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
668void SwitchNode::streamTo(SourceStream &s) const
669{
670 s << SourceStream::Endl << "switch (" << expr << ") {"
671 << SourceStream::Indent << block << SourceStream::Unindent
672 << SourceStream::Endl << "}";
673}
674
675void LabelNode::streamTo(SourceStream &s) const
676{
677 s << SourceStream::Endl << label << ":" << SourceStream::Indent
678 << statement << SourceStream::Unindent;
679}
680
681void ThrowNode::streamTo(SourceStream &s) const
682{
683 s << SourceStream::Endl << "throw " << expr << ";";
684}
685
686void 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
695void 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
702void FuncDeclNode::streamTo(SourceStream &s) const
703{
704 s << SourceStream::Endl << "function " << ident << "(" << param << ")" << body;
705}
706
707void FuncExprNode::streamTo(SourceStream &s) const
708{
709 s << "function " << ident << "(" << param << ")" << body;
710}
711
712void SourceElementsNode::streamTo(SourceStream &s) const
713{
714 for (const SourceElementsNode *n = this; n; n = n->next.get())
715 s << n->node;
716}
Note: See TracBrowser for help on using the repository browser.