]> git.saurik.com Git - cycript.git/blame - Output.cpp
Support SO variable even when not Mach.
[cycript.git] / Output.cpp
CommitLineData
b3378a02
JF
1/* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2010 Jay Freeman (saurik)
4644480a
JF
3*/
4
b3378a02 5/* GNU Lesser General Public License, Version 3 {{{ */
4644480a 6/*
b3378a02
JF
7 * Cycript is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
4644480a 11 *
b3378a02
JF
12 * Cycript is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
4644480a 16 *
b3378a02
JF
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
19**/
4644480a
JF
20/* }}} */
21
520c130f 22#include "cycript.hpp"
5999c315
JF
23#include "Parser.hpp"
24
4afefdd9
JF
25#include <sstream>
26
b09da87b
JF
27_finline CYFlags operator ~(CYFlags rhs) {
28 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
29}
30
31_finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
32 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
33}
34
35_finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
36 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
37}
38
39_finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
40 return lhs = lhs | rhs;
41}
42
43_finline CYFlags CYLeft(CYFlags flags) {
9561f209 44 return flags & ~(CYNoDangle | CYNoInteger);
b09da87b
JF
45}
46
96a7e5c2
JF
47_finline CYFlags CYRight(CYFlags flags) {
48 return flags & ~CYNoBF;
b09da87b
JF
49}
50
96a7e5c2 51_finline CYFlags CYCenter(CYFlags flags) {
d29365ce 52 return CYLeft(CYRight(flags));
b09da87b
JF
53}
54
1fdca2fa
JF
55void CYOutput::Terminate() {
56 out_ << ';';
57 mode_ = NoMode;
58}
59
96a7e5c2 60CYOutput &CYOutput::operator <<(char rhs) {
1fdca2fa
JF
61 if (rhs == ' ' || rhs == '\n')
62 if (pretty_)
63 out_ << rhs;
64 else goto done;
65 else if (rhs == '\t')
66 if (pretty_)
67 for (unsigned i(0); i != indent_; ++i)
68 out_ << " ";
69 else goto done;
320ce753
JF
70 else if (rhs == '\r') {
71 if (right_) {
72 out_ << '\n';
73 right_ = false;
14ec9e00 74 } goto done;
320ce753 75 } else goto work;
1fdca2fa 76
320ce753 77 right_ = true;
1fdca2fa
JF
78 mode_ = NoMode;
79 goto done;
96a7e5c2 80
1fdca2fa 81 work:
320ce753
JF
82 if (mode_ == Terminated && rhs != '}') {
83 right_ = true;
96a7e5c2 84 out_ << ';';
320ce753 85 }
96a7e5c2
JF
86
87 if (rhs == ';') {
88 if (pretty_)
89 goto none;
90 else {
91 mode_ = Terminated;
92 goto done;
93 }
c0bc320e
JF
94 } else if (rhs == '+') {
95 if (mode_ == NoPlus)
96 out_ << ' ';
97 mode_ = NoPlus;
96a7e5c2
JF
98 } else if (rhs == '-') {
99 if (mode_ == NoHyphen)
100 out_ << ' ';
101 mode_ = NoHyphen;
102 } else if (WordEndRange_[rhs]) {
103 if (mode_ == NoLetter)
104 out_ << ' ';
105 mode_ = NoLetter;
106 } else none:
107 mode_ = NoMode;
108
320ce753 109 right_ = true;
96a7e5c2
JF
110 out_ << rhs;
111 done:
112 return *this;
113}
114
115CYOutput &CYOutput::operator <<(const char *rhs) {
116 size_t size(strlen(rhs));
117
118 if (size == 1)
119 return *this << *rhs;
120
121 if (mode_ == Terminated)
122 out_ << ';';
123 else if (
c0bc320e 124 mode_ == NoPlus && *rhs == '+' ||
96a7e5c2
JF
125 mode_ == NoHyphen && *rhs == '-' ||
126 mode_ == NoLetter && WordEndRange_[*rhs]
127 )
128 out_ << ' ';
129
130 if (WordEndRange_[rhs[size - 1]])
131 mode_ = NoLetter;
132 else
133 mode_ = NoMode;
134
320ce753 135 right_ = true;
96a7e5c2
JF
136 out_ << rhs;
137 return *this;
138}
139
652ec1ba 140void CYArgument::Output(CYOutput &out) const {
d35a3b07 141 if (name_ != NULL) {
5999c315 142 out << *name_;
96a7e5c2
JF
143 if (value_ != NULL)
144 out << ':' << ' ';
5999c315 145 }
d35a3b07 146 if (value_ != NULL)
8351aa30 147 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
5999c315 148 if (next_ != NULL) {
96a7e5c2 149 if (next_->name_ == NULL)
11c1cc16 150 out << ',';
96a7e5c2 151 out << ' ' << *next_;
5999c315
JF
152 }
153}
154
652ec1ba 155void CYArray::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 156 out << '[' << elements_ << ']';
5befe15e
JF
157}
158
652ec1ba 159void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
4644480a 160 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
75b0a457
JF
161}
162
652ec1ba 163void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 164 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
96a7e5c2 165 out << ' ' << Operator() << ' ';
b09da87b 166 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
167}
168
3b52fd1a
JF
169void CYBlock::Output(CYOutput &out) const {
170 out << '{' << '\n';
171 ++out.indent_;
172 if (statements_ != NULL)
173 statements_->Multiple(out);
174 --out.indent_;
175 out << '\t' << '}';
176}
177
fb98ac0c 178void CYBlock::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a
JF
179 if (statements_ == NULL)
180 out.Terminate();
181 else if (statements_->next_ == NULL)
182 statements_->Single(out, flags);
183 else
184 Output(out);
9e562cfc
JF
185}
186
652ec1ba 187void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
188 out << (Value() ? "true" : "false");
189}
190
fb98ac0c 191void CYBreak::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
192 out << "break";
193 if (label_ != NULL)
194 out << ' ' << *label_;
96a7e5c2 195 out << ';';
5999c315
JF
196}
197
652ec1ba 198void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
199 bool protect((flags & CYNoCall) != 0);
200 if (protect)
201 out << '(';
202 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
96a7e5c2 203 out << '(' << arguments_ << ')';
fb98ac0c
JF
204 if (protect)
205 out << ')';
5999c315
JF
206}
207
37954781
JF
208namespace cy {
209namespace Syntax {
210
211void Catch::Output(CYOutput &out) const {
3b52fd1a 212 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
5999c315
JF
213}
214
37954781
JF
215} }
216
320ce753
JF
217void CYComment::Output(CYOutput &out, CYFlags flags) const {
218 out << '\r';
14ec9e00
JF
219 out.out_ << value_;
220 out.right_ = true;
320ce753
JF
221 out << '\r';
222}
223
652ec1ba 224void CYCompound::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
225 if (CYExpression *expression = expressions_)
226 if (CYExpression *next = expression->next_) {
227 expression->Output(out, CYLeft(flags));
228 CYFlags center(CYCenter(flags));
229 while (next != NULL) {
230 expression = next;
96a7e5c2 231 out << ',' << ' ';
e5bc40db
JF
232 next = expression->next_;
233 CYFlags right(next != NULL ? center : CYRight(flags));
234 expression->Output(out, right);
235 }
236 } else
237 expression->Output(out, flags);
238}
239
652ec1ba 240void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 241 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 242 out << ' ' << '?' << ' ';
5999c315 243 if (true_ != NULL)
8351aa30 244 true_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 245 out << ' ' << ':' << ' ';
8351aa30 246 false_->Output(out, CYAssign::Precedence_, CYRight(flags));
5999c315
JF
247}
248
fb98ac0c 249void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
250 out << "continue";
251 if (label_ != NULL)
252 out << ' ' << *label_;
96a7e5c2 253 out << ';';
5999c315
JF
254}
255
652ec1ba 256void CYClause::Output(CYOutput &out) const {
96a7e5c2
JF
257 if (case_ != NULL)
258 out << "case" << ' ' << *case_;
259 else
5999c315 260 out << "default";
1fdca2fa 261 out << ':' << '\n';
3b52fd1a
JF
262 if (statements_ != NULL)
263 statements_->Multiple(out);
96a7e5c2 264 out << next_;
cac61857
JF
265}
266
267const char *CYDeclaration::ForEachIn() const {
029bc65b 268 return identifier_->Word();
5999c315
JF
269}
270
652ec1ba 271void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 272 out << "var";
96a7e5c2 273 Output(out, CYRight(flags));
75b0a457
JF
274}
275
652ec1ba 276void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 277 out << *identifier_;
e013809d 278 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
d35a3b07 279 if (initialiser_ != NULL) {
96a7e5c2 280 out << ' ' << '=' << ' ';
8351aa30 281 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
96a7e5c2 282 }
5999c315
JF
283}
284
652ec1ba 285void CYDeclarations::For(CYOutput &out) const {
fb98ac0c 286 out << "var";
96a7e5c2
JF
287 Output(out, CYNoIn);
288}
289
290void CYDeclarations::Output(CYOutput &out) const {
291 Output(out, CYNoFlags);
cac61857 292}
d35a3b07 293
652ec1ba 294void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 295 const CYDeclarations *declaration(this);
fb98ac0c 296 bool first(true);
d35a3b07 297 output:
75b0a457 298 CYDeclarations *next(declaration->next_);
fb98ac0c
JF
299 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
300 first = false;
301 declaration->declaration_->Output(out, jacks);
d35a3b07 302
75b0a457 303 if (next != NULL) {
96a7e5c2 304 out << ',' << ' ';
75b0a457 305 declaration = next;
d35a3b07
JF
306 goto output;
307 }
5999c315
JF
308}
309
652ec1ba 310void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
b38adb44 311 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
9b5527f0
JF
312 if (const char *word = property_->Word())
313 out << '.' << word;
96a7e5c2
JF
314 else
315 out << '[' << *property_ << ']';
9b5527f0
JF
316}
317
fb98ac0c 318void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 319 out << "do";
d29365ce 320 code_->Single(out, CYCenter(flags));
96a7e5c2 321 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
322}
323
652ec1ba 324void CYElement::Output(CYOutput &out) const {
5999c315 325 if (value_ != NULL)
8351aa30 326 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
11c1cc16 327 if (next_ != NULL || value_ == NULL) {
5999c315 328 out << ',';
96a7e5c2 329 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
330 out << ' ';
331 }
5befe15e
JF
332 if (next_ != NULL)
333 next_->Output(out);
5999c315
JF
334}
335
fb98ac0c 336void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 337 out.Terminate();
5999c315
JF
338}
339
fb98ac0c 340void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
341 expression_->Output(out, flags | CYNoBF);
342 out << ';';
5999c315
JF
343}
344
652ec1ba 345void CYExpression::ClassName(CYOutput &out, bool object) const {
8351aa30 346 Output(out, CYAssign::Precedence_, CYNoFlags);
e5bc40db
JF
347}
348
cac61857
JF
349const char *CYExpression::ForEachIn() const {
350 return NULL;
351}
352
652ec1ba 353void CYExpression::For(CYOutput &out) const {
cac61857
JF
354 Output(out, CYNoIn);
355}
356
652ec1ba 357void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 358 Output(out, flags | CYNoRightHand);
d35a3b07
JF
359}
360
96a7e5c2
JF
361void CYExpression::Output(CYOutput &out) const {
362 Output(out, CYNoFlags);
363}
364
652ec1ba 365void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
96a7e5c2
JF
366 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
367 out << '(' << *this << ')';
368 else
b09da87b
JF
369 Output(out, flags);
370}
371
b10bd496 372void CYFinally::Output(CYOutput &out) const {
3b52fd1a 373 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
374}
375
fb98ac0c 376void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 377 out << "for" << ' ' << '(';
5999c315 378 if (initialiser_ != NULL)
cac61857 379 initialiser_->For(out);
1fdca2fa 380 out.Terminate();
96a7e5c2 381 out << test_;
1fdca2fa 382 out.Terminate();
96a7e5c2 383 out << increment_;
5999c315 384 out << ')';
d29365ce 385 code_->Single(out, CYRight(flags));
5999c315
JF
386}
387
fb98ac0c 388void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
389 out << "for" << ' ' << "each" << ' ' << '(';
390 initialiser_->ForIn(out, CYNoIn);
391 out << "in" << *set_ << ')';
392 code_->Single(out, CYRight(flags));
75b0a457
JF
393}
394
4644480a
JF
395void CYForEachInComprehension::Output(CYOutput &out) const {
396 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
397}
398
fb98ac0c 399void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 400 out << "for" << ' ' << '(';
029bc65b
JF
401 if (initialiser_ != NULL)
402 initialiser_->ForIn(out, CYNoIn);
96a7e5c2 403 out << "in" << *set_ << ')';
fb98ac0c 404 code_->Single(out, CYRight(flags));
5999c315
JF
405}
406
4644480a
JF
407void CYForInComprehension::Output(CYOutput &out) const {
408 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
409}
410
fb98ac0c 411void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 412 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
413 bool protect((flags & CYNoFunction) != 0);
414 if (protect)
415 out << '(';
fb98ac0c
JF
416 out << "function";
417 if (name_ != NULL)
418 out << ' ' << *name_;
1fdca2fa 419 out << '(' << parameters_ << ')';
3b52fd1a 420 out << ' ' << code_;
fb98ac0c
JF
421 if (protect)
422 out << ')';
423}
424
425void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
426 CYFunction::Output(out, flags);
427}
428
429void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
430 CYFunction::Output(out, flags);
b09da87b
JF
431}
432
652ec1ba 433void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b 434 out << *name_;
96a7e5c2
JF
435 if (next_ != NULL)
436 out << ',' << ' ' << *next_;
5999c315
JF
437}
438
029bc65b
JF
439const char *CYIdentifier::Word() const {
440 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
441}
442
fb98ac0c
JF
443void CYIf::Output(CYOutput &out, CYFlags flags) const {
444 bool protect(false);
445 if (false_ == NULL && (flags & CYNoDangle) != 0) {
446 protect = true;
447 out << '{';
96a7e5c2 448 }
1fdca2fa
JF
449
450 out << "if" << ' ' << '(' << *test_ << ')';
451
fb98ac0c 452 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 453
fb98ac0c 454 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
455 if (false_ == NULL)
456 jacks |= right;
d29365ce
JF
457 else
458 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 459
3b52fd1a 460 true_->Single(out, jacks);
1fdca2fa 461
5999c315 462 if (false_ != NULL) {
fb98ac0c 463 out << "else";
96a7e5c2 464 false_->Single(out, right);
5999c315 465 }
1fdca2fa 466
fb98ac0c
JF
467 if (protect)
468 out << '}';
5999c315
JF
469}
470
4644480a
JF
471void CYIfComprehension::Output(CYOutput &out) const {
472 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
473}
474
652ec1ba 475void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 476 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 477 if (const char *word = property_->Word())
3b52fd1a 478 out << "->" << word;
96a7e5c2 479 else
3b52fd1a 480 out << "->" << '[' << *property_ << ']';
5999c315
JF
481}
482
652ec1ba 483void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 484 const char *name(Operator());
d09e527c 485 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
486 if (protect)
487 out << '(';
b09da87b 488 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 489 lhs_->Output(out, Precedence(), left);
96a7e5c2 490 out << ' ' << name << ' ';
b09da87b 491 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
492 rhs_->Output(out, Precedence() - 1, right);
493 if (protect)
494 out << ')';
5999c315
JF
495}
496
3b52fd1a
JF
497void CYLabel::Output(CYOutput &out, CYFlags flags) const {
498 out << *name_ << ':' << ' ';
499 statement_->Single(out, CYRight(flags));
500}
501
fb98ac0c 502void CYLet::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 503 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
cac61857
JF
504}
505
2eb8215d
JF
506namespace cy {
507namespace Syntax {
508
509void New::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 510 out << "new" << ' ';
11c1cc16 511 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 512 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
513 if (arguments_ != NULL)
514 out << '(' << *arguments_ << ')';
5999c315
JF
515}
516
2eb8215d
JF
517} }
518
652ec1ba 519void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
520 CYWord::Output(out);
521}
522
652ec1ba 523void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
524 std::ostringstream str;
525 CYNumerify(str, Value());
9561f209
JF
526 std::string value(str.str());
527 out << value.c_str();
528 // XXX: this should probably also handle hex conversions and exponents
529 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
530 out << '.';
5999c315
JF
531}
532
652ec1ba 533void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 534 Output(out, CYNoFlags);
e5bc40db
JF
535}
536
652ec1ba 537void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
538 bool protect((flags & CYNoBrace) != 0);
539 if (protect)
540 out << '(';
c0bc320e
JF
541 out << '{' << '\n';
542 ++out.indent_;
3b52fd1a 543 out << properties_;
c0bc320e
JF
544 --out.indent_;
545 out << '\t' << '}';
b09da87b
JF
546 if (protect)
547 out << ')';
693d501b
JF
548}
549
4e11a430 550void CYOptionalFunctionParameter::Output(CYOutput &out) const {
6c093cce 551 out << *name_ << '=';
8351aa30 552 initializer_->Output(out, CYAssign::Precedence_, CYNoFlags);
4e11a430
JF
553 if (next_ != NULL)
554 out << ',' << ' ' << *next_;
555}
556
652ec1ba 557void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 558 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 559 out << Operator();
5999c315
JF
560}
561
652ec1ba 562void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 563 const char *name(Operator());
1ef7d061 564 out << name;
96a7e5c2 565 if (Alphabetic())
11c1cc16 566 out << ' ';
96a7e5c2 567 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
568}
569
3b52fd1a
JF
570void CYProgram::Output(CYOutput &out) const {
571 if (statements_ != NULL)
572 statements_->Multiple(out);
573}
574
652ec1ba 575void CYProperty::Output(CYOutput &out) const {
c0bc320e 576 out << '\t';
e5bc40db 577 name_->PropertyName(out);
96a7e5c2 578 out << ':' << ' ';
8351aa30 579 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 580 if (next_ != NULL)
c0bc320e
JF
581 out << ',' << '\n' << *next_;
582 else
583 out << '\n';
5999c315
JF
584}
585
63cd45c9
JF
586void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
587 out << Value();
63cd45c9
JF
588}
589
fb98ac0c 590void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
591 out << "return";
592 if (value_ != NULL)
593 out << ' ' << *value_;
594 out << ';';
5999c315
JF
595}
596
6c093cce
JF
597void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
598 call_->Output(out, CYLeft(flags));
599 out << ' ';
600 proc_->Output(out, CYRight(flags));
601}
602
603void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
604 // XXX: this is not outputting the parameters
605 out << code_;
606}
607
fb98ac0c
JF
608void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
609 bool first(true);
c2c9f509 610 CYForEach (next, this) {
fb98ac0c 611 bool last(next->next_ == NULL);
7bf4a0cd 612 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
fb98ac0c 613 first = false;
1fdca2fa 614 out << '\t';
fb98ac0c 615 next->Output(out, jacks);
1fdca2fa 616 out << '\n';
fb98ac0c 617 }
5999c315
JF
618}
619
3b52fd1a
JF
620void CYStatement::Single(CYOutput &out, CYFlags flags) const {
621 _assert(next_ == NULL);
622 out << '\n';
623 ++out.indent_;
624 out << '\t';
625 Output(out, flags);
626 out << '\n';
627 --out.indent_;
5999c315
JF
628}
629
652ec1ba 630void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 631 std::ostringstream str;
520c130f 632 CYStringify(str, value_, size_);
96a7e5c2 633 out << str.str().c_str();
5999c315
JF
634}
635
652ec1ba 636void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
637 if (const char *word = Word())
638 out << word;
639 else
96a7e5c2 640 out << *this;
e5bc40db
JF
641}
642
c0bc320e
JF
643static const char *Reserved_[] = {
644 "false", "null", "true",
645
646 "break", "case", "catch", "continue", "default",
647 "delete", "do", "else", "finally", "for", "function",
648 "if", "in", "instanceof", "new", "return", "switch",
649 "this", "throw", "try", "typeof", "var", "void",
650 "while", "with",
651
652 "debugger", "const",
653
654 "class", "enum", "export", "extends", "import", "super",
655
656 "abstract", "boolean", "byte", "char", "double", "final",
657 "float", "goto", "int", "long", "native", "short",
658 "synchronized", "throws", "transient", "volatile",
659
660 "let", "yield",
661
c0bc320e
JF
662 NULL
663};
664
11c1cc16
JF
665const char *CYString::Word() const {
666 if (size_ == 0 || !WordStartRange_[value_[0]])
667 return NULL;
668 for (size_t i(1); i != size_; ++i)
669 if (!WordEndRange_[value_[i]])
670 return NULL;
671 const char *value(Value());
c0bc320e 672 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
673 if (strcmp(*reserved, value) == 0)
674 return NULL;
675 return value;
676}
677
fb98ac0c 678void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
679 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
680 out << clauses_;
5999c315
JF
681 out << '}';
682}
683
652ec1ba 684void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
685 CYWord::Output(out);
686}
687
37954781
JF
688namespace cy {
689namespace Syntax {
690
691void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
692 out << "throw";
693 if (value_ != NULL)
694 out << ' ' << *value_;
695 out << ';';
5999c315
JF
696}
697
37954781 698void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 699 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
700}
701
37954781
JF
702} }
703
fb98ac0c 704void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 705 out << "var";
96a7e5c2
JF
706 declarations_->Output(out, flags);
707 out << ';';
cac61857
JF
708}
709
652ec1ba 710void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
711 out << *name_;
712}
713
fb98ac0c 714void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 715 out << "while" << '(' << *test_ << ')';
fb98ac0c 716 code_->Single(out, CYRight(flags));
5999c315
JF
717}
718
fb98ac0c 719void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 720 out << "with" << '(' << *scope_ << ')';
fb98ac0c 721 code_->Single(out, CYRight(flags));
5999c315
JF
722}
723
652ec1ba 724void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
725 if (object)
726 out << "objc_getClass(";
029bc65b 727 out << '"' << Word() << '"';
367eebb1
JF
728 if (object)
729 out << ')';
e5bc40db
JF
730}
731
652ec1ba 732void CYWord::Output(CYOutput &out) const {
029bc65b
JF
733 out << Word();
734 if (out.options_.verbose_)
735 out.out_ << '@' << this;
5999c315 736}
e5bc40db 737
652ec1ba 738void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
739 Output(out);
740}
029bc65b
JF
741
742const char *CYWord::Word() const {
743 return word_;
744}