]>
git.saurik.com Git - cycript.git/blob - Output.cpp
09ee163a739f138b964081d9a9d0aab5e4afdefd
6 #include <objc/runtime.h>
9 _finline CYFlags
operator ~(CYFlags rhs
) {
10 return static_cast<CYFlags
>(~static_cast<unsigned>(rhs
));
13 _finline CYFlags
operator &(CYFlags lhs
, CYFlags rhs
) {
14 return static_cast<CYFlags
>(static_cast<unsigned>(lhs
) & static_cast<unsigned>(rhs
));
17 _finline CYFlags
operator |(CYFlags lhs
, CYFlags rhs
) {
18 return static_cast<CYFlags
>(static_cast<unsigned>(lhs
) | static_cast<unsigned>(rhs
));
21 _finline CYFlags
&operator |=(CYFlags
&lhs
, CYFlags rhs
) {
22 return lhs
= lhs
| rhs
;
25 _finline CYFlags
CYLeft(CYFlags flags
) {
26 return flags
& ~CYNoTrailer
;
29 _finline CYFlags
CYCenter(CYFlags flags
) {
30 return flags
& CYNoIn
;
33 _finline CYFlags
CYRight(CYFlags flags
) {
34 return flags
& (CYNoIn
| CYNoTrailer
);
37 bool CYFalse::Value() const {
41 bool CYTrue::Value() const {
47 void CYAddressOf::Output(CYOutput
&out
, CYFlags flags
) const {
48 rhs_
->Output(out
, 1, CYLeft(flags
));
52 void CYArgument::Output(CYOutput
&out
) const {
59 value_
->Output(out
, CYPA
, CYNoFlags
);
61 if (next_
->name_
== NULL
)
69 void CYArray::Output(CYOutput
&out
, CYFlags flags
) const {
71 if (elements_
!= NULL
)
72 elements_
->Output(out
);
76 void CYArrayComprehension::Output(CYOutput
&out
, CYFlags flags
) const {
77 // XXX: I don't necc. need the ()s
78 out
<< "(function($cyv";
79 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
80 if (const char *name
= comprehension
->Name())
84 comprehensions_
->Output(out
);
86 expression_
->Output(out
, CYPA
, CYNoFlags
);
88 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
89 comprehension
->End_(out
);
90 out
<< "return $cyv;";
94 void CYAssignment::Output(CYOutput
&out
, CYFlags flags
) const {
95 lhs_
->Output(out
, Precedence() - 1, CYLeft(flags
));
97 rhs_
->Output(out
, Precedence(), CYRight(flags
));
100 void CYBlock::Output(CYOutput
&out
) const {
101 for (CYStatement
*statement(statements_
); statement
!= NULL
; statement
= statement
->next_
)
102 statement
->Output(out
);
105 void CYBoolean::Output(CYOutput
&out
, CYFlags flags
) const {
106 if ((flags
& CYNoLeader
) != 0)
108 out
<< (Value() ? "true" : "false");
109 if ((flags
& CYNoTrailer
) != 0)
113 void CYBreak::Output(CYOutput
&out
) const {
116 out
<< ' ' << *label_
;
120 void CYCall::Output(CYOutput
&out
, CYFlags flags
) const {
121 function_
->Output(out
, Precedence(), CYLeft(flags
));
123 if (arguments_
!= NULL
)
124 arguments_
->Output(out
);
128 void CYCatch::Output(CYOutput
&out
) const {
129 out
<< "catch(" << *name_
<< "){";
135 void CYCategory::Output(CYOutput
&out
) const {
136 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt){";
137 out
<< "$cyp=object_getClass($cys);";
139 if (messages_
!= NULL
)
140 messages_
->Output(out
, true);
142 name_
->ClassName(out
, true);
146 void CYClass::Output(CYOutput
&out
) const {
151 void CYClass::Output(CYOutput
&out
, CYFlags flags
) const {
152 // XXX: I don't necc. need the ()s
153 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
154 out
<< "$cyp=object_getClass($cys);";
155 out
<< "$cyc=objc_allocateClassPair($cys,";
157 name_
->ClassName(out
, false);
159 out
<< "$cyq(\"CY$\")";
161 out
<< "$cym=object_getClass($cyc);";
163 fields_
->Output(out
);
164 if (messages_
!= NULL
)
165 messages_
->Output(out
, false);
166 out
<< "objc_registerClassPair($cyc);";
167 out
<< "return $cyc;";
170 super_
->Output(out
, CYPA
, CYNoFlags
);
176 void CYCompound::Output(CYOutput
&out
, CYFlags flags
) const {
177 if (CYExpression
*expression
= expressions_
)
178 if (CYExpression
*next
= expression
->next_
) {
179 expression
->Output(out
, CYLeft(flags
));
180 CYFlags
center(CYCenter(flags
));
181 while (next
!= NULL
) {
184 next
= expression
->next_
;
185 CYFlags
right(next
!= NULL
? center
: CYRight(flags
));
186 expression
->Output(out
, right
);
189 expression
->Output(out
, flags
);
192 void CYComprehension::Output(CYOutput
&out
) const {
198 void CYCondition::Output(CYOutput
&out
, CYFlags flags
) const {
199 test_
->Output(out
, Precedence() - 1, CYLeft(flags
));
202 true_
->Output(out
, CYPA
, CYNoFlags
);
204 false_
->Output(out
, CYPA
, CYRight(flags
));
207 void CYContinue::Output(CYOutput
&out
) const {
210 out
<< ' ' << *label_
;
214 void CYClause::Output(CYOutput
&out
) const {
217 case_
->Output(out
, CYNoLeader
);
222 code_
->Output(out
, false);
227 const char *CYDeclaration::ForEachIn() const {
228 return identifier_
->Value();
231 void CYDeclaration::ForIn(CYOutput
&out
, CYFlags flags
) const {
232 if ((flags
& CYNoLeader
) != 0)
235 Output(out
, CYRight(flags
));
238 void CYDeclaration::ForEachIn(CYOutput
&out
) const {
242 void CYDeclaration::Output(CYOutput
&out
, CYFlags flags
) const {
244 if (initialiser_
!= NULL
) {
246 initialiser_
->Output(out
, CYPA
, CYRight(flags
));
247 } else if ((flags
& CYNoTrailer
) != 0)
251 void CYDeclarations::For(CYOutput
&out
) const {
256 void CYDeclarations::Output(CYOutput
&out
, CYFlags flags
) const {
257 const CYDeclarations
*declaration(this);
259 CYDeclarations
*next(declaration
->next_
);
260 CYFlags
right(next
== NULL
? CYRight(flags
) : CYCenter(flags
));
261 declaration
->declaration_
->Output(out
, right
);
270 void CYDirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
271 object_
->Output(out
, Precedence(), CYLeft(flags
));
272 if (const char *word
= property_
->Word())
276 property_
->Output(out
, CYNoFlags
);
281 void CYDoWhile::Output(CYOutput
&out
) const {
282 // XXX: extra space character!
284 code_
->Output(out
, false);
286 test_
->Output(out
, CYNoFlags
);
290 void CYElement::Output(CYOutput
&out
) const {
292 value_
->Output(out
, CYPA
, CYNoFlags
);
293 if (next_
!= NULL
|| value_
== NULL
)
299 void CYEmpty::Output(CYOutput
&out
) const {
303 void CYEmpty::Output(CYOutput
&out
, bool block
) const {
305 CYStatement::Output(out
, block
);
310 void CYExpress::Output(CYOutput
&out
) const {
311 expression_
->Output(out
, CYNoBF
);
315 void CYExpression::ClassName(CYOutput
&out
, bool object
) const {
316 Output(out
, CYPA
, CYNoFlags
);
319 const char *CYExpression::ForEachIn() const {
323 void CYExpression::For(CYOutput
&out
) const {
327 void CYExpression::ForEachIn(CYOutput
&out
) const {
328 // XXX: this should handle LeftHandSideExpression
329 Output(out
, CYPA
, CYNoFlags
);
332 void CYExpression::ForIn(CYOutput
&out
, CYFlags flags
) const {
333 // XXX: this should handle LeftHandSideExpression
337 void CYExpression::Output(CYOutput
&out
, unsigned precedence
, CYFlags flags
) const {
338 if (precedence
< Precedence()) {
340 Output(out
, CYNoFlags
);
346 void CYField::Output(CYOutput
&out
) const {
350 void CYFinally::Output(CYOutput
&out
) const {
357 void CYFor::Output(CYOutput
&out
) const {
359 if (initialiser_
!= NULL
)
360 initialiser_
->For(out
);
363 test_
->Output(out
, CYNoFlags
);
365 if (increment_
!= NULL
)
366 increment_
->Output(out
, CYNoFlags
);
368 code_
->Output(out
, false);
371 void CYForEachIn::Output(CYOutput
&out
) const {
372 out
<< "with({$cys:0,$cyt:0}){";
375 set_
->Output(out
, CYPA
, CYNoFlags
);
378 out
<< "for($cyt in $cys){";
380 initialiser_
->ForEachIn(out
);
381 out
<< "=$cys[$cyt];";
390 void CYForEachInComprehension::Begin_(CYOutput
&out
) const {
391 out
<< "(function($cys){";
393 set_
->Output(out
, CYPA
, CYNoFlags
);
396 out
<< "for(" << *name_
<< " in $cys){";
397 out
<< *name_
<< "=$cys[" << *name_
<< "];";
400 void CYForEachInComprehension::End_(CYOutput
&out
) const {
404 void CYForIn::Output(CYOutput
&out
) const {
406 initialiser_
->ForIn(out
, CYNoIn
| CYNoTrailer
);
408 set_
->Output(out
, CYNoLeader
);
410 code_
->Output(out
, false);
413 void CYForInComprehension::Begin_(CYOutput
&out
) const {
414 out
<< "for(" << *name_
<< " in";
415 set_
->Output(out
, CYNoLeader
);
419 void CYFunction::Output(CYOutput
&out
) const {
420 CYLambda::Output(out
, CYNoFlags
);
423 void CYFunctionParameter::Output(CYOutput
&out
) const {
431 void CYIf::Output(CYOutput
&out
) const {
433 test_
->Output(out
, CYNoFlags
);
435 true_
->Output(out
, true);
436 if (false_
!= NULL
) {
438 false_
->Output(out
, false);
442 void CYIfComprehension::Begin_(CYOutput
&out
) const {
444 test_
->Output(out
, CYNoFlags
);
448 void CYIndirect::Output(CYOutput
&out
, CYFlags flags
) const {
449 rhs_
->Output(out
, 1, CYLeft(flags
));
453 void CYIndirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
454 object_
->Output(out
, Precedence(), CYLeft(flags
));
456 if (const char *word
= property_
->Word())
460 property_
->Output(out
, CYNoFlags
);
465 void CYInfix::Output(CYOutput
&out
, CYFlags flags
) const {
466 const char *name(Operator());
467 bool protect((flags
& CYNoIn
) != 0 && strcmp(name
, "in"));
470 bool alphabetic(Alphabetic());
471 CYFlags
left(protect
? CYNoFlags
: CYLeft(flags
));
474 lhs_
->Output(out
, Precedence(), left
);
476 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
479 if (strcmp(name
, "-") == 0)
481 rhs_
->Output(out
, Precedence() - 1, right
);
486 void CYLambda::Output(CYOutput
&out
, CYFlags flags
) const {
487 bool protect((flags
& CYNoFunction
) != 0);
490 else if ((flags
& CYNoLeader
) != 0)
494 out
<< ' ' << *name_
;
496 if (parameters_
!= NULL
)
506 void CYLet::Output(CYOutput
&out
) const {
508 declarations_
->Output(out
, CYNoFlags
);
510 if (statements_
!= NULL
)
511 statements_
->Show(out
);
515 void CYMessage::Output(CYOutput
&out
, bool replace
) const {
517 next_
->Output(out
, replace
);
518 out
<< "$cyn=new Selector(\"";
519 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
520 if (parameter
->tag_
!= NULL
) {
521 out
<< *parameter
->tag_
;
522 if (parameter
->name_
!= NULL
)
526 out
<< "$cyt=$cyn.type($cy" << (instance_
? 's' : 'p') << ");";
527 out
<< "class_" << (replace
? "replace" : "add") << "Method($cy" << (instance_
? 'c' : 'm') << ",$cyn,";
528 out
<< "new Functor(function(self,_cmd";
529 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
530 if (parameter
->name_
!= NULL
)
531 out
<< ',' << *parameter
->name_
;
532 out
<< "){return function(){";
535 out
<< "}.call(self);},$cyt),$cyt);";
538 void CYNew::Output(CYOutput
&out
, CYFlags flags
) const {
539 if ((flags
& CYNoLeader
) != 0)
542 constructor_
->Output(out
, Precedence(), CYCenter(flags
) | CYNoLeader
);
544 if (arguments_
!= NULL
)
545 arguments_
->Output(out
);
549 void CYNull::Output(CYOutput
&out
, CYFlags flags
) const {
550 if ((flags
& CYNoLeader
) != 0)
553 if ((flags
& CYNoTrailer
) != 0)
557 void CYNumber::Output(CYOutput
&out
, CYFlags flags
) const {
558 double value(Value());
559 if ((flags
& CYNoLeader
) != 0 || value
< 0 && (flags
& CYNoHyphen
) != 0)
561 // XXX: decide on correct precision
562 out
.out_
<< std::setprecision(9) << value
;
563 if ((flags
& CYNoTrailer
) != 0)
567 void CYNumber::PropertyName(CYOutput
&out
) const {
571 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
572 bool protect((flags
& CYNoBrace
) != 0);
576 if (property_
!= NULL
)
577 property_
->Output(out
);
583 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
584 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
588 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
589 const char *name(Operator());
590 bool alphabetic(Alphabetic());
591 if (alphabetic
&& (flags
& CYNoLeader
) != 0 || name
[0] == '-' && (flags
& CYNoHyphen
) != 0)
594 CYFlags
right(CYRight(flags
));
597 rhs_
->Output(out
, Precedence(), right
);
600 void CYProperty::Output(CYOutput
&out
) const {
601 name_
->PropertyName(out
);
603 value_
->Output(out
, CYPA
, CYNoFlags
);
610 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
612 if ((flags
& CYNoTrailer
) != 0)
616 void CYReturn::Output(CYOutput
&out
) const {
619 value_
->Output(out
, CYNoLeader
);
623 void CYSelector::Output(CYOutput
&out
, CYFlags flags
) const {
624 if ((flags
& CYNoLeader
) != 0)
626 out
<< "new Selector(\"";
632 void CYSelectorPart::Output(CYOutput
&out
) const {
641 void CYSend::Output(CYOutput
&out
, CYFlags flags
) const {
642 if ((flags
& CYNoLeader
) != 0)
644 out
<< "objc_msgSend(";
645 self_
->Output(out
, CYPA
, CYNoFlags
);
647 std::ostringstream name
;
648 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
649 if (argument
->name_
!= NULL
) {
650 name
<< *argument
->name_
;
651 if (argument
->value_
!= NULL
)
654 out
.out_
<< reinterpret_cast<void *>(sel_registerName(name
.str().c_str()));
655 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
656 if (argument
->value_
!= NULL
) {
658 argument
->value_
->Output(out
, CYPA
, CYNoFlags
);
663 void CYStatement::Show(CYOutput
&out
) const {
664 for (const CYStatement
*next(this); next
!= NULL
; next
= next
->next_
)
668 void CYStatement::Output(CYOutput
&out
, bool block
) const {
669 if (!block
&& !IsBlock())
678 void CYStatement::Output_(CYOutput
&out
) const {
679 for (CYLabel
*label(labels_
); label
!= NULL
; label
= label
->next_
)
680 out
<< *label
->name_
<< ':';
684 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
685 unsigned quot(0), apos(0);
686 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
689 else if (*value
== '\'')
692 bool single(quot
> apos
);
694 out
<< (single
? '\'' : '"');
695 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
697 case '\\': out
<< "\\\\"; break;
698 case '\b': out
<< "\\b"; break;
699 case '\f': out
<< "\\f"; break;
700 case '\n': out
<< "\\n"; break;
701 case '\r': out
<< "\\r"; break;
702 case '\t': out
<< "\\t"; break;
703 case '\v': out
<< "\\v"; break;
718 if (*value
< 0x20 || *value
>= 0x7f)
719 out
.out_
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value
);
723 out
<< (single
? '\'' : '"');
726 void CYString::PropertyName(CYOutput
&out
) const {
727 if (const char *word
= Word())
733 void CYSwitch::Output(CYOutput
&out
) const {
735 value_
->Output(out
, CYNoFlags
);
737 if (clauses_
!= NULL
)
742 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
743 if ((flags
& CYNoLeader
) != 0)
746 if ((flags
& CYNoTrailer
) != 0)
750 void CYThrow::Output(CYOutput
&out
) const {
753 value_
->Output(out
, CYNoLeader
);
757 void CYTry::Output(CYOutput
&out
) const {
764 if (finally_
!= NULL
)
765 finally_
->Output(out
);
768 void CYVar::Output(CYOutput
&out
) const {
770 declarations_
->Output(out
, CYNoFlags
);
774 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
775 if ((flags
& CYNoLeader
) != 0)
778 if ((flags
& CYNoTrailer
) != 0)
782 void CYWhile::Output(CYOutput
&out
) const {
784 test_
->Output(out
, CYNoFlags
);
786 code_
->Output(out
, false);
789 void CYWith::Output(CYOutput
&out
) const {
791 scope_
->Output(out
, CYNoFlags
);
793 code_
->Output(out
, false);
796 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
798 out
<< "objc_getClass(";
799 out
<< '"' << Value() << '"';
804 void CYWord::Output(CYOutput
&out
) const {
808 void CYWord::PropertyName(CYOutput
&out
) const {