]> git.saurik.com Git - cycript.git/blame - Output.cpp
Implement output of Objective-C class field lists.
[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 23
4afefdd9
JF
24#include <sstream>
25
20052ff7
JF
26#include "Syntax.hpp"
27
1fdca2fa 28void CYOutput::Terminate() {
efd689d8 29 operator ()(';');
1fdca2fa
JF
30 mode_ = NoMode;
31}
32
96a7e5c2 33CYOutput &CYOutput::operator <<(char rhs) {
1fdca2fa
JF
34 if (rhs == ' ' || rhs == '\n')
35 if (pretty_)
efd689d8 36 operator ()(rhs);
1fdca2fa
JF
37 else goto done;
38 else if (rhs == '\t')
39 if (pretty_)
40 for (unsigned i(0); i != indent_; ++i)
efd689d8 41 operator ()(" ", 4);
1fdca2fa 42 else goto done;
320ce753
JF
43 else if (rhs == '\r') {
44 if (right_) {
efd689d8 45 operator ()('\n');
320ce753 46 right_ = false;
14ec9e00 47 } goto done;
320ce753 48 } else goto work;
1fdca2fa 49
320ce753 50 right_ = true;
1fdca2fa
JF
51 mode_ = NoMode;
52 goto done;
96a7e5c2 53
1fdca2fa 54 work:
320ce753
JF
55 if (mode_ == Terminated && rhs != '}') {
56 right_ = true;
efd689d8 57 operator ()(';');
320ce753 58 }
96a7e5c2
JF
59
60 if (rhs == ';') {
61 if (pretty_)
62 goto none;
63 else {
64 mode_ = Terminated;
65 goto done;
66 }
c0bc320e
JF
67 } else if (rhs == '+') {
68 if (mode_ == NoPlus)
efd689d8 69 operator ()(' ');
c0bc320e 70 mode_ = NoPlus;
96a7e5c2
JF
71 } else if (rhs == '-') {
72 if (mode_ == NoHyphen)
efd689d8 73 operator ()(' ');
96a7e5c2
JF
74 mode_ = NoHyphen;
75 } else if (WordEndRange_[rhs]) {
76 if (mode_ == NoLetter)
efd689d8 77 operator ()(' ');
96a7e5c2
JF
78 mode_ = NoLetter;
79 } else none:
80 mode_ = NoMode;
81
320ce753 82 right_ = true;
efd689d8 83 operator ()(rhs);
96a7e5c2
JF
84 done:
85 return *this;
86}
87
88CYOutput &CYOutput::operator <<(const char *rhs) {
89 size_t size(strlen(rhs));
90
91 if (size == 1)
92 return *this << *rhs;
93
94 if (mode_ == Terminated)
efd689d8 95 operator ()(';');
96a7e5c2 96 else if (
c0bc320e 97 mode_ == NoPlus && *rhs == '+' ||
96a7e5c2
JF
98 mode_ == NoHyphen && *rhs == '-' ||
99 mode_ == NoLetter && WordEndRange_[*rhs]
100 )
efd689d8 101 operator ()(' ');
96a7e5c2 102
0482072a
JF
103 char last(rhs[size - 1]);
104 if (WordEndRange_[last] || last == '/')
96a7e5c2
JF
105 mode_ = NoLetter;
106 else
107 mode_ = NoMode;
108
320ce753 109 right_ = true;
efd689d8 110 operator ()(rhs, size);
96a7e5c2
JF
111 return *this;
112}
113
652ec1ba 114void CYArgument::Output(CYOutput &out) const {
d35a3b07 115 if (name_ != NULL) {
5999c315 116 out << *name_;
96a7e5c2
JF
117 if (value_ != NULL)
118 out << ':' << ' ';
5999c315 119 }
d35a3b07 120 if (value_ != NULL)
8351aa30 121 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
5999c315 122 if (next_ != NULL) {
068fc9b8 123 out << ',';
96a7e5c2 124 out << ' ' << *next_;
5999c315
JF
125 }
126}
127
652ec1ba 128void CYArray::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 129 out << '[' << elements_ << ']';
5befe15e
JF
130}
131
652ec1ba 132void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
4644480a 133 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
75b0a457
JF
134}
135
652ec1ba 136void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 137 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
96a7e5c2 138 out << ' ' << Operator() << ' ';
b09da87b 139 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
140}
141
b0385401 142void CYBlock::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a
JF
143 out << '{' << '\n';
144 ++out.indent_;
b0385401 145 out << code_;
3b52fd1a
JF
146 --out.indent_;
147 out << '\t' << '}';
148}
149
652ec1ba 150void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
76284c74
JF
151 out << '!' << (Value() ? "0" : "1");
152 if ((flags & CYNoInteger) != 0)
153 out << '.';
5999c315
JF
154}
155
fb98ac0c 156void CYBreak::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
157 out << "break";
158 if (label_ != NULL)
159 out << ' ' << *label_;
96a7e5c2 160 out << ';';
5999c315
JF
161}
162
652ec1ba 163void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
164 bool protect((flags & CYNoCall) != 0);
165 if (protect)
166 out << '(';
167 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
96a7e5c2 168 out << '(' << arguments_ << ')';
fb98ac0c
JF
169 if (protect)
170 out << ')';
5999c315
JF
171}
172
37954781
JF
173namespace cy {
174namespace Syntax {
175
176void Catch::Output(CYOutput &out) const {
b0385401
JF
177 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ';
178 out << '{' << '\n';
179 ++out.indent_;
180 out << code_;
181 --out.indent_;
182 out << '\t' << '}';
5999c315
JF
183}
184
37954781
JF
185} }
186
c5b15840
JF
187void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
188 bool protect((flags & CYNoClass) != 0);
189 if (protect)
190 out << '(';
191 out << "class";
192 if (name_ != NULL)
193 out << ' ' << *name_;
194 out << *tail_;;
195 if (protect)
196 out << ')';
197}
198
199void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
200 out << "class" << ' ' << *name_ << *tail_;
201}
202
203void CYClassTail::Output(CYOutput &out) const {
204 if (extends_ == NULL)
205 out << ' ';
206 else {
207 out << '\n';
208 ++out.indent_;
209 out << "extends" << ' ';
210 extends_->Output(out, CYAssign::Precedence_ - 1, CYNoFlags);
211 out << '\n';
212 --out.indent_;
213 }
214
215 out << '{' << '\n';
216 ++out.indent_;
217
218 --out.indent_;
219 out << '}';
220}
221
652ec1ba 222void CYCompound::Output(CYOutput &out, CYFlags flags) const {
fd5cdf97
JF
223 if (next_ == NULL)
224 expression_->Output(out, flags);
225 else {
226 expression_->Output(out, CYLeft(flags));
227 out << ',' << ' ';
228 next_->Output(out, CYRight(flags));
229 }
e5bc40db
JF
230}
231
c5b15840
JF
232void CYComputed::PropertyName(CYOutput &out) const {
233 out << '[';
234 expression_->Output(out, CYAssign::Precedence_, CYNoFlags);
235 out << ']';
236}
237
652ec1ba 238void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 239 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 240 out << ' ' << '?' << ' ';
5999c315 241 if (true_ != NULL)
8351aa30 242 true_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 243 out << ' ' << ':' << ' ';
8351aa30 244 false_->Output(out, CYAssign::Precedence_, CYRight(flags));
5999c315
JF
245}
246
fb98ac0c 247void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
248 out << "continue";
249 if (label_ != NULL)
250 out << ' ' << *label_;
96a7e5c2 251 out << ';';
5999c315
JF
252}
253
652ec1ba 254void CYClause::Output(CYOutput &out) const {
efd689d8 255 out << '\t';
09fc3efb
JF
256 if (value_ != NULL)
257 out << "case" << ' ' << *value_;
96a7e5c2 258 else
5999c315 259 out << "default";
1fdca2fa 260 out << ':' << '\n';
efd689d8 261 ++out.indent_;
b0385401 262 out << code_;
efd689d8 263 --out.indent_;
96a7e5c2 264 out << next_;
cac61857
JF
265}
266
c8a0500b
JF
267void CYDebugger::Output(CYOutput &out, CYFlags flags) const {
268 out << "debugger" << ';';
269}
270
09fc3efb 271void CYBinding::Output(CYOutput &out, CYFlags flags) const {
5999c315 272 out << *identifier_;
e013809d 273 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
09fc3efb 274 if (initializer_ != NULL) {
96a7e5c2 275 out << ' ' << '=' << ' ';
09fc3efb 276 initializer_->Output(out, CYAssign::Precedence_, CYRight(flags));
96a7e5c2 277 }
5999c315
JF
278}
279
09fc3efb 280void CYBindings::Output(CYOutput &out) const {
96a7e5c2 281 Output(out, CYNoFlags);
cac61857 282}
d35a3b07 283
09fc3efb
JF
284void CYBindings::Output(CYOutput &out, CYFlags flags) const {
285 const CYBindings *binding(this);
fb98ac0c 286 bool first(true);
d35a3b07 287
c8a0500b 288 for (;;) {
09fc3efb 289 CYBindings *next(binding->next_);
c8a0500b
JF
290
291 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
292 first = false;
09fc3efb 293 binding->binding_->Output(out, jacks);
c8a0500b
JF
294
295 if (next == NULL)
296 break;
297
96a7e5c2 298 out << ',' << ' ';
09fc3efb 299 binding = next;
d35a3b07 300 }
5999c315
JF
301}
302
652ec1ba 303void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
b38adb44 304 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
9b5527f0
JF
305 if (const char *word = property_->Word())
306 out << '.' << word;
96a7e5c2
JF
307 else
308 out << '[' << *property_ << ']';
9b5527f0
JF
309}
310
fb98ac0c 311void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 312 out << "do";
efd689d8
JF
313
314 unsigned line(out.position_.line);
315 unsigned indent(out.indent_);
316 code_->Single(out, CYCenter(flags), CYCompactLong);
317
318 if (out.position_.line != line && out.recent_ == indent)
319 out << ' ';
320 else
321 out << '\n' << '\t';
322
96a7e5c2 323 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
324}
325
fc8fc33d
JF
326void CYElementSpread::Output(CYOutput &out) const {
327 out << "..." << value_;
328}
329
330void CYElementValue::Output(CYOutput &out) const {
5999c315 331 if (value_ != NULL)
8351aa30 332 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
11c1cc16 333 if (next_ != NULL || value_ == NULL) {
5999c315 334 out << ',';
fc8fc33d 335 if (next_ != NULL && !next_->Elision())
11c1cc16
JF
336 out << ' ';
337 }
5befe15e
JF
338 if (next_ != NULL)
339 next_->Output(out);
5999c315
JF
340}
341
fb98ac0c 342void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 343 out.Terminate();
5999c315
JF
344}
345
7085e1ab
JF
346void CYEval::Output(CYOutput &out, CYFlags flags) const {
347 _assert(false);
348}
349
fb98ac0c 350void CYExpress::Output(CYOutput &out, CYFlags flags) const {
c5b15840 351 expression_->Output(out, flags | CYNoBFC);
96a7e5c2 352 out << ';';
5999c315
JF
353}
354
96a7e5c2
JF
355void CYExpression::Output(CYOutput &out) const {
356 Output(out, CYNoFlags);
357}
358
9a39f705 359void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const {
96a7e5c2
JF
360 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
361 out << '(' << *this << ')';
362 else
b09da87b
JF
363 Output(out, flags);
364}
365
c5587ed7
JF
366void CYExternal::Output(CYOutput &out, CYFlags flags) const {
367 out << "extern" << abi_ << typed_ << ';';
368}
369
a0be43fc 370void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
b0385401 371 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << '{' << code_ << '}';
a0be43fc
JF
372}
373
b10bd496 374void CYFinally::Output(CYOutput &out) const {
b0385401
JF
375 out << ' ' << "finally" << ' ';
376 out << '{' << '\n';
377 ++out.indent_;
378 out << code_;
379 --out.indent_;
380 out << '\t' << '}';
b10bd496
JF
381}
382
fb98ac0c 383void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 384 out << "for" << ' ' << '(';
09fc3efb
JF
385 if (initializer_ != NULL)
386 initializer_->Output(out, CYNoIn);
1fdca2fa 387 out.Terminate();
e661185c
JF
388 if (test_ != NULL)
389 out << ' ';
96a7e5c2 390 out << test_;
1fdca2fa 391 out.Terminate();
e661185c
JF
392 if (increment_ != NULL)
393 out << ' ';
96a7e5c2 394 out << increment_;
5999c315 395 out << ')';
efd689d8 396 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315 397}
75b0a457 398
7085e1ab
JF
399void CYForLexical::Output(CYOutput &out, CYFlags flags) const {
400 out << (constant_ ? "const" : "let") << ' ';
09fc3efb 401 binding_->Output(out, CYRight(flags));
75b0a457
JF
402}
403
fb98ac0c 404void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 405 out << "for" << ' ' << '(';
09fc3efb
JF
406 initializer_->Output(out, CYNoIn | CYNoRightHand);
407 out << ' ' << "in" << ' ' << *iterable_ << ')';
efd689d8 408 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
409}
410
23111dca
JF
411void CYForInitialized::Output(CYOutput &out, CYFlags flags) const {
412 out << "for" << ' ' << '(' << "var" << ' ';
09fc3efb
JF
413 binding_->Output(out, CYNoIn | CYNoRightHand);
414 out << ' ' << "in" << ' ' << *iterable_ << ')';
23111dca
JF
415 code_->Single(out, CYRight(flags), CYCompactShort);
416}
417
4644480a 418void CYForInComprehension::Output(CYOutput &out) const {
4e3c9056 419 out << "for" << ' ' << '(';
09fc3efb
JF
420 binding_->Output(out, CYNoIn | CYNoRightHand);
421 out << ' ' << "in" << ' ' << *iterable_ << ')';
75b0a457
JF
422}
423
7085e1ab
JF
424void CYForOf::Output(CYOutput &out, CYFlags flags) const {
425 out << "for" << ' ' << '(';
09fc3efb
JF
426 initializer_->Output(out, CYNoRightHand);
427 out << ' ' << "of" << ' ' << *iterable_ << ')';
7085e1ab
JF
428 code_->Single(out, CYRight(flags), CYCompactShort);
429}
430
431void CYForOfComprehension::Output(CYOutput &out) const {
432 out << "for" << ' ' << '(';
09fc3efb
JF
433 binding_->Output(out, CYNoRightHand);
434 out << ' ' << "of" << ' ' << *iterable_ << ')' << next_;
7085e1ab
JF
435}
436
437void CYForVariable::Output(CYOutput &out, CYFlags flags) const {
438 out << "var" << ' ';
09fc3efb 439 binding_->Output(out, CYRight(flags));
7085e1ab
JF
440}
441
c5b15840 442void CYFunction::Output(CYOutput &out) const {
b0385401
JF
443 out << '(' << parameters_ << ')' << ' ';
444 out << '{' << '\n';
445 ++out.indent_;
446 out << code_;
447 --out.indent_;
448 out << '\t' << '}';
fb98ac0c
JF
449}
450
451void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
c5b15840
JF
452 // XXX: one could imagine using + here to save a byte
453 bool protect((flags & CYNoFunction) != 0);
454 if (protect)
455 out << '(';
456 out << "function";
457 if (name_ != NULL)
458 out << ' ' << *name_;
459 CYFunction::Output(out);
460 if (protect)
461 out << ')';
fb98ac0c
JF
462}
463
464void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
c5b15840
JF
465 out << "function" << ' ' << *name_;
466 CYFunction::Output(out);
b09da87b
JF
467}
468
652ec1ba 469void CYFunctionParameter::Output(CYOutput &out) const {
09fc3efb 470 binding_->Output(out, CYNoFlags);
96a7e5c2
JF
471 if (next_ != NULL)
472 out << ',' << ' ' << *next_;
5999c315
JF
473}
474
029bc65b 475const char *CYIdentifier::Word() const {
7085e1ab 476 return next_ == NULL || next_ == this ? CYWord::Word() : next_->Word();
029bc65b
JF
477}
478
fb98ac0c
JF
479void CYIf::Output(CYOutput &out, CYFlags flags) const {
480 bool protect(false);
481 if (false_ == NULL && (flags & CYNoDangle) != 0) {
482 protect = true;
483 out << '{';
96a7e5c2 484 }
1fdca2fa
JF
485
486 out << "if" << ' ' << '(' << *test_ << ')';
487
fb98ac0c 488 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 489
fb98ac0c 490 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
491 if (false_ == NULL)
492 jacks |= right;
d29365ce
JF
493 else
494 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 495
efd689d8
JF
496 unsigned line(out.position_.line);
497 unsigned indent(out.indent_);
498 true_->Single(out, jacks, CYCompactShort);
1fdca2fa 499
5999c315 500 if (false_ != NULL) {
efd689d8
JF
501 if (out.position_.line != line && out.recent_ == indent)
502 out << ' ';
503 else
504 out << '\n' << '\t';
505
506 out << "else";
507 false_->Single(out, right, CYCompactLong);
5999c315 508 }
1fdca2fa 509
fb98ac0c
JF
510 if (protect)
511 out << '}';
5999c315
JF
512}
513
4644480a
JF
514void CYIfComprehension::Output(CYOutput &out) const {
515 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
516}
517
7b750785
JF
518void CYImport::Output(CYOutput &out, CYFlags flags) const {
519 out << "@import";
520}
521
7085e1ab
JF
522void CYIndirect::Output(CYOutput &out, CYFlags flags) const {
523 out << "*";
524 rhs_->Output(out, Precedence(), CYRight(flags));
525}
526
652ec1ba 527void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 528 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 529 if (const char *word = property_->Word())
3b52fd1a 530 out << "->" << word;
96a7e5c2 531 else
3b52fd1a 532 out << "->" << '[' << *property_ << ']';
5999c315
JF
533}
534
652ec1ba 535void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 536 const char *name(Operator());
d09e527c 537 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
538 if (protect)
539 out << '(';
b09da87b 540 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 541 lhs_->Output(out, Precedence(), left);
96a7e5c2 542 out << ' ' << name << ' ';
b09da87b 543 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
544 rhs_->Output(out, Precedence() - 1, right);
545 if (protect)
546 out << ')';
5999c315
JF
547}
548
3b52fd1a 549void CYLabel::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
550 out << *name_ << ':';
551 statement_->Single(out, CYRight(flags), CYCompactShort);
3b52fd1a
JF
552}
553
b0385401
JF
554void CYParenthetical::Output(CYOutput &out, CYFlags flags) const {
555 out << '(';
556 expression_->Output(out, CYCompound::Precedence_, CYNoFlags);
557 out << ')';
558}
559
560void CYStatement::Output(CYOutput &out) const {
561 Multiple(out);
562}
563
b900e1a4
JF
564void CYTemplate::Output(CYOutput &out, CYFlags flags) const {
565 _assert(false);
566}
567
9a39f705
JF
568void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
569 next_->Output(out, Precedence(), identifier);
570 out << '[';
571 out << size_;
572 out << ']';
573}
574
3fe16be7
JF
575void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
576 out << '(' << '^';
577 next_->Output(out, Precedence(), identifier);
578 out << ')' << '(' << parameters_ << ')';
579}
580
9a39f705 581void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
efd689d8 582 out << "const" << ' ';
9a39f705
JF
583 next_->Output(out, Precedence(), identifier);
584}
585
586void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
587 next_->Output(out, Precedence(), identifier);
588 out << '(' << parameters_ << ')';
589}
590
591void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
592 out << '*';
593 next_->Output(out, Precedence(), identifier);
594}
595
596void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
597 out << "volatile";
598 next_->Output(out, Precedence(), identifier);
599}
600
601void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
602 if (this == NULL) {
603 out << identifier;
604 return;
605 }
606
607 bool protect(precedence > Precedence());
608
609 if (protect)
610 out << '(';
611 Output(out, identifier);
612 if (protect)
613 out << ')';
614}
615
60097023 616void CYTypedIdentifier::Output(CYOutput &out) const {
3fe283c5 617 specifier_->Output(out);
9a39f705
JF
618 modifier_->Output(out, 0, identifier_);
619}
620
621void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
622 out << "@encode(" << typed_ << ")";
623}
624
625void CYTypedParameter::Output(CYOutput &out) const {
626 out << typed_;
627 if (next_ != NULL)
628 out << ',' << ' ' << next_;
60097023
JF
629}
630
690cf1a8
JF
631void CYLambda::Output(CYOutput &out, CYFlags flags) const {
632 // XXX: this is seriously wrong
633 out << "[](";
634 out << ")->";
635 out << "{";
636 out << "}";
637}
638
60097023 639void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
efd689d8 640 out << "typedef" << ' ' << *typed_;
60097023
JF
641}
642
64a505ff
JF
643void CYTypeExpression::Output(CYOutput &out, CYFlags flags) const {
644 out << '(' << "typedef" << ' ' << *typed_ << ')';
645}
646
09fc3efb 647void CYLexical::Output(CYOutput &out, CYFlags flags) const {
ca6a1b2b 648 out << "let" << ' ';
09fc3efb 649 bindings_->Output(out, flags); // XXX: flags
ca6a1b2b 650 out << ';';
cac61857
JF
651}
652
7b750785
JF
653void CYModule::Output(CYOutput &out) const {
654 out << part_;
655 if (next_ != NULL)
656 out << '.' << next_;
657}
658
2eb8215d
JF
659namespace cy {
660namespace Syntax {
661
662void New::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 663 out << "new" << ' ';
11c1cc16 664 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 665 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
666 if (arguments_ != NULL)
667 out << '(' << *arguments_ << ')';
5999c315
JF
668}
669
2eb8215d
JF
670} }
671
652ec1ba 672void CYNull::Output(CYOutput &out, CYFlags flags) const {
8f56307d 673 out << "null";
5999c315
JF
674}
675
652ec1ba 676void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
677 std::ostringstream str;
678 CYNumerify(str, Value());
9561f209
JF
679 std::string value(str.str());
680 out << value.c_str();
681 // XXX: this should probably also handle hex conversions and exponents
682 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
683 out << '.';
5999c315
JF
684}
685
652ec1ba 686void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 687 Output(out, CYNoFlags);
e5bc40db
JF
688}
689
652ec1ba 690void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
691 bool protect((flags & CYNoBrace) != 0);
692 if (protect)
693 out << '(';
c0bc320e
JF
694 out << '{' << '\n';
695 ++out.indent_;
3b52fd1a 696 out << properties_;
c0bc320e
JF
697 --out.indent_;
698 out << '\t' << '}';
b09da87b
JF
699 if (protect)
700 out << ')';
693d501b
JF
701}
702
652ec1ba 703void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 704 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 705 out << Operator();
5999c315
JF
706}
707
652ec1ba 708void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 709 const char *name(Operator());
1ef7d061 710 out << name;
96a7e5c2 711 if (Alphabetic())
11c1cc16 712 out << ' ';
96a7e5c2 713 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
714}
715
a7d8b413 716void CYScript::Output(CYOutput &out) const {
b0385401 717 out << code_;
3b52fd1a
JF
718}
719
652ec1ba 720void CYProperty::Output(CYOutput &out) const {
c5b15840
JF
721 if (next_ != NULL || out.pretty_)
722 out << ',';
723 out << '\n' << next_;
724}
725
726void CYPropertyGetter::Output(CYOutput &out) const {
727 out << "get" << ' ';
728 name_->PropertyName(out);
729 CYFunction::Output(out);
730 CYProperty::Output(out);
731}
732
733void CYPropertyMethod::Output(CYOutput &out) const {
734 name_->PropertyName(out);
735 CYFunction::Output(out);
736 CYProperty::Output(out);
737}
738
739void CYPropertySetter::Output(CYOutput &out) const {
740 out << "set" << ' ';
741 name_->PropertyName(out);
742 CYFunction::Output(out);
743 CYProperty::Output(out);
744}
745
746void CYPropertyValue::Output(CYOutput &out) const {
c0bc320e 747 out << '\t';
e5bc40db 748 name_->PropertyName(out);
96a7e5c2 749 out << ':' << ' ';
8351aa30 750 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
c5b15840 751 CYProperty::Output(out);
5999c315
JF
752}
753
63cd45c9
JF
754void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
755 out << Value();
63cd45c9
JF
756}
757
fb98ac0c 758void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
759 out << "return";
760 if (value_ != NULL)
761 out << ' ' << *value_;
762 out << ';';
5999c315
JF
763}
764
6c093cce
JF
765void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
766 call_->Output(out, CYLeft(flags));
767 out << ' ';
768 proc_->Output(out, CYRight(flags));
769}
770
771void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
0da459fc 772 out << '{' << ' ' << '|' << parameters_ << '|' << '\n';
b0385401 773 ++out.indent_;
6c093cce 774 out << code_;
b0385401
JF
775 --out.indent_;
776 out << '\t' << '}';
6c093cce
JF
777}
778
fb98ac0c
JF
779void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
780 bool first(true);
c2c9f509 781 CYForEach (next, this) {
fb98ac0c 782 bool last(next->next_ == NULL);
7bf4a0cd 783 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
fb98ac0c 784 first = false;
1fdca2fa 785 out << '\t';
fb98ac0c 786 next->Output(out, jacks);
1fdca2fa 787 out << '\n';
fb98ac0c 788 }
5999c315
JF
789}
790
efd689d8 791void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) const {
0f37eca9
JF
792 if (this == NULL)
793 return out.Terminate();
794
3b52fd1a 795 _assert(next_ == NULL);
efd689d8
JF
796
797 CYCompactType compact(Compact());
798
799 if (compact >= request)
800 out << ' ';
801 else {
802 out << '\n';
803 ++out.indent_;
804 out << '\t';
805 }
806
3b52fd1a 807 Output(out, flags);
efd689d8
JF
808
809 if (compact < request)
810 --out.indent_;
5999c315
JF
811}
812
652ec1ba 813void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 814 std::ostringstream str;
520c130f 815 CYStringify(str, value_, size_);
96a7e5c2 816 out << str.str().c_str();
5999c315
JF
817}
818
652ec1ba 819void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
820 if (const char *word = Word())
821 out << word;
822 else
96a7e5c2 823 out << *this;
e5bc40db
JF
824}
825
c0bc320e
JF
826static const char *Reserved_[] = {
827 "false", "null", "true",
828
829 "break", "case", "catch", "continue", "default",
830 "delete", "do", "else", "finally", "for", "function",
831 "if", "in", "instanceof", "new", "return", "switch",
832 "this", "throw", "try", "typeof", "var", "void",
833 "while", "with",
834
835 "debugger", "const",
836
837 "class", "enum", "export", "extends", "import", "super",
838
839 "abstract", "boolean", "byte", "char", "double", "final",
840 "float", "goto", "int", "long", "native", "short",
841 "synchronized", "throws", "transient", "volatile",
842
843 "let", "yield",
844
c0bc320e
JF
845 NULL
846};
847
11c1cc16
JF
848const char *CYString::Word() const {
849 if (size_ == 0 || !WordStartRange_[value_[0]])
850 return NULL;
851 for (size_t i(1); i != size_; ++i)
852 if (!WordEndRange_[value_[i]])
853 return NULL;
854 const char *value(Value());
c0bc320e 855 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
856 if (strcmp(*reserved, value) == 0)
857 return NULL;
858 return value;
859}
860
c5b15840
JF
861void CYSuperAccess::Output(CYOutput &out, CYFlags flags) const {
862 out << "super";
863 if (const char *word = property_->Word())
864 out << '.' << word;
865 else
866 out << '[' << *property_ << ']';
867}
868
869void CYSuperCall::Output(CYOutput &out, CYFlags flags) const {
870 out << "super" << '(' << arguments_ << ')';
871}
872
fb98ac0c 873void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
874 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{' << '\n';
875 ++out.indent_;
96a7e5c2 876 out << clauses_;
efd689d8
JF
877 --out.indent_;
878 out << '\t' << '}';
5999c315
JF
879}
880
652ec1ba 881void CYThis::Output(CYOutput &out, CYFlags flags) const {
8f56307d 882 out << "this";
5999c315
JF
883}
884
37954781
JF
885namespace cy {
886namespace Syntax {
887
888void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
889 out << "throw";
890 if (value_ != NULL)
891 out << ' ' << *value_;
892 out << ';';
5999c315
JF
893}
894
37954781 895void Try::Output(CYOutput &out, CYFlags flags) const {
b0385401
JF
896 out << "try" << ' ';
897 out << '{' << '\n';
898 ++out.indent_;
899 out << code_;
900 --out.indent_;
901 out << '\t' << '}';
902 out << catch_ << finally_;
5999c315
JF
903}
904
37954781
JF
905} }
906
03db6a67
JF
907void CYTypeError::Output(CYOutput &out) const {
908 out << "@error";
909}
910
3fe283c5
JF
911void CYTypeLong::Output(CYOutput &out) const {
912 out << "long" << specifier_;
913}
914
915void CYTypeShort::Output(CYOutput &out) const {
916 out << "short" << specifier_;
917}
918
919void CYTypeSigned::Output(CYOutput &out) const {
920 out << "signed" << specifier_;
921}
922
923void CYTypeUnsigned::Output(CYOutput &out) const {
924 out << "unsigned" << specifier_;
925}
926
927void CYTypeVariable::Output(CYOutput &out) const {
928 out << *name_;
929}
930
931void CYTypeVoid::Output(CYOutput &out) const {
932 out << "void";
933}
934
fb98ac0c 935void CYVar::Output(CYOutput &out, CYFlags flags) const {
efd689d8 936 out << "var" << ' ';
09fc3efb 937 bindings_->Output(out, flags); // XXX: flags
96a7e5c2 938 out << ';';
cac61857
JF
939}
940
652ec1ba 941void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
942 out << *name_;
943}
944
fb98ac0c 945void CYWhile::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
946 out << "while" << ' ' << '(' << *test_ << ')';
947 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
948}
949
fb98ac0c 950void CYWith::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
951 out << "with" << ' ' << '(' << *scope_ << ')';
952 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
953}
954
652ec1ba 955void CYWord::Output(CYOutput &out) const {
029bc65b 956 out << Word();
efd689d8
JF
957 if (out.options_.verbose_) {
958 out('@');
959 char number[32];
960 sprintf(number, "%p", this);
961 out(number);
962 }
5999c315 963}
e5bc40db 964
652ec1ba 965void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
966 Output(out);
967}
029bc65b
JF
968
969const char *CYWord::Word() const {
970 return word_;
971}