]> git.saurik.com Git - cycript.git/blame - Output.cpp
Minor refactoring, checkpoint commit.
[cycript.git] / Output.cpp
CommitLineData
5999c315
JF
1#include "Parser.hpp"
2
3#include <iostream>
4#include <iomanip>
5
b09da87b
JF
6_finline CYFlags operator ~(CYFlags rhs) {
7 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
8}
9
10_finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
11 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
12}
13
14_finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
15 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
16}
17
18_finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
19 return lhs = lhs | rhs;
20}
21
22_finline CYFlags CYLeft(CYFlags flags) {
23 return flags & ~CYNoTrailer;
24}
25
26_finline CYFlags CYCenter(CYFlags flags) {
27 return flags & CYNoIn;
28}
29
30_finline CYFlags CYRight(CYFlags flags) {
31 return flags & (CYNoIn | CYNoTrailer);
32}
33
34bool CYFalse::Value() const {
35 return false;
36}
37
38bool CYTrue::Value() const {
39 return true;
40}
41
d35a3b07
JF
42#define CYPA 16
43
b09da87b
JF
44void CYAddressOf::Output(std::ostream &out, CYFlags flags) const {
45 rhs_->Output(out, 1, CYLeft(flags));
d35a3b07 46 out << ".$()";
5999c315
JF
47}
48
d35a3b07
JF
49void CYArgument::Output(std::ostream &out) const {
50 if (name_ != NULL) {
5999c315
JF
51 out << *name_;
52 if (value_ != NULL)
53 out << ":";
54 }
d35a3b07 55 if (value_ != NULL)
b09da87b 56 value_->Output(out, CYPA, CYNoFlags);
5999c315 57 if (next_ != NULL) {
d35a3b07
JF
58 if (next_->name_ == NULL)
59 out << ',';
60 else
61 out << ' ';
62 next_->Output(out);
5999c315
JF
63 }
64}
65
b09da87b 66void CYArray::Output(std::ostream &out, CYFlags flags) const {
5befe15e
JF
67 out << '[';
68 if (elements_ != NULL)
69 elements_->Output(out);
70 out << ']';
71}
72
b09da87b
JF
73void CYAssignment::Output(std::ostream &out, CYFlags flags) const {
74 lhs_->Output(out, Precedence() - 1, CYLeft(flags));
d35a3b07 75 out << Operator();
b09da87b 76 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
77}
78
b09da87b
JF
79void CYBoolean::Output(std::ostream &out, CYFlags flags) const {
80 if ((flags & CYNoLeader) != 0)
81 out << ' ';
5999c315 82 out << (Value() ? "true" : "false");
b09da87b
JF
83 if ((flags & CYNoTrailer) != 0)
84 out << ' ';
5999c315
JF
85}
86
87void CYBreak::Output(std::ostream &out) const {
88 out << "break";
89 if (label_ != NULL)
90 out << ' ' << *label_;
91 out << ';';
92}
93
b09da87b
JF
94void CYCall::Output(std::ostream &out, CYFlags flags) const {
95 function_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 96 out << '(';
5999c315 97 if (arguments_ != NULL)
d35a3b07 98 arguments_->Output(out);
5999c315
JF
99 out << ')';
100}
101
102void CYCatch::Output(std::ostream &out) const {
103 out << "catch(" << *name_ << ')';
104 code_->Output(out, true);
105}
106
b09da87b
JF
107void CYClass::Output(std::ostream &out) const {
108 out << "(function($cys,$cyc,$cym,$cyn,$cyt){";
109 out << "$cyc=objc_allocateClassPair($cys,\"" << *name_ << "\",0);";
110 out << "$cym=object_getClass($cyc);";
111 if (fields_ != NULL)
112 fields_->Output(out);
113 if (messages_ != NULL)
114 messages_->Output(out);
115 out << "objc_registerClassPair($cyc);";
116 out << "})(";
117 if (super_ != NULL)
118 super_->Output(out, CYPA, CYNoFlags);
119 else
120 out << "null";
121 out << ");";
122}
123
124void CYCondition::Output(std::ostream &out, CYFlags flags) const {
125 test_->Output(out, Precedence() - 1, CYLeft(flags));
d35a3b07 126 out << '?';
5999c315 127 if (true_ != NULL)
b09da87b 128 true_->Output(out, CYPA, CYNoFlags);
d35a3b07 129 out << ':';
b09da87b 130 false_->Output(out, CYPA, CYRight(flags));
5999c315
JF
131}
132
133void CYContinue::Output(std::ostream &out) const {
134 out << "continue";
135 if (label_ != NULL)
136 out << ' ' << *label_;
137 out << ';';
138}
139
140void CYClause::Output(std::ostream &out) const {
d35a3b07
JF
141 if (case_ != NULL) {
142 out << "case";
b09da87b 143 case_->Output(out, CYNoFlags);
d35a3b07 144 } else
5999c315
JF
145 out << "default";
146 out << ':';
147 if (code_ != NULL)
148 code_->Output(out, false);
149 out << *next_;
150}
151
b09da87b 152// XXX: deal with NoIn
5999c315
JF
153void CYDeclaration::Part(std::ostream &out) const {
154 out << "var ";
155 Output(out);
156}
157
158void CYDeclaration::Output(std::ostream &out) const {
159 out << *identifier_;
d35a3b07
JF
160 if (initialiser_ != NULL) {
161 out << '=';
b09da87b 162 initialiser_->Output(out, CYPA, CYNoFlags);
d35a3b07 163 }
5999c315
JF
164}
165
b09da87b 166// XXX: deal with NoIn
5999c315
JF
167void CYDeclarations::Part(std::ostream &out) const {
168 out << "var ";
d35a3b07 169
5999c315 170 const CYDeclarations *declaration(this);
d35a3b07
JF
171 output:
172 out << *declaration->declaration_;
173 declaration = declaration->next_;
174
175 if (declaration != NULL) {
176 out << ',';
177 goto output;
178 }
5999c315
JF
179}
180
181void CYDeclarations::Output(std::ostream &out) const {
182 Part(out);
183 out << ';';
184}
185
186void CYDoWhile::Output(std::ostream &out) const {
b09da87b 187 // XXX: extra space character!
5999c315
JF
188 out << "do ";
189 code_->Output(out, false);
d35a3b07 190 out << "while(";
b09da87b
JF
191 test_->Output(out, CYNoFlags);
192 out << ')';
5999c315
JF
193}
194
5befe15e 195void CYElement::Output(std::ostream &out) const {
5999c315 196 if (value_ != NULL)
b09da87b 197 value_->Output(out, CYPA, CYNoFlags);
5befe15e 198 if (next_ != NULL || value_ == NULL)
5999c315 199 out << ',';
5befe15e
JF
200 if (next_ != NULL)
201 next_->Output(out);
5999c315
JF
202}
203
204void CYEmpty::Output(std::ostream &out) const {
205 out << ';';
206}
207
208void CYEmpty::Output(std::ostream &out, bool block) const {
209 if (next_ != NULL)
210 CYSource::Output(out, block);
211 else
212 out << "{}";
213}
214
215void CYExpress::Output(std::ostream &out) const {
b09da87b 216 expression_->Output(out, CYNoFunction | CYNoBrace);
5999c315
JF
217 out << ';';
218}
219
220void CYExpression::Part(std::ostream &out) const {
d35a3b07 221 // XXX: this should handle LeftHandSideExpression
b09da87b 222 Output(out, CYNoIn);
d35a3b07
JF
223}
224
b09da87b 225void CYCompound::Output(std::ostream &out, CYFlags flags) const {
d35a3b07 226 if (CYExpression *expression = expressions_)
478d4ed0 227 if (CYExpression *next = expression->next_) {
b09da87b
JF
228 expression->Output(out, CYLeft(flags));
229 CYFlags center(CYCenter(flags));
230 while (next != NULL) {
478d4ed0 231 expression = next;
b09da87b
JF
232 out << ',';
233 next = expression->next_;
234 CYFlags right(next != NULL ? center : CYRight(flags));
235 expression->Output(out, right);
236 }
478d4ed0
JF
237 } else
238 expression->Output(out, flags);
5999c315
JF
239}
240
b09da87b
JF
241void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const {
242 if (precedence < Precedence()) {
5999c315 243 out << '(';
b09da87b 244 Output(out, CYNoFlags);
5999c315 245 out << ')';
b09da87b
JF
246 } else
247 Output(out, flags);
248}
249
250void CYField::Output(std::ostream &out) const {
251 // XXX: implement!
5999c315
JF
252}
253
254void CYFor::Output(std::ostream &out) const {
255 out << "for(";
256 if (initialiser_ != NULL)
257 initialiser_->Part(out);
258 out << ';';
259 if (test_ != NULL)
b09da87b 260 test_->Output(out, CYNoFlags);
5999c315
JF
261 out << ';';
262 if (increment_ != NULL)
b09da87b 263 increment_->Output(out, CYNoFlags);
5999c315
JF
264 out << ')';
265 code_->Output(out, false);
266}
267
268void CYForIn::Output(std::ostream &out) const {
269 out << "for(";
270 initialiser_->Part(out);
b09da87b
JF
271 // XXX: deal with this space character!
272 out << ' ';
273 out << "in";
274 set_->Output(out, CYNoLeader);
5999c315
JF
275 out << ')';
276 code_->Output(out, false);
277}
278
279void CYFunction::Output(std::ostream &out) const {
b09da87b
JF
280 CYLambda::Output(out, CYNoFlags);
281}
282
283void CYFunctionParameter::Output(std::ostream &out) const {
284 out << *name_;
285 if (next_ != NULL) {
286 out << ',';
287 out << *next_;
288 }
5999c315
JF
289}
290
291void CYIf::Output(std::ostream &out) const {
d35a3b07 292 out << "if(";
b09da87b 293 test_->Output(out, CYNoFlags);
d35a3b07 294 out << ')';
5999c315
JF
295 true_->Output(out, true);
296 if (false_ != NULL) {
297 out << "else ";
298 false_->Output(out, false);
299 }
300}
301
b09da87b
JF
302void CYIndirect::Output(std::ostream &out, CYFlags flags) const {
303 rhs_->Output(out, 1, CYLeft(flags));
d35a3b07 304 out << "[0]";
5999c315
JF
305}
306
b09da87b
JF
307void CYInfix::Output(std::ostream &out, CYFlags flags) const {
308 const char *name(Operator());
309 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in"));
310 if (protect)
311 out << '(';
312 bool alphabetic(Alphabetic());
313 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
314 if (alphabetic)
315 left |= CYNoTrailer;
316 lhs_->Output(out, Precedence(), left);
317 out << name;
318 CYFlags right(protect ? CYNoFlags : CYRight(flags));
319 if (alphabetic)
320 right |= CYNoLeader;
321 rhs_->Output(out, Precedence() - 1, right);
322 if (protect)
323 out << ')';
5999c315
JF
324}
325
b09da87b
JF
326void CYLambda::Output(std::ostream &out, CYFlags flags) const {
327 bool protect((flags & CYNoFunction) != 0);
328 if (protect)
329 out << '(';
5999c315
JF
330 out << "function";
331 if (name_ != NULL)
332 out << ' ' << *name_;
333 out << '(';
334 if (parameters_ != NULL)
335 out << *parameters_;
b09da87b
JF
336 out << "){";
337 if (body_ != NULL)
338 body_->Show(out);
339 out << '}';
340 if (protect)
341 out << ')';
5999c315
JF
342}
343
b09da87b
JF
344void CYMember::Output(std::ostream &out, CYFlags flags) const {
345 object_->Output(out, Precedence(), CYLeft(flags));
dea834b0
JF
346 if (const char *word = property_->Word())
347 out << '.' << word;
348 else {
349 out << '[';
b09da87b 350 property_->Output(out, CYNoFlags);
dea834b0
JF
351 out << ']';
352 }
5999c315
JF
353}
354
355void CYMessage::Output(std::ostream &out) const {
4e8c99fb
JF
356 if (next_ != NULL)
357 next_->Output(out);
b09da87b
JF
358 out << "$cyn=new Selector(\"";
359 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
360 if (parameter->tag_ != NULL) {
361 out << *parameter->tag_;
362 if (parameter->name_ != NULL)
5999c315
JF
363 out << ':';
364 }
b09da87b
JF
365 out << "\");";
366 out << "$cyt=$cyn.type($cys," << (instance_ ? "true" : "false") << ");";
367 out << "class_addMethod($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
478d4ed0 368 out << "new Functor(function(self,_cmd";
b09da87b 369 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
478d4ed0
JF
370 if (parameter->name_ != NULL)
371 out << ',' << *parameter->name_;
372 out << "){return function(){";
b09da87b
JF
373 if (body_ != NULL)
374 body_->Show(out);
478d4ed0 375 out << "}.call(self);},$cyt),$cyt);";
5999c315
JF
376}
377
b09da87b 378void CYNew::Output(std::ostream &out, CYFlags flags) const {
d35a3b07 379 out << "new";
b09da87b 380 constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader);
d35a3b07 381 out << '(';
5999c315 382 if (arguments_ != NULL)
d35a3b07 383 arguments_->Output(out);
5999c315
JF
384 out << ')';
385}
386
b09da87b
JF
387void CYNull::Output(std::ostream &out, CYFlags flags) const {
388 if ((flags & CYNoLeader) != 0)
389 out << ' ';
5999c315 390 CYWord::Output(out);
b09da87b
JF
391 if ((flags & CYNoTrailer) != 0)
392 out << ' ';
5999c315
JF
393}
394
b09da87b
JF
395void CYNumber::Output(std::ostream &out, CYFlags flags) const {
396 if ((flags & CYNoLeader) != 0)
397 out << ' ';
5999c315
JF
398 // XXX: this is not a useful formatting
399 out << Value();
b09da87b
JF
400 if ((flags & CYNoTrailer) != 0)
401 out << ' ';
5999c315
JF
402}
403
b09da87b
JF
404void CYObject::Output(std::ostream &out, CYFlags flags) const {
405 bool protect((flags & CYNoBrace) != 0);
406 if (protect)
407 out << '(';
693d501b
JF
408 out << '{';
409 if (property_ != NULL)
410 property_->Output(out);
411 out << '}';
b09da87b
JF
412 if (protect)
413 out << ')';
693d501b
JF
414}
415
b09da87b
JF
416void CYPostfix::Output(std::ostream &out, CYFlags flags) const {
417 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 418 out << Operator();
5999c315
JF
419}
420
b09da87b
JF
421void CYPrefix::Output(std::ostream &out, CYFlags flags) const {
422 bool alphabetic(Alphabetic());
d35a3b07 423 out << Operator();
b09da87b
JF
424 CYFlags right(CYRight(flags));
425 if (alphabetic)
426 right |= CYNoLeader;
427 rhs_->Output(out, Precedence(), right);
5999c315
JF
428}
429
693d501b 430void CYProperty::Output(std::ostream &out) const {
579ed526
JF
431 out << *name_;
432 out << ':';
b09da87b 433 value_->Output(out, CYPA, CYNoFlags);
5999c315
JF
434 if (next_ != NULL) {
435 out << ',';
693d501b 436 next_->Output(out);
5999c315 437 }
5999c315
JF
438}
439
440void CYReturn::Output(std::ostream &out) const {
441 out << "return";
b09da87b
JF
442 if (value_ != NULL)
443 value_->Output(out, CYNoLeader);
5999c315
JF
444 out << ';';
445}
446
b09da87b
JF
447void CYSelector::Output(std::ostream &out, CYFlags flags) const {
448 out << "new Selector(\"";
62014ea9
JF
449 if (name_ != NULL)
450 name_->Output(out);
dea834b0 451 out << "\")";
e7ed5354
JF
452}
453
62014ea9
JF
454void CYSelectorPart::Output(std::ostream &out) const {
455 if (name_ != NULL)
456 out << *name_;
457 if (value_)
458 out << ':';
459 if (next_ != NULL)
460 next_->Output(out);
461}
462
b09da87b
JF
463void CYSend::Output(std::ostream &out, CYFlags flags) const {
464 out << "objc_msgSend(";
465 self_->Output(out, CYPA, CYNoFlags);
466 out << ",\"";
467 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
468 if (argument->name_ != NULL) {
469 out << *argument->name_;
470 if (argument->value_ != NULL)
471 out << ':';
472 }
473 out << "\"";
474 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
475 if (argument->value_ != NULL) {
476 out << ",";
477 argument->value_->Output(out, CYPA, CYNoFlags);
478 }
479 out << ')';
480}
481
b1ff2d78 482void CYSource::Show(std::ostream &out) const {
5999c315 483 for (const CYSource *next(this); next != NULL; next = next->next_)
b09da87b 484 next->Output(out);
5999c315
JF
485}
486
487void CYSource::Output(std::ostream &out, bool block) const {
488 if (!block && next_ == NULL)
489 Output(out);
490 else {
491 out << '{';
b1ff2d78 492 Show(out);
5999c315
JF
493 out << '}';
494 }
495}
496
b09da87b 497void CYString::Output(std::ostream &out, CYFlags flags) const {
5999c315
JF
498 out << '\"';
499 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
500 switch (*value) {
501 case '"': out << "\\\""; break;
502 case '\\': out << "\\\\"; break;
503 case '\b': out << "\\b"; break;
504 case '\f': out << "\\f"; break;
505 case '\n': out << "\\n"; break;
506 case '\r': out << "\\r"; break;
507 case '\t': out << "\\t"; break;
508 case '\v': out << "\\v"; break;
509
510 default:
511 if (*value < 0x20 || *value >= 0x7f)
512 out << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
513 else
514 out << *value;
515 }
516 out << '\"';
517}
518
519void CYSwitch::Output(std::ostream &out) const {
d35a3b07 520 out << "switch(";
b09da87b 521 value_->Output(out, CYNoFlags);
d35a3b07 522 out << "){";
5999c315
JF
523 if (clauses_ != NULL)
524 out << *clauses_;
525 out << '}';
526}
527
b09da87b
JF
528void CYThis::Output(std::ostream &out, CYFlags flags) const {
529 if ((flags & CYNoLeader) != 0)
530 out << ' ';
5999c315 531 CYWord::Output(out);
b09da87b
JF
532 if ((flags & CYNoTrailer) != 0)
533 out << ' ';
5999c315
JF
534}
535
536void CYThrow::Output(std::ostream &out) const {
d35a3b07 537 out << "throw";
b09da87b
JF
538 if (value_ != NULL)
539 value_->Output(out, CYNoLeader);
5999c315
JF
540 out << ';';
541}
542
543void CYTry::Output(std::ostream &out) const {
544 out << "try";
545 try_->Output(out, true);
546 if (catch_ != NULL)
547 out << catch_;
548 if (finally_ != NULL) {
549 out << "finally";
550 finally_->Output(out, true);
551 }
552}
553
b09da87b 554void CYVariable::Output(std::ostream &out, CYFlags flags) const {
478d4ed0
JF
555 if ((flags & CYNoLeader) != 0)
556 out << ' ';
5999c315 557 out << *name_;
478d4ed0
JF
558 if ((flags & CYNoTrailer) != 0)
559 out << ' ';
5999c315
JF
560}
561
562void CYWhile::Output(std::ostream &out) const {
d35a3b07 563 out << "while(";
b09da87b 564 test_->Output(out, CYNoFlags);
d35a3b07 565 out << ')';
5999c315
JF
566 code_->Output(out, false);
567}
568
569void CYWith::Output(std::ostream &out) const {
d35a3b07 570 out << "with(";
b09da87b 571 scope_->Output(out, CYNoFlags);
d35a3b07 572 out << ')';
5999c315
JF
573 code_->Output(out, false);
574}
575
576void CYWord::Output(std::ostream &out) const {
577 out << Value();
578}