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