]> git.saurik.com Git - cycript.git/blame - Output.cpp
Started working on making the build environment more portable.
[cycript.git] / Output.cpp
CommitLineData
5999c315
JF
1#include "Parser.hpp"
2
3#include <iostream>
4#include <iomanip>
5
4afefdd9
JF
6#include <objc/runtime.h>
7#include <sstream>
8
b09da87b
JF
9_finline CYFlags operator ~(CYFlags rhs) {
10 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
11}
12
13_finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
14 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
15}
16
17_finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
18 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
19}
20
21_finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
22 return lhs = lhs | rhs;
23}
24
25_finline CYFlags CYLeft(CYFlags flags) {
d29365ce 26 return flags & ~CYNoDangle;
b09da87b
JF
27}
28
96a7e5c2
JF
29_finline CYFlags CYRight(CYFlags flags) {
30 return flags & ~CYNoBF;
b09da87b
JF
31}
32
96a7e5c2 33_finline CYFlags CYCenter(CYFlags flags) {
d29365ce 34 return CYLeft(CYRight(flags));
b09da87b
JF
35}
36
11c1cc16 37#define CYPA 16
b09da87b 38
1fdca2fa
JF
39void CYOutput::Terminate() {
40 out_ << ';';
41 mode_ = NoMode;
42}
43
96a7e5c2 44CYOutput &CYOutput::operator <<(char rhs) {
1fdca2fa
JF
45 if (rhs == ' ' || rhs == '\n')
46 if (pretty_)
47 out_ << rhs;
48 else goto done;
49 else if (rhs == '\t')
50 if (pretty_)
51 for (unsigned i(0); i != indent_; ++i)
52 out_ << " ";
53 else goto done;
54 else goto work;
55
56 mode_ = NoMode;
57 goto done;
96a7e5c2 58
1fdca2fa 59 work:
96a7e5c2
JF
60 if (mode_ == Terminated && rhs != '}')
61 out_ << ';';
62
63 if (rhs == ';') {
64 if (pretty_)
65 goto none;
66 else {
67 mode_ = Terminated;
68 goto done;
69 }
c0bc320e
JF
70 } else if (rhs == '+') {
71 if (mode_ == NoPlus)
72 out_ << ' ';
73 mode_ = NoPlus;
96a7e5c2
JF
74 } else if (rhs == '-') {
75 if (mode_ == NoHyphen)
76 out_ << ' ';
77 mode_ = NoHyphen;
78 } else if (WordEndRange_[rhs]) {
79 if (mode_ == NoLetter)
80 out_ << ' ';
81 mode_ = NoLetter;
82 } else none:
83 mode_ = NoMode;
84
85 out_ << rhs;
86 done:
87 return *this;
88}
89
90CYOutput &CYOutput::operator <<(const char *rhs) {
91 size_t size(strlen(rhs));
92
93 if (size == 1)
94 return *this << *rhs;
95
96 if (mode_ == Terminated)
97 out_ << ';';
98 else if (
c0bc320e 99 mode_ == NoPlus && *rhs == '+' ||
96a7e5c2
JF
100 mode_ == NoHyphen && *rhs == '-' ||
101 mode_ == NoLetter && WordEndRange_[*rhs]
102 )
103 out_ << ' ';
104
105 if (WordEndRange_[rhs[size - 1]])
106 mode_ = NoLetter;
107 else
108 mode_ = NoMode;
109
110 out_ << rhs;
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)
b09da87b 121 value_->Output(out, CYPA, CYNoFlags);
5999c315 122 if (next_ != NULL) {
96a7e5c2 123 if (next_->name_ == NULL)
11c1cc16 124 out << ',';
96a7e5c2 125 out << ' ' << *next_;
5999c315
JF
126 }
127}
128
652ec1ba 129void CYArray::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 130 out << '[' << elements_ << ']';
5befe15e
JF
131}
132
652ec1ba 133void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
75b0a457
JF
134 // XXX: I don't necc. need the ()s
135 out << "(function($cyv";
136 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
137 if (const char *name = comprehension->Name())
138 out << ',' << name;
139 out << "){";
dc81e1c2 140 out << "$cyv=[];";
75b0a457 141 comprehensions_->Output(out);
dc81e1c2 142 out << "$cyv.push(";
75b0a457
JF
143 expression_->Output(out, CYPA, CYNoFlags);
144 out << ");";
145 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
146 comprehension->End_(out);
dc81e1c2 147 out << "return $cyv;";
75b0a457
JF
148 out << "}())";
149}
150
652ec1ba 151void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 152 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
96a7e5c2 153 out << ' ' << Operator() << ' ';
b09da87b 154 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
155}
156
3b52fd1a
JF
157void CYBlock::Output(CYOutput &out) const {
158 out << '{' << '\n';
159 ++out.indent_;
160 if (statements_ != NULL)
161 statements_->Multiple(out);
162 --out.indent_;
163 out << '\t' << '}';
164}
165
fb98ac0c 166void CYBlock::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a
JF
167 if (statements_ == NULL)
168 out.Terminate();
169 else if (statements_->next_ == NULL)
170 statements_->Single(out, flags);
171 else
172 Output(out);
9e562cfc
JF
173}
174
652ec1ba 175void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
176 out << (Value() ? "true" : "false");
177}
178
fb98ac0c 179void CYBreak::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
180 out << "break";
181 if (label_ != NULL)
182 out << ' ' << *label_;
96a7e5c2 183 out << ';';
5999c315
JF
184}
185
652ec1ba 186void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
187 bool protect((flags & CYNoCall) != 0);
188 if (protect)
189 out << '(';
190 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
96a7e5c2 191 out << '(' << arguments_ << ')';
fb98ac0c
JF
192 if (protect)
193 out << ')';
5999c315
JF
194}
195
652ec1ba 196void CYCatch::Output(CYOutput &out) const {
3b52fd1a 197 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
5999c315
JF
198}
199
fb98ac0c 200void CYCategory::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
201 out << "(function($cys,$cyp,$cyc,$cyn,$cyt){";
202 out << "$cyp=object_getClass($cys);";
203 out << "$cyc=$cys;";
204 if (messages_ != NULL)
205 messages_->Output(out, true);
206 out << "})(";
367eebb1 207 name_->ClassName(out, true);
fb98ac0c 208 out << ')';
96a7e5c2 209 out << ';';
365abb0a
JF
210}
211
652ec1ba 212void CYClass::Output(CYOutput &out, CYFlags flags) const {
367eebb1 213 // XXX: I don't necc. need the ()s
e5bc40db
JF
214 out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
215 out << "$cyp=object_getClass($cys);";
367eebb1
JF
216 out << "$cyc=objc_allocateClassPair($cys,";
217 if (name_ != NULL)
218 name_->ClassName(out, false);
219 else
220 out << "$cyq(\"CY$\")";
221 out << ",0);";
b09da87b
JF
222 out << "$cym=object_getClass($cyc);";
223 if (fields_ != NULL)
224 fields_->Output(out);
225 if (messages_ != NULL)
e5bc40db 226 messages_->Output(out, false);
b09da87b 227 out << "objc_registerClassPair($cyc);";
367eebb1
JF
228 out << "return $cyc;";
229 out << "}(";
b09da87b
JF
230 if (super_ != NULL)
231 super_->Output(out, CYPA, CYNoFlags);
232 else
233 out << "null";
367eebb1 234 out << "))";
b09da87b
JF
235}
236
fb98ac0c
JF
237void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
238 CYClass::Output(out, flags);
239}
240
241void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
242 CYClass::Output(out, flags);
243}
244
652ec1ba 245void CYCompound::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
246 if (CYExpression *expression = expressions_)
247 if (CYExpression *next = expression->next_) {
248 expression->Output(out, CYLeft(flags));
249 CYFlags center(CYCenter(flags));
250 while (next != NULL) {
251 expression = next;
96a7e5c2 252 out << ',' << ' ';
e5bc40db
JF
253 next = expression->next_;
254 CYFlags right(next != NULL ? center : CYRight(flags));
255 expression->Output(out, right);
256 }
257 } else
258 expression->Output(out, flags);
259}
260
652ec1ba 261void CYComprehension::Output(CYOutput &out) const {
75b0a457 262 Begin_(out);
96a7e5c2 263 out << next_;
75b0a457
JF
264}
265
652ec1ba 266void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 267 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 268 out << ' ' << '?' << ' ';
5999c315 269 if (true_ != NULL)
b09da87b 270 true_->Output(out, CYPA, CYNoFlags);
96a7e5c2 271 out << ' ' << ':' << ' ';
b09da87b 272 false_->Output(out, CYPA, CYRight(flags));
5999c315
JF
273}
274
fb98ac0c 275void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
276 out << "continue";
277 if (label_ != NULL)
278 out << ' ' << *label_;
96a7e5c2 279 out << ';';
5999c315
JF
280}
281
652ec1ba 282void CYClause::Output(CYOutput &out) const {
96a7e5c2
JF
283 if (case_ != NULL)
284 out << "case" << ' ' << *case_;
285 else
5999c315 286 out << "default";
1fdca2fa 287 out << ':' << '\n';
3b52fd1a
JF
288 if (statements_ != NULL)
289 statements_->Multiple(out);
96a7e5c2 290 out << next_;
cac61857
JF
291}
292
293const char *CYDeclaration::ForEachIn() const {
294 return identifier_->Value();
5999c315
JF
295}
296
652ec1ba 297void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 298 out << "var";
96a7e5c2 299 Output(out, CYRight(flags));
75b0a457
JF
300}
301
652ec1ba 302void CYDeclaration::ForEachIn(CYOutput &out) const {
75b0a457 303 out << *identifier_;
5999c315
JF
304}
305
652ec1ba 306void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 307 out << *identifier_;
d35a3b07 308 if (initialiser_ != NULL) {
96a7e5c2 309 out << ' ' << '=' << ' ';
75b0a457 310 initialiser_->Output(out, CYPA, CYRight(flags));
96a7e5c2 311 }
5999c315
JF
312}
313
652ec1ba 314void CYDeclarations::For(CYOutput &out) const {
fb98ac0c 315 out << "var";
96a7e5c2
JF
316 Output(out, CYNoIn);
317}
318
319void CYDeclarations::Output(CYOutput &out) const {
320 Output(out, CYNoFlags);
cac61857 321}
d35a3b07 322
652ec1ba 323void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 324 const CYDeclarations *declaration(this);
fb98ac0c 325 bool first(true);
d35a3b07 326 output:
75b0a457 327 CYDeclarations *next(declaration->next_);
fb98ac0c
JF
328 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
329 first = false;
330 declaration->declaration_->Output(out, jacks);
d35a3b07 331
75b0a457 332 if (next != NULL) {
96a7e5c2 333 out << ',' << ' ';
75b0a457 334 declaration = next;
d35a3b07
JF
335 goto output;
336 }
5999c315
JF
337}
338
652ec1ba 339void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0
JF
340 object_->Output(out, Precedence(), CYLeft(flags));
341 if (const char *word = property_->Word())
342 out << '.' << word;
96a7e5c2
JF
343 else
344 out << '[' << *property_ << ']';
9b5527f0
JF
345}
346
fb98ac0c 347void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 348 out << "do";
d29365ce 349 code_->Single(out, CYCenter(flags));
96a7e5c2 350 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
351}
352
652ec1ba 353void CYElement::Output(CYOutput &out) const {
5999c315 354 if (value_ != NULL)
b09da87b 355 value_->Output(out, CYPA, CYNoFlags);
11c1cc16 356 if (next_ != NULL || value_ == NULL) {
5999c315 357 out << ',';
96a7e5c2 358 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
359 out << ' ';
360 }
5befe15e
JF
361 if (next_ != NULL)
362 next_->Output(out);
5999c315
JF
363}
364
fb98ac0c 365void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 366 out.Terminate();
5999c315
JF
367}
368
fb98ac0c 369void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
370 expression_->Output(out, flags | CYNoBF);
371 out << ';';
5999c315
JF
372}
373
652ec1ba 374void CYExpression::ClassName(CYOutput &out, bool object) const {
e5bc40db
JF
375 Output(out, CYPA, CYNoFlags);
376}
377
cac61857
JF
378const char *CYExpression::ForEachIn() const {
379 return NULL;
380}
381
652ec1ba 382void CYExpression::For(CYOutput &out) const {
cac61857
JF
383 Output(out, CYNoIn);
384}
385
652ec1ba 386void CYExpression::ForEachIn(CYOutput &out) const {
fb98ac0c 387 Output(out, CYPA, CYNoRightHand);
75b0a457
JF
388}
389
652ec1ba 390void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 391 Output(out, flags | CYNoRightHand);
d35a3b07
JF
392}
393
96a7e5c2
JF
394void CYExpression::Output(CYOutput &out) const {
395 Output(out, CYNoFlags);
396}
397
652ec1ba 398void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
96a7e5c2
JF
399 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
400 out << '(' << *this << ')';
401 else
b09da87b
JF
402 Output(out, flags);
403}
404
652ec1ba 405void CYField::Output(CYOutput &out) const {
b09da87b 406 // XXX: implement!
5999c315
JF
407}
408
b10bd496 409void CYFinally::Output(CYOutput &out) const {
3b52fd1a 410 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
411}
412
fb98ac0c 413void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 414 out << "for" << ' ' << '(';
5999c315 415 if (initialiser_ != NULL)
cac61857 416 initialiser_->For(out);
1fdca2fa 417 out.Terminate();
96a7e5c2 418 out << test_;
1fdca2fa 419 out.Terminate();
96a7e5c2 420 out << increment_;
5999c315 421 out << ')';
d29365ce 422 code_->Single(out, CYRight(flags));
5999c315
JF
423}
424
fb98ac0c 425void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
6f926cee 426 out << "with({$cys:0,$cyt:0}){";
75b0a457 427
75b0a457
JF
428 out << "$cys=";
429 set_->Output(out, CYPA, CYNoFlags);
11c1cc16 430 out << ';';
75b0a457
JF
431
432 out << "for($cyt in $cys){";
433
434 initialiser_->ForEachIn(out);
435 out << "=$cys[$cyt];";
436
fb98ac0c 437 code_->Multiple(out);
75b0a457 438
6f926cee 439 out << '}';
75b0a457 440
6f926cee 441 out << '}';
75b0a457
JF
442}
443
652ec1ba 444void CYForEachInComprehension::Begin_(CYOutput &out) const {
75b0a457
JF
445 out << "(function($cys){";
446 out << "$cys=";
447 set_->Output(out, CYPA, CYNoFlags);
11c1cc16 448 out << ';';
75b0a457
JF
449
450 out << "for(" << *name_ << " in $cys){";
451 out << *name_ << "=$cys[" << *name_ << "];";
452}
453
652ec1ba 454void CYForEachInComprehension::End_(CYOutput &out) const {
75b0a457
JF
455 out << "}}());";
456}
457
fb98ac0c 458void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
459 out << "for" << ' ' << '(';
460 initialiser_->ForIn(out, CYNoIn);
461 out << "in" << *set_ << ')';
fb98ac0c 462 code_->Single(out, CYRight(flags));
5999c315
JF
463}
464
652ec1ba 465void CYForInComprehension::Begin_(CYOutput &out) const {
96a7e5c2 466 out << "for" << ' ' << '(' << *name_ << "in" << *set_ << ')';
75b0a457
JF
467}
468
fb98ac0c 469void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 470 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
471 bool protect((flags & CYNoFunction) != 0);
472 if (protect)
473 out << '(';
fb98ac0c
JF
474 out << "function";
475 if (name_ != NULL)
476 out << ' ' << *name_;
1fdca2fa 477 out << '(' << parameters_ << ')';
3b52fd1a 478 out << ' ' << code_;
fb98ac0c
JF
479 if (protect)
480 out << ')';
481}
482
483void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
484 CYFunction::Output(out, flags);
485}
486
487void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
488 CYFunction::Output(out, flags);
b09da87b
JF
489}
490
652ec1ba 491void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b 492 out << *name_;
96a7e5c2
JF
493 if (next_ != NULL)
494 out << ',' << ' ' << *next_;
5999c315
JF
495}
496
fb98ac0c
JF
497void CYIf::Output(CYOutput &out, CYFlags flags) const {
498 bool protect(false);
499 if (false_ == NULL && (flags & CYNoDangle) != 0) {
500 protect = true;
501 out << '{';
96a7e5c2 502 }
1fdca2fa
JF
503
504 out << "if" << ' ' << '(' << *test_ << ')';
505
fb98ac0c 506 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 507
fb98ac0c 508 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
509 if (false_ == NULL)
510 jacks |= right;
d29365ce
JF
511 else
512 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 513
3b52fd1a 514 true_->Single(out, jacks);
1fdca2fa 515
5999c315 516 if (false_ != NULL) {
fb98ac0c 517 out << "else";
96a7e5c2 518 false_->Single(out, right);
5999c315 519 }
1fdca2fa 520
fb98ac0c
JF
521 if (protect)
522 out << '}';
5999c315
JF
523}
524
652ec1ba 525void CYIfComprehension::Begin_(CYOutput &out) const {
96a7e5c2 526 out << "if" << '(' << *test_ << ')';
75b0a457
JF
527}
528
652ec1ba 529void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 530 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 531 if (const char *word = property_->Word())
3b52fd1a 532 out << "->" << word;
96a7e5c2 533 else
3b52fd1a 534 out << "->" << '[' << *property_ << ']';
5999c315
JF
535}
536
652ec1ba 537void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 538 const char *name(Operator());
d09e527c 539 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
540 if (protect)
541 out << '(';
b09da87b 542 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 543 lhs_->Output(out, Precedence(), left);
96a7e5c2 544 out << ' ' << name << ' ';
b09da87b 545 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
546 rhs_->Output(out, Precedence() - 1, right);
547 if (protect)
548 out << ')';
5999c315
JF
549}
550
3b52fd1a
JF
551void CYLabel::Output(CYOutput &out, CYFlags flags) const {
552 out << *name_ << ':' << ' ';
553 statement_->Single(out, CYRight(flags));
554}
555
fb98ac0c 556void CYLet::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 557 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
cac61857
JF
558}
559
652ec1ba 560void CYMessage::Output(CYOutput &out, bool replace) const {
4e8c99fb 561 if (next_ != NULL)
e5bc40db 562 next_->Output(out, replace);
b09da87b 563 out << "$cyn=new Selector(\"";
3b52fd1a 564 for (CYMessageParameter *parameter(parameters_); parameter != NULL; parameter = parameter->next_)
b09da87b
JF
565 if (parameter->tag_ != NULL) {
566 out << *parameter->tag_;
567 if (parameter->name_ != NULL)
5999c315
JF
568 out << ':';
569 }
b09da87b 570 out << "\");";
3b52fd1a
JF
571 out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ')' << ';';
572 out << (replace ? "class_replaceMethod" : "class_addMethod") << '(' << (instance_ ? "$cyc" : "$cym") << ',' << "$cyn" << ',';
478d4ed0 573 out << "new Functor(function(self,_cmd";
3b52fd1a 574 for (CYMessageParameter *parameter(parameters_); parameter != NULL; parameter = parameter->next_)
478d4ed0
JF
575 if (parameter->name_ != NULL)
576 out << ',' << *parameter->name_;
577 out << "){return function(){";
3b52fd1a
JF
578 if (statements_ != NULL)
579 statements_->Multiple(out);
478d4ed0 580 out << "}.call(self);},$cyt),$cyt);";
5999c315
JF
581}
582
652ec1ba 583void CYNew::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 584 out << "new" << ' ';
11c1cc16 585 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 586 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
587 if (arguments_ != NULL)
588 out << '(' << *arguments_ << ')';
5999c315
JF
589}
590
652ec1ba 591void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
592 CYWord::Output(out);
593}
594
652ec1ba 595void CYNumber::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
596 char value[32];
597 sprintf(value, "%.17g", Value());
598 out << value;
5999c315
JF
599}
600
652ec1ba 601void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 602 Output(out, CYNoFlags);
e5bc40db
JF
603}
604
652ec1ba 605void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
606 bool protect((flags & CYNoBrace) != 0);
607 if (protect)
608 out << '(';
c0bc320e
JF
609 out << '{' << '\n';
610 ++out.indent_;
3b52fd1a 611 out << properties_;
c0bc320e
JF
612 --out.indent_;
613 out << '\t' << '}';
b09da87b
JF
614 if (protect)
615 out << ')';
693d501b
JF
616}
617
652ec1ba 618void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 619 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 620 out << Operator();
5999c315
JF
621}
622
652ec1ba 623void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 624 const char *name(Operator());
1ef7d061 625 out << name;
96a7e5c2 626 if (Alphabetic())
11c1cc16 627 out << ' ';
96a7e5c2 628 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
629}
630
3b52fd1a
JF
631void CYProgram::Output(CYOutput &out) const {
632 if (statements_ != NULL)
633 statements_->Multiple(out);
634}
635
652ec1ba 636void CYProperty::Output(CYOutput &out) const {
c0bc320e 637 out << '\t';
e5bc40db 638 name_->PropertyName(out);
96a7e5c2 639 out << ':' << ' ';
b09da87b 640 value_->Output(out, CYPA, CYNoFlags);
96a7e5c2 641 if (next_ != NULL)
c0bc320e
JF
642 out << ',' << '\n' << *next_;
643 else
644 out << '\n';
5999c315
JF
645}
646
63cd45c9
JF
647void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
648 out << Value();
63cd45c9
JF
649}
650
fb98ac0c 651void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
652 out << "return";
653 if (value_ != NULL)
654 out << ' ' << *value_;
655 out << ';';
5999c315
JF
656}
657
652ec1ba 658void CYSelector::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 659 out << "@selector" << '(' << name_ << ')';
e7ed5354
JF
660}
661
652ec1ba 662void CYSelectorPart::Output(CYOutput &out) const {
96a7e5c2 663 out << name_;
62014ea9
JF
664 if (value_)
665 out << ':';
96a7e5c2 666 out << next_;
62014ea9
JF
667}
668
652ec1ba 669void CYSend::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 670 out << '[';
b09da87b 671 self_->Output(out, CYPA, CYNoFlags);
3b52fd1a
JF
672 out << ']';
673
4afefdd9 674 std::ostringstream name;
b09da87b
JF
675 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
676 if (argument->name_ != NULL) {
4afefdd9 677 name << *argument->name_;
b09da87b 678 if (argument->value_ != NULL)
4afefdd9 679 name << ':';
b09da87b 680 }
3b52fd1a 681
652ec1ba 682 out.out_ << reinterpret_cast<void *>(sel_registerName(name.str().c_str()));
b09da87b
JF
683 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
684 if (argument->value_ != NULL) {
11c1cc16 685 out << ',';
b09da87b
JF
686 argument->value_->Output(out, CYPA, CYNoFlags);
687 }
688 out << ')';
689}
690
fb98ac0c
JF
691void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
692 bool first(true);
693 for (const CYStatement *next(this); next != NULL; next = next->next_) {
694 bool last(next->next_ == NULL);
695 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
fb98ac0c 696 first = false;
1fdca2fa 697 out << '\t';
fb98ac0c 698 next->Output(out, jacks);
1fdca2fa 699 out << '\n';
fb98ac0c 700 }
5999c315
JF
701}
702
3b52fd1a
JF
703void CYStatement::Single(CYOutput &out, CYFlags flags) const {
704 _assert(next_ == NULL);
705 out << '\n';
706 ++out.indent_;
707 out << '\t';
708 Output(out, flags);
709 out << '\n';
710 --out.indent_;
5999c315
JF
711}
712
652ec1ba 713void CYString::Output(CYOutput &out, CYFlags flags) const {
b4aa79af
JF
714 unsigned quot(0), apos(0);
715 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
716 if (*value == '"')
717 ++quot;
718 else if (*value == '\'')
719 ++apos;
720
721 bool single(quot > apos);
722
96a7e5c2
JF
723 std::ostringstream str;
724
725 str << (single ? '\'' : '"');
5999c315
JF
726 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
727 switch (*value) {
96a7e5c2
JF
728 case '\\': str << "\\\\"; break;
729 case '\b': str << "\\b"; break;
730 case '\f': str << "\\f"; break;
731 case '\n': str << "\\n"; break;
732 case '\r': str << "\\r"; break;
733 case '\t': str << "\\t"; break;
734 case '\v': str << "\\v"; break;
5999c315 735
b4aa79af
JF
736 case '"':
737 if (!single)
96a7e5c2 738 str << "\\\"";
b4aa79af
JF
739 else goto simple;
740 break;
741
742 case '\'':
743 if (single)
96a7e5c2 744 str << "\\'";
b4aa79af
JF
745 else goto simple;
746 break;
747
5999c315
JF
748 default:
749 if (*value < 0x20 || *value >= 0x7f)
96a7e5c2 750 str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
b4aa79af 751 else simple:
96a7e5c2 752 str << *value;
5999c315 753 }
96a7e5c2
JF
754 str << (single ? '\'' : '"');
755
756 out << str.str().c_str();
5999c315
JF
757}
758
652ec1ba 759void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
760 if (const char *word = Word())
761 out << word;
762 else
96a7e5c2 763 out << *this;
e5bc40db
JF
764}
765
c0bc320e
JF
766static const char *Reserved_[] = {
767 "false", "null", "true",
768
769 "break", "case", "catch", "continue", "default",
770 "delete", "do", "else", "finally", "for", "function",
771 "if", "in", "instanceof", "new", "return", "switch",
772 "this", "throw", "try", "typeof", "var", "void",
773 "while", "with",
774
775 "debugger", "const",
776
777 "class", "enum", "export", "extends", "import", "super",
778
779 "abstract", "boolean", "byte", "char", "double", "final",
780 "float", "goto", "int", "long", "native", "short",
781 "synchronized", "throws", "transient", "volatile",
782
783 "let", "yield",
784
785 "each",
786
787 NULL
788};
789
11c1cc16
JF
790const char *CYString::Word() const {
791 if (size_ == 0 || !WordStartRange_[value_[0]])
792 return NULL;
793 for (size_t i(1); i != size_; ++i)
794 if (!WordEndRange_[value_[i]])
795 return NULL;
796 const char *value(Value());
c0bc320e 797 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
798 if (strcmp(*reserved, value) == 0)
799 return NULL;
800 return value;
801}
802
fb98ac0c 803void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
804 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
805 out << clauses_;
5999c315
JF
806 out << '}';
807}
808
652ec1ba 809void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
810 CYWord::Output(out);
811}
812
fb98ac0c 813void CYThrow::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
814 out << "throw";
815 if (value_ != NULL)
816 out << ' ' << *value_;
817 out << ';';
5999c315
JF
818}
819
fb98ac0c 820void CYTry::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 821 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
822}
823
fb98ac0c 824void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 825 out << "var";
96a7e5c2
JF
826 declarations_->Output(out, flags);
827 out << ';';
cac61857
JF
828}
829
652ec1ba 830void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
831 out << *name_;
832}
833
fb98ac0c 834void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 835 out << "while" << '(' << *test_ << ')';
fb98ac0c 836 code_->Single(out, CYRight(flags));
5999c315
JF
837}
838
fb98ac0c 839void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 840 out << "with" << '(' << *scope_ << ')';
fb98ac0c 841 code_->Single(out, CYRight(flags));
5999c315
JF
842}
843
652ec1ba 844void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
845 if (object)
846 out << "objc_getClass(";
847 out << '"' << Value() << '"';
848 if (object)
849 out << ')';
e5bc40db
JF
850}
851
652ec1ba 852void CYWord::Output(CYOutput &out) const {
5999c315
JF
853 out << Value();
854}
e5bc40db 855
652ec1ba 856void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
857 Output(out);
858}