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