]> git.saurik.com Git - cycript.git/blame - Output.cpp
Put the filename in _trace to make it more useful.
[cycript.git] / Output.cpp
CommitLineData
b3378a02 1/* Cycript - Optimizing JavaScript Compiler/Runtime
c1d3e52e 2 * Copyright (C) 2009-2015 Jay Freeman (saurik)
4644480a
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
4644480a 6/*
f95d2598
JF
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
c15969fd 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f95d2598
JF
15 * GNU Affero General Public License for more details.
16
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
b3378a02 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";
bf1fd02c 252 declarations_->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
c5587ed7
JF
332void CYExternal::Output(CYOutput &out, CYFlags flags) const {
333 out << "extern" << abi_ << typed_ << ';';
334}
335
a0be43fc
JF
336void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
337 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << code_;
338}
339
b10bd496 340void CYFinally::Output(CYOutput &out) const {
3b52fd1a 341 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
342}
343
fb98ac0c 344void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 345 out << "for" << ' ' << '(';
5999c315 346 if (initialiser_ != NULL)
15b88a33 347 initialiser_->Output(out, CYNoIn);
1fdca2fa 348 out.Terminate();
e661185c
JF
349 if (test_ != NULL)
350 out << ' ';
96a7e5c2 351 out << test_;
1fdca2fa 352 out.Terminate();
e661185c
JF
353 if (increment_ != NULL)
354 out << ' ';
96a7e5c2 355 out << increment_;
5999c315 356 out << ')';
d29365ce 357 code_->Single(out, CYRight(flags));
5999c315
JF
358}
359
d5618df7 360void CYForOf::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
361 out << "for" << ' ' << "each" << ' ' << '(';
362 initialiser_->ForIn(out, CYNoIn);
363 out << "in" << *set_ << ')';
364 code_->Single(out, CYRight(flags));
75b0a457
JF
365}
366
d5618df7 367void CYForOfComprehension::Output(CYOutput &out) const {
4644480a 368 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
369}
370
fb98ac0c 371void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 372 out << "for" << ' ' << '(';
029bc65b
JF
373 if (initialiser_ != NULL)
374 initialiser_->ForIn(out, CYNoIn);
96a7e5c2 375 out << "in" << *set_ << ')';
fb98ac0c 376 code_->Single(out, CYRight(flags));
5999c315
JF
377}
378
4644480a
JF
379void CYForInComprehension::Output(CYOutput &out) const {
380 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
381}
382
fb98ac0c 383void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 384 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
385 bool protect((flags & CYNoFunction) != 0);
386 if (protect)
387 out << '(';
fb98ac0c
JF
388 out << "function";
389 if (name_ != NULL)
390 out << ' ' << *name_;
1fdca2fa 391 out << '(' << parameters_ << ')';
3b52fd1a 392 out << ' ' << code_;
fb98ac0c
JF
393 if (protect)
394 out << ')';
395}
396
397void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
398 CYFunction::Output(out, flags);
399}
400
401void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
402 CYFunction::Output(out, flags);
b09da87b
JF
403}
404
652ec1ba 405void CYFunctionParameter::Output(CYOutput &out) const {
c8a0500b 406 initialiser_->Output(out, CYNoFlags);
96a7e5c2
JF
407 if (next_ != NULL)
408 out << ',' << ' ' << *next_;
5999c315
JF
409}
410
029bc65b
JF
411const char *CYIdentifier::Word() const {
412 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
413}
414
fb98ac0c
JF
415void CYIf::Output(CYOutput &out, CYFlags flags) const {
416 bool protect(false);
417 if (false_ == NULL && (flags & CYNoDangle) != 0) {
418 protect = true;
419 out << '{';
96a7e5c2 420 }
1fdca2fa
JF
421
422 out << "if" << ' ' << '(' << *test_ << ')';
423
fb98ac0c 424 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 425
fb98ac0c 426 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
427 if (false_ == NULL)
428 jacks |= right;
d29365ce
JF
429 else
430 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 431
3b52fd1a 432 true_->Single(out, jacks);
1fdca2fa 433
5999c315 434 if (false_ != NULL) {
e661185c 435 out << '\t' << "else";
96a7e5c2 436 false_->Single(out, right);
5999c315 437 }
1fdca2fa 438
fb98ac0c
JF
439 if (protect)
440 out << '}';
5999c315
JF
441}
442
4644480a
JF
443void CYIfComprehension::Output(CYOutput &out) const {
444 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
445}
446
7b750785
JF
447void CYImport::Output(CYOutput &out, CYFlags flags) const {
448 out << "@import";
449}
450
652ec1ba 451void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 452 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 453 if (const char *word = property_->Word())
3b52fd1a 454 out << "->" << word;
96a7e5c2 455 else
3b52fd1a 456 out << "->" << '[' << *property_ << ']';
5999c315
JF
457}
458
652ec1ba 459void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 460 const char *name(Operator());
d09e527c 461 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
462 if (protect)
463 out << '(';
b09da87b 464 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 465 lhs_->Output(out, Precedence(), left);
96a7e5c2 466 out << ' ' << name << ' ';
b09da87b 467 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
468 rhs_->Output(out, Precedence() - 1, right);
469 if (protect)
470 out << ')';
5999c315
JF
471}
472
3b52fd1a
JF
473void CYLabel::Output(CYOutput &out, CYFlags flags) const {
474 out << *name_ << ':' << ' ';
475 statement_->Single(out, CYRight(flags));
476}
477
9a39f705
JF
478void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
479 next_->Output(out, Precedence(), identifier);
480 out << '[';
481 out << size_;
482 out << ']';
483}
484
3fe16be7
JF
485void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
486 out << '(' << '^';
487 next_->Output(out, Precedence(), identifier);
488 out << ')' << '(' << parameters_ << ')';
489}
490
9a39f705
JF
491void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
492 out << "const";
493 next_->Output(out, Precedence(), identifier);
494}
495
496void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
497 next_->Output(out, Precedence(), identifier);
498 out << '(' << parameters_ << ')';
499}
500
501void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
502 out << '*';
503 next_->Output(out, Precedence(), identifier);
504}
505
506void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
507 out << "volatile";
508 next_->Output(out, Precedence(), identifier);
509}
510
511void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
512 if (this == NULL) {
513 out << identifier;
514 return;
515 }
516
517 bool protect(precedence > Precedence());
518
519 if (protect)
520 out << '(';
521 Output(out, identifier);
522 if (protect)
523 out << ')';
524}
525
60097023 526void CYTypedIdentifier::Output(CYOutput &out) const {
3fe283c5 527 specifier_->Output(out);
9a39f705
JF
528 modifier_->Output(out, 0, identifier_);
529}
530
531void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
532 out << "@encode(" << typed_ << ")";
533}
534
535void CYTypedParameter::Output(CYOutput &out) const {
536 out << typed_;
537 if (next_ != NULL)
538 out << ',' << ' ' << next_;
60097023
JF
539}
540
690cf1a8
JF
541void CYLambda::Output(CYOutput &out, CYFlags flags) const {
542 // XXX: this is seriously wrong
543 out << "[](";
544 out << ")->";
545 out << "{";
546 out << "}";
547}
548
60097023
JF
549void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
550 out << "typedef" << *typed_;
551}
552
c8a0500b 553void CYLetStatement::Output(CYOutput &out, CYFlags flags) const {
15b88a33
JF
554 out << "let" << ' ' << '(' << *declarations_ << ')';
555 code_->Single(out, CYRight(flags));
cac61857
JF
556}
557
7b750785
JF
558void CYModule::Output(CYOutput &out) const {
559 out << part_;
560 if (next_ != NULL)
561 out << '.' << next_;
562}
563
2eb8215d
JF
564namespace cy {
565namespace Syntax {
566
567void New::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 568 out << "new" << ' ';
11c1cc16 569 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 570 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
571 if (arguments_ != NULL)
572 out << '(' << *arguments_ << ')';
5999c315
JF
573}
574
2eb8215d
JF
575} }
576
652ec1ba 577void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
578 CYWord::Output(out);
579}
580
652ec1ba 581void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
582 std::ostringstream str;
583 CYNumerify(str, Value());
9561f209
JF
584 std::string value(str.str());
585 out << value.c_str();
586 // XXX: this should probably also handle hex conversions and exponents
587 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
588 out << '.';
5999c315
JF
589}
590
652ec1ba 591void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 592 Output(out, CYNoFlags);
e5bc40db
JF
593}
594
652ec1ba 595void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
596 bool protect((flags & CYNoBrace) != 0);
597 if (protect)
598 out << '(';
c0bc320e
JF
599 out << '{' << '\n';
600 ++out.indent_;
3b52fd1a 601 out << properties_;
c0bc320e
JF
602 --out.indent_;
603 out << '\t' << '}';
b09da87b
JF
604 if (protect)
605 out << ')';
693d501b
JF
606}
607
652ec1ba 608void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 609 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 610 out << Operator();
5999c315
JF
611}
612
652ec1ba 613void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 614 const char *name(Operator());
1ef7d061 615 out << name;
96a7e5c2 616 if (Alphabetic())
11c1cc16 617 out << ' ';
96a7e5c2 618 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
619}
620
3b52fd1a
JF
621void CYProgram::Output(CYOutput &out) const {
622 if (statements_ != NULL)
623 statements_->Multiple(out);
624}
625
652ec1ba 626void CYProperty::Output(CYOutput &out) const {
c0bc320e 627 out << '\t';
e5bc40db 628 name_->PropertyName(out);
96a7e5c2 629 out << ':' << ' ';
8351aa30 630 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 631 if (next_ != NULL)
c0bc320e
JF
632 out << ',' << '\n' << *next_;
633 else
634 out << '\n';
5999c315
JF
635}
636
63cd45c9
JF
637void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
638 out << Value();
63cd45c9
JF
639}
640
fb98ac0c 641void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
642 out << "return";
643 if (value_ != NULL)
644 out << ' ' << *value_;
645 out << ';';
5999c315
JF
646}
647
6c093cce
JF
648void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
649 call_->Output(out, CYLeft(flags));
650 out << ' ';
651 proc_->Output(out, CYRight(flags));
652}
653
654void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
655 // XXX: this is not outputting the parameters
656 out << code_;
657}
658
fb98ac0c
JF
659void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
660 bool first(true);
c2c9f509 661 CYForEach (next, this) {
fb98ac0c 662 bool last(next->next_ == NULL);
7bf4a0cd 663 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
fb98ac0c 664 first = false;
1fdca2fa 665 out << '\t';
fb98ac0c 666 next->Output(out, jacks);
1fdca2fa 667 out << '\n';
fb98ac0c 668 }
5999c315
JF
669}
670
3b52fd1a 671void CYStatement::Single(CYOutput &out, CYFlags flags) const {
0f37eca9
JF
672 if (this == NULL)
673 return out.Terminate();
674
3b52fd1a
JF
675 _assert(next_ == NULL);
676 out << '\n';
677 ++out.indent_;
678 out << '\t';
679 Output(out, flags);
680 out << '\n';
681 --out.indent_;
5999c315
JF
682}
683
652ec1ba 684void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 685 std::ostringstream str;
520c130f 686 CYStringify(str, value_, size_);
96a7e5c2 687 out << str.str().c_str();
5999c315
JF
688}
689
652ec1ba 690void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
691 if (const char *word = Word())
692 out << word;
693 else
96a7e5c2 694 out << *this;
e5bc40db
JF
695}
696
c0bc320e
JF
697static const char *Reserved_[] = {
698 "false", "null", "true",
699
700 "break", "case", "catch", "continue", "default",
701 "delete", "do", "else", "finally", "for", "function",
702 "if", "in", "instanceof", "new", "return", "switch",
703 "this", "throw", "try", "typeof", "var", "void",
704 "while", "with",
705
706 "debugger", "const",
707
708 "class", "enum", "export", "extends", "import", "super",
709
710 "abstract", "boolean", "byte", "char", "double", "final",
711 "float", "goto", "int", "long", "native", "short",
712 "synchronized", "throws", "transient", "volatile",
713
714 "let", "yield",
715
c0bc320e
JF
716 NULL
717};
718
11c1cc16
JF
719const char *CYString::Word() const {
720 if (size_ == 0 || !WordStartRange_[value_[0]])
721 return NULL;
722 for (size_t i(1); i != size_; ++i)
723 if (!WordEndRange_[value_[i]])
724 return NULL;
725 const char *value(Value());
c0bc320e 726 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
727 if (strcmp(*reserved, value) == 0)
728 return NULL;
729 return value;
730}
731
fb98ac0c 732void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
733 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
734 out << clauses_;
5999c315
JF
735 out << '}';
736}
737
652ec1ba 738void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
739 CYWord::Output(out);
740}
741
37954781
JF
742namespace cy {
743namespace Syntax {
744
745void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
746 out << "throw";
747 if (value_ != NULL)
748 out << ' ' << *value_;
749 out << ';';
5999c315
JF
750}
751
37954781 752void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 753 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
754}
755
37954781
JF
756} }
757
03db6a67
JF
758void CYTypeError::Output(CYOutput &out) const {
759 out << "@error";
760}
761
3fe283c5
JF
762void CYTypeLong::Output(CYOutput &out) const {
763 out << "long" << specifier_;
764}
765
766void CYTypeShort::Output(CYOutput &out) const {
767 out << "short" << specifier_;
768}
769
770void CYTypeSigned::Output(CYOutput &out) const {
771 out << "signed" << specifier_;
772}
773
774void CYTypeUnsigned::Output(CYOutput &out) const {
775 out << "unsigned" << specifier_;
776}
777
778void CYTypeVariable::Output(CYOutput &out) const {
779 out << *name_;
780}
781
782void CYTypeVoid::Output(CYOutput &out) const {
783 out << "void";
784}
785
fb98ac0c 786void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 787 out << "var";
96a7e5c2
JF
788 declarations_->Output(out, flags);
789 out << ';';
cac61857
JF
790}
791
652ec1ba 792void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
793 out << *name_;
794}
795
fb98ac0c 796void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 797 out << "while" << '(' << *test_ << ')';
fb98ac0c 798 code_->Single(out, CYRight(flags));
5999c315
JF
799}
800
fb98ac0c 801void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 802 out << "with" << '(' << *scope_ << ')';
fb98ac0c 803 code_->Single(out, CYRight(flags));
5999c315
JF
804}
805
652ec1ba 806void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
807 if (object)
808 out << "objc_getClass(";
029bc65b 809 out << '"' << Word() << '"';
367eebb1
JF
810 if (object)
811 out << ')';
e5bc40db
JF
812}
813
652ec1ba 814void CYWord::Output(CYOutput &out) const {
029bc65b
JF
815 out << Word();
816 if (out.options_.verbose_)
817 out.out_ << '@' << this;
5999c315 818}
e5bc40db 819
652ec1ba 820void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
821 Output(out);
822}
029bc65b
JF
823
824const char *CYWord::Word() const {
825 return word_;
826}