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