]>
git.saurik.com Git - cycript.git/blob - Output.cpp
f648a575d35a55fea68369205210a189b20921d7
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
) {
29 _finline CYFlags
CYRight(CYFlags flags
) {
30 return flags
& ~CYNoBF
;
33 _finline CYFlags
CYCenter(CYFlags flags
) {
34 return CYRight(flags
);
39 void CYOutput::Terminate() {
44 CYOutput
&CYOutput::operator <<(char rhs
) {
45 if (rhs
== ' ' || rhs
== '\n')
51 for (unsigned i(0); i
!= indent_
; ++i
)
60 if (mode_
== Terminated
&& rhs
!= '}')
70 } else if (rhs
== '-') {
71 if (mode_
== NoHyphen
)
74 } else if (WordEndRange_
[rhs
]) {
75 if (mode_
== NoLetter
)
86 CYOutput
&CYOutput::operator <<(const char *rhs
) {
87 size_t size(strlen(rhs
));
92 if (mode_
== Terminated
)
95 mode_
== NoHyphen
&& *rhs
== '-' ||
96 mode_
== NoLetter
&& WordEndRange_
[*rhs
]
100 if (WordEndRange_
[rhs
[size
- 1]])
109 void OutputBody(CYOutput
&out
, CYStatement
*body
) {
110 out
<< ' ' << '{' << '\n';
118 void CYAddressOf::Output(CYOutput
&out
, CYFlags flags
) const {
119 rhs_
->Output(out
, 1, CYLeft(flags
));
123 void CYArgument::Output(CYOutput
&out
) const {
130 value_
->Output(out
, CYPA
, CYNoFlags
);
132 if (next_
->name_
== NULL
)
134 out
<< ' ' << *next_
;
138 void CYArray::Output(CYOutput
&out
, CYFlags flags
) const {
139 out
<< '[' << elements_
<< ']';
142 void CYArrayComprehension::Output(CYOutput
&out
, CYFlags flags
) const {
143 // XXX: I don't necc. need the ()s
144 out
<< "(function($cyv";
145 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
146 if (const char *name
= comprehension
->Name())
150 comprehensions_
->Output(out
);
152 expression_
->Output(out
, CYPA
, CYNoFlags
);
154 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
155 comprehension
->End_(out
);
156 out
<< "return $cyv;";
160 void CYAssignment::Output(CYOutput
&out
, CYFlags flags
) const {
161 lhs_
->Output(out
, Precedence() - 1, CYLeft(flags
) | CYNoRightHand
);
162 out
<< ' ' << Operator() << ' ';
163 rhs_
->Output(out
, Precedence(), CYRight(flags
));
166 void CYBlock::Output(CYOutput
&out
, CYFlags flags
) const {
167 statements_
->Single(out
, flags
);
170 void CYBoolean::Output(CYOutput
&out
, CYFlags flags
) const {
171 out
<< (Value() ? "true" : "false");
174 void CYBreak::Output(CYOutput
&out
, CYFlags flags
) const {
177 out
<< ' ' << *label_
;
181 void CYCall::Output(CYOutput
&out
, CYFlags flags
) const {
182 bool protect((flags
& CYNoCall
) != 0);
185 function_
->Output(out
, Precedence(), protect
? CYNoFlags
: flags
);
186 out
<< '(' << arguments_
<< ')';
191 void CYCatch::Output(CYOutput
&out
) const {
192 out
<< "catch" << ' ' << '(' << *name_
<< ')' << ' ' << '{';
194 code_
->Multiple(out
);
198 void CYCategory::Output(CYOutput
&out
, CYFlags flags
) const {
199 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt){";
200 out
<< "$cyp=object_getClass($cys);";
202 if (messages_
!= NULL
)
203 messages_
->Output(out
, true);
205 name_
->ClassName(out
, true);
210 void CYClass::Output(CYOutput
&out
, CYFlags flags
) const {
211 // XXX: I don't necc. need the ()s
212 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
213 out
<< "$cyp=object_getClass($cys);";
214 out
<< "$cyc=objc_allocateClassPair($cys,";
216 name_
->ClassName(out
, false);
218 out
<< "$cyq(\"CY$\")";
220 out
<< "$cym=object_getClass($cyc);";
222 fields_
->Output(out
);
223 if (messages_
!= NULL
)
224 messages_
->Output(out
, false);
225 out
<< "objc_registerClassPair($cyc);";
226 out
<< "return $cyc;";
229 super_
->Output(out
, CYPA
, CYNoFlags
);
235 void CYClassExpression::Output(CYOutput
&out
, CYFlags flags
) const {
236 CYClass::Output(out
, flags
);
239 void CYClassStatement::Output(CYOutput
&out
, CYFlags flags
) const {
240 CYClass::Output(out
, flags
);
243 void CYCompound::Output(CYOutput
&out
, CYFlags flags
) const {
244 if (CYExpression
*expression
= expressions_
)
245 if (CYExpression
*next
= expression
->next_
) {
246 expression
->Output(out
, CYLeft(flags
));
247 CYFlags
center(CYCenter(flags
));
248 while (next
!= NULL
) {
251 next
= expression
->next_
;
252 CYFlags
right(next
!= NULL
? center
: CYRight(flags
));
253 expression
->Output(out
, right
);
256 expression
->Output(out
, flags
);
259 void CYComprehension::Output(CYOutput
&out
) const {
264 void CYCondition::Output(CYOutput
&out
, CYFlags flags
) const {
265 test_
->Output(out
, Precedence() - 1, CYLeft(flags
));
266 out
<< ' ' << '?' << ' ';
268 true_
->Output(out
, CYPA
, CYNoFlags
);
269 out
<< ' ' << ':' << ' ';
270 false_
->Output(out
, CYPA
, CYRight(flags
));
273 void CYContinue::Output(CYOutput
&out
, CYFlags flags
) const {
276 out
<< ' ' << *label_
;
280 void CYClause::Output(CYOutput
&out
) const {
282 out
<< "case" << ' ' << *case_
;
287 code_
->Multiple(out
, CYNoFlags
);
291 const char *CYDeclaration::ForEachIn() const {
292 return identifier_
->Value();
295 void CYDeclaration::ForIn(CYOutput
&out
, CYFlags flags
) const {
297 Output(out
, CYRight(flags
));
300 void CYDeclaration::ForEachIn(CYOutput
&out
) const {
304 void CYDeclaration::Output(CYOutput
&out
, CYFlags flags
) const {
306 if (initialiser_
!= NULL
) {
307 out
<< ' ' << '=' << ' ';
308 initialiser_
->Output(out
, CYPA
, CYRight(flags
));
312 void CYDeclarations::For(CYOutput
&out
) const {
317 void CYDeclarations::Output(CYOutput
&out
) const {
318 Output(out
, CYNoFlags
);
321 void CYDeclarations::Output(CYOutput
&out
, CYFlags flags
) const {
322 const CYDeclarations
*declaration(this);
325 CYDeclarations
*next(declaration
->next_
);
326 CYFlags
jacks(first
? CYLeft(flags
) : next
== NULL
? CYRight(flags
) : CYCenter(flags
));
328 declaration
->declaration_
->Output(out
, jacks
);
337 void CYDirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
338 object_
->Output(out
, Precedence(), CYLeft(flags
));
339 if (const char *word
= property_
->Word())
342 out
<< '[' << *property_
<< ']';
345 void CYDoWhile::Output(CYOutput
&out
, CYFlags flags
) const {
347 code_
->Single(out
, CYNoFlags
);
348 out
<< "while" << ' ' << '(' << *test_
<< ')';
351 void CYElement::Output(CYOutput
&out
) const {
353 value_
->Output(out
, CYPA
, CYNoFlags
);
354 if (next_
!= NULL
|| value_
== NULL
) {
356 if (next_
!= NULL
&& next_
->value_
!= NULL
)
363 void CYEmpty::Output(CYOutput
&out
, CYFlags flags
) const {
367 void CYExpress::Output(CYOutput
&out
, CYFlags flags
) const {
368 expression_
->Output(out
, flags
| CYNoBF
);
372 void CYExpression::ClassName(CYOutput
&out
, bool object
) const {
373 Output(out
, CYPA
, CYNoFlags
);
376 const char *CYExpression::ForEachIn() const {
380 void CYExpression::For(CYOutput
&out
) const {
384 void CYExpression::ForEachIn(CYOutput
&out
) const {
385 Output(out
, CYPA
, CYNoRightHand
);
388 void CYExpression::ForIn(CYOutput
&out
, CYFlags flags
) const {
389 Output(out
, flags
| CYNoRightHand
);
392 void CYExpression::Output(CYOutput
&out
) const {
393 Output(out
, CYNoFlags
);
396 void CYExpression::Output(CYOutput
&out
, unsigned precedence
, CYFlags flags
) const {
397 if (precedence
< Precedence() || (flags
& CYNoRightHand
) != 0 && RightHand())
398 out
<< '(' << *this << ')';
403 void CYField::Output(CYOutput
&out
) const {
407 void CYFinally::Output(CYOutput
&out
) const {
408 out
<< "finally" << ' ' << '{';
410 code_
->Multiple(out
);
414 void CYFor::Output(CYOutput
&out
, CYFlags flags
) const {
415 out
<< "for" << ' ' << '(';
416 if (initialiser_
!= NULL
)
417 initialiser_
->For(out
);
423 code_
->Single(out
, CYNoFlags
);
426 void CYForEachIn::Output(CYOutput
&out
, CYFlags flags
) const {
427 out
<< "with({$cys:0,$cyt:0}){";
430 set_
->Output(out
, CYPA
, CYNoFlags
);
433 out
<< "for($cyt in $cys){";
435 initialiser_
->ForEachIn(out
);
436 out
<< "=$cys[$cyt];";
438 code_
->Multiple(out
);
445 void CYForEachInComprehension::Begin_(CYOutput
&out
) const {
446 out
<< "(function($cys){";
448 set_
->Output(out
, CYPA
, CYNoFlags
);
451 out
<< "for(" << *name_
<< " in $cys){";
452 out
<< *name_
<< "=$cys[" << *name_
<< "];";
455 void CYForEachInComprehension::End_(CYOutput
&out
) const {
459 void CYForIn::Output(CYOutput
&out
, CYFlags flags
) const {
460 out
<< "for" << ' ' << '(';
461 initialiser_
->ForIn(out
, CYNoIn
);
462 out
<< "in" << *set_
<< ')';
463 code_
->Single(out
, CYRight(flags
));
466 void CYForInComprehension::Begin_(CYOutput
&out
) const {
467 out
<< "for" << ' ' << '(' << *name_
<< "in" << *set_
<< ')';
470 void CYFunction::Output(CYOutput
&out
, CYFlags flags
) const {
471 // XXX: one could imagine using + here to save a byte
472 bool protect((flags
& CYNoFunction
) != 0);
477 out
<< ' ' << *name_
;
478 out
<< '(' << parameters_
<< ')';
479 OutputBody(out
, body_
);
484 void CYFunctionExpression::Output(CYOutput
&out
, CYFlags flags
) const {
485 CYFunction::Output(out
, flags
);
488 void CYFunctionStatement::Output(CYOutput
&out
, CYFlags flags
) const {
489 CYFunction::Output(out
, flags
);
492 void CYFunctionParameter::Output(CYOutput
&out
) const {
495 out
<< ',' << ' ' << *next_
;
498 void CYIf::Output(CYOutput
&out
, CYFlags flags
) const {
500 if (false_
== NULL
&& (flags
& CYNoDangle
) != 0) {
505 out
<< "if" << ' ' << '(' << *test_
<< ')';
507 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
508 CYFlags
jacks(CYNoDangle
);
512 bool single(true_
->Single(out
, jacks
));
514 if (false_
!= NULL
) {
515 out
<< (single
? '\t' : ' ');
517 false_
->Single(out
, right
);
524 void CYIfComprehension::Begin_(CYOutput
&out
) const {
525 out
<< "if" << '(' << *test_
<< ')';
528 void CYIndirect::Output(CYOutput
&out
, CYFlags flags
) const {
529 rhs_
->Output(out
, 1, CYLeft(flags
));
533 void CYIndirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
534 object_
->Output(out
, Precedence(), CYLeft(flags
));
536 if (const char *word
= property_
->Word())
539 out
<< '[' << *property_
<< ']';
542 void CYInfix::Output(CYOutput
&out
, CYFlags flags
) const {
543 const char *name(Operator());
544 bool protect((flags
& CYNoIn
) != 0 && strcmp(name
, "in"));
547 CYFlags
left(protect
? CYNoFlags
: CYLeft(flags
));
548 lhs_
->Output(out
, Precedence(), left
);
549 out
<< ' ' << name
<< ' ';
550 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
551 rhs_
->Output(out
, Precedence() - 1, right
);
556 void CYLet::Output(CYOutput
&out
, CYFlags flags
) const {
557 out
<< "let" << ' ' << '(' << *declarations_
<< ')' << ' ' << '{';
558 if (statements_
!= NULL
)
559 statements_
->Multiple(out
);
563 void CYMessage::Output(CYOutput
&out
, bool replace
) const {
565 next_
->Output(out
, replace
);
566 out
<< "$cyn=new Selector(\"";
567 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
568 if (parameter
->tag_
!= NULL
) {
569 out
<< *parameter
->tag_
;
570 if (parameter
->name_
!= NULL
)
574 out
<< "$cyt=$cyn.type($cy" << (instance_
? 's' : 'p') << ");";
575 out
<< "class_" << (replace
? "replace" : "add") << "Method($cy" << (instance_
? 'c' : 'm') << ",$cyn,";
576 out
<< "new Functor(function(self,_cmd";
577 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
578 if (parameter
->name_
!= NULL
)
579 out
<< ',' << *parameter
->name_
;
580 out
<< "){return function(){";
582 body_
->Multiple(out
);
583 out
<< "}.call(self);},$cyt),$cyt);";
586 void CYNew::Output(CYOutput
&out
, CYFlags flags
) const {
588 CYFlags
jacks(CYNoCall
| CYCenter(flags
));
589 constructor_
->Output(out
, Precedence(), jacks
);
590 if (arguments_
!= NULL
)
591 out
<< '(' << *arguments_
<< ')';
594 void CYNull::Output(CYOutput
&out
, CYFlags flags
) const {
598 void CYNumber::Output(CYOutput
&out
, CYFlags flags
) const {
600 sprintf(value
, "%.17g", Value());
604 void CYNumber::PropertyName(CYOutput
&out
) const {
605 Output(out
, CYNoFlags
);
608 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
609 bool protect((flags
& CYNoBrace
) != 0);
619 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
620 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
624 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
625 const char *name(Operator());
629 rhs_
->Output(out
, Precedence(), CYRight(flags
));
632 void CYProperty::Output(CYOutput
&out
) const {
633 name_
->PropertyName(out
);
635 value_
->Output(out
, CYPA
, CYNoFlags
);
637 out
<< ',' << ' ' << *next_
;
640 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
644 void CYReturn::Output(CYOutput
&out
, CYFlags flags
) const {
645 out
<< "return" << value_
<< ';';
648 void CYSelector::Output(CYOutput
&out
, CYFlags flags
) const {
649 out
<< "new Selector(\"";
655 void CYSelectorPart::Output(CYOutput
&out
) const {
662 void CYSend::Output(CYOutput
&out
, CYFlags flags
) const {
663 out
<< "objc_msgSend(";
664 self_
->Output(out
, CYPA
, CYNoFlags
);
666 std::ostringstream name
;
667 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
668 if (argument
->name_
!= NULL
) {
669 name
<< *argument
->name_
;
670 if (argument
->value_
!= NULL
)
673 out
.out_
<< reinterpret_cast<void *>(sel_registerName(name
.str().c_str()));
674 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
675 if (argument
->value_
!= NULL
) {
677 argument
->value_
->Output(out
, CYPA
, CYNoFlags
);
682 void CYStatement::Multiple(CYOutput
&out
, CYFlags flags
) const {
684 for (const CYStatement
*next(this); next
!= NULL
; next
= next
->next_
) {
685 bool last(next
->next_
== NULL
);
686 CYFlags
jacks(first
? last
? flags
: CYLeft(flags
) : last
? CYCenter(flags
) : CYRight(flags
));
689 next
->Output(out
, jacks
);
694 bool CYStatement::Single(CYOutput
&out
, CYFlags flags
) const {
696 out
<< ' ' << '{' << '\n';
703 for (CYLabel
*label(labels_
); label
!= NULL
; label
= label
->next_
)
704 out
<< ' ' << *label
->name_
<< ':';
715 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
716 unsigned quot(0), apos(0);
717 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
720 else if (*value
== '\'')
723 bool single(quot
> apos
);
725 std::ostringstream str
;
727 str
<< (single
? '\'' : '"');
728 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
730 case '\\': str
<< "\\\\"; break;
731 case '\b': str
<< "\\b"; break;
732 case '\f': str
<< "\\f"; break;
733 case '\n': str
<< "\\n"; break;
734 case '\r': str
<< "\\r"; break;
735 case '\t': str
<< "\\t"; break;
736 case '\v': str
<< "\\v"; break;
751 if (*value
< 0x20 || *value
>= 0x7f)
752 str
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value
);
756 str
<< (single
? '\'' : '"');
758 out
<< str
.str().c_str();
761 void CYString::PropertyName(CYOutput
&out
) const {
762 if (const char *word
= Word())
768 const char *CYString::Word() const {
769 if (size_
== 0 || !WordStartRange_
[value_
[0]])
771 for (size_t i(1); i
!= size_
; ++i
)
772 if (!WordEndRange_
[value_
[i
]])
774 const char *value(Value());
775 // XXX: we should probably include the full ECMAScript3+5 list.
776 static const char *reserveds
[] = {"class", "const", "enum", "export", "extends", "import", "super", NULL
};
777 for (const char **reserved(reserveds
); *reserved
!= NULL
; ++reserved
)
778 if (strcmp(*reserved
, value
) == 0)
783 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
784 out
<< "switch" << ' ' << '(' << *value_
<< ')' << ' ' << '{';
789 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
793 void CYThrow::Output(CYOutput
&out
, CYFlags flags
) const {
794 out
<< "throw" << value_
<< ';';
797 void CYTry::Output(CYOutput
&out
, CYFlags flags
) const {
798 out
<< "try" << ' ' << '{';
800 code_
->Multiple(out
);
806 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
808 declarations_
->Output(out
, flags
);
812 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
816 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
817 out
<< "while" << '(' << *test_
<< ')';
818 code_
->Single(out
, CYRight(flags
));
821 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
822 out
<< "with" << '(' << *scope_
<< ')';
823 code_
->Single(out
, CYRight(flags
));
826 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
828 out
<< "objc_getClass(";
829 out
<< '"' << Value() << '"';
834 void CYWord::Output(CYOutput
&out
) const {
838 void CYWord::PropertyName(CYOutput
&out
) const {