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