]>
git.saurik.com Git - cycript.git/blob - Output.cpp
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 CYOutput
&CYOutput::operator <<(char rhs
) {
48 if (mode_
== Terminated
&& rhs
!= '}')
58 } else if (rhs
== '-') {
59 if (mode_
== NoHyphen
)
62 } else if (WordEndRange_
[rhs
]) {
63 if (mode_
== NoLetter
)
74 CYOutput
&CYOutput::operator <<(const char *rhs
) {
75 size_t size(strlen(rhs
));
80 if (mode_
== Terminated
)
83 mode_
== NoHyphen
&& *rhs
== '-' ||
84 mode_
== NoLetter
&& WordEndRange_
[*rhs
]
88 if (WordEndRange_
[rhs
[size
- 1]])
97 void CYOutput::Indent() {
100 for (unsigned i(0); i
!= indent_
; ++i
)
105 void OutputBody(CYOutput
&out
, CYStatement
*body
) {
117 void CYAddressOf::Output(CYOutput
&out
, CYFlags flags
) const {
118 rhs_
->Output(out
, 1, CYLeft(flags
));
122 void CYArgument::Output(CYOutput
&out
) const {
129 value_
->Output(out
, CYPA
, CYNoFlags
);
131 if (next_
->name_
== NULL
)
133 out
<< ' ' << *next_
;
137 void CYArray::Output(CYOutput
&out
, CYFlags flags
) const {
138 out
<< '[' << elements_
<< ']';
141 void CYArrayComprehension::Output(CYOutput
&out
, CYFlags flags
) const {
142 // XXX: I don't necc. need the ()s
143 out
<< "(function($cyv";
144 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
145 if (const char *name
= comprehension
->Name())
149 comprehensions_
->Output(out
);
151 expression_
->Output(out
, CYPA
, CYNoFlags
);
153 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
154 comprehension
->End_(out
);
155 out
<< "return $cyv;";
159 void CYAssignment::Output(CYOutput
&out
, CYFlags flags
) const {
160 lhs_
->Output(out
, Precedence() - 1, CYLeft(flags
) | CYNoRightHand
);
161 out
<< ' ' << Operator() << ' ';
162 rhs_
->Output(out
, Precedence(), CYRight(flags
));
165 void CYBlock::Output(CYOutput
&out
, CYFlags flags
) const {
166 statements_
->Single(out
, flags
);
169 void CYBoolean::Output(CYOutput
&out
, CYFlags flags
) const {
170 out
<< (Value() ? "true" : "false");
173 void CYBreak::Output(CYOutput
&out
, CYFlags flags
) const {
176 out
<< ' ' << *label_
;
180 void CYCall::Output(CYOutput
&out
, CYFlags flags
) const {
181 bool protect((flags
& CYNoCall
) != 0);
184 function_
->Output(out
, Precedence(), protect
? CYNoFlags
: flags
);
185 out
<< '(' << arguments_
<< ')';
190 void CYCatch::Output(CYOutput
&out
) const {
191 out
<< "catch" << ' ' << '(' << *name_
<< ')' << ' ' << '{';
193 code_
->Multiple(out
);
197 void CYCategory::Output(CYOutput
&out
, CYFlags flags
) const {
198 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt){";
199 out
<< "$cyp=object_getClass($cys);";
201 if (messages_
!= NULL
)
202 messages_
->Output(out
, true);
204 name_
->ClassName(out
, true);
209 void CYClass::Output(CYOutput
&out
, CYFlags flags
) const {
210 // XXX: I don't necc. need the ()s
211 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
212 out
<< "$cyp=object_getClass($cys);";
213 out
<< "$cyc=objc_allocateClassPair($cys,";
215 name_
->ClassName(out
, false);
217 out
<< "$cyq(\"CY$\")";
219 out
<< "$cym=object_getClass($cyc);";
221 fields_
->Output(out
);
222 if (messages_
!= NULL
)
223 messages_
->Output(out
, false);
224 out
<< "objc_registerClassPair($cyc);";
225 out
<< "return $cyc;";
228 super_
->Output(out
, CYPA
, CYNoFlags
);
234 void CYClassExpression::Output(CYOutput
&out
, CYFlags flags
) const {
235 CYClass::Output(out
, flags
);
238 void CYClassStatement::Output(CYOutput
&out
, CYFlags flags
) const {
239 CYClass::Output(out
, flags
);
242 void CYCompound::Output(CYOutput
&out
, CYFlags flags
) const {
243 if (CYExpression
*expression
= expressions_
)
244 if (CYExpression
*next
= expression
->next_
) {
245 expression
->Output(out
, CYLeft(flags
));
246 CYFlags
center(CYCenter(flags
));
247 while (next
!= NULL
) {
250 next
= expression
->next_
;
251 CYFlags
right(next
!= NULL
? center
: CYRight(flags
));
252 expression
->Output(out
, right
);
255 expression
->Output(out
, flags
);
258 void CYComprehension::Output(CYOutput
&out
) const {
263 void CYCondition::Output(CYOutput
&out
, CYFlags flags
) const {
264 test_
->Output(out
, Precedence() - 1, CYLeft(flags
));
265 out
<< ' ' << '?' << ' ';
267 true_
->Output(out
, CYPA
, CYNoFlags
);
268 out
<< ' ' << ':' << ' ';
269 false_
->Output(out
, CYPA
, CYRight(flags
));
272 void CYContinue::Output(CYOutput
&out
, CYFlags flags
) const {
275 out
<< ' ' << *label_
;
279 void CYClause::Output(CYOutput
&out
) const {
281 out
<< "case" << ' ' << *case_
;
288 code_
->Multiple(out
, CYNoFlags
);
292 const char *CYDeclaration::ForEachIn() const {
293 return identifier_
->Value();
296 void CYDeclaration::ForIn(CYOutput
&out
, CYFlags flags
) const {
298 Output(out
, CYRight(flags
));
301 void CYDeclaration::ForEachIn(CYOutput
&out
) const {
305 void CYDeclaration::Output(CYOutput
&out
, CYFlags flags
) const {
307 if (initialiser_
!= NULL
) {
308 out
<< ' ' << '=' << ' ';
309 initialiser_
->Output(out
, CYPA
, CYRight(flags
));
313 void CYDeclarations::For(CYOutput
&out
) const {
318 void CYDeclarations::Output(CYOutput
&out
) const {
319 Output(out
, CYNoFlags
);
322 void CYDeclarations::Output(CYOutput
&out
, CYFlags flags
) const {
323 const CYDeclarations
*declaration(this);
326 CYDeclarations
*next(declaration
->next_
);
327 CYFlags
jacks(first
? CYLeft(flags
) : next
== NULL
? CYRight(flags
) : CYCenter(flags
));
329 declaration
->declaration_
->Output(out
, jacks
);
338 void CYDirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
339 object_
->Output(out
, Precedence(), CYLeft(flags
));
340 if (const char *word
= property_
->Word())
343 out
<< '[' << *property_
<< ']';
346 void CYDoWhile::Output(CYOutput
&out
, CYFlags flags
) const {
348 code_
->Single(out
, CYNoFlags
);
349 out
<< "while" << ' ' << '(' << *test_
<< ')';
352 void CYElement::Output(CYOutput
&out
) const {
354 value_
->Output(out
, CYPA
, CYNoFlags
);
355 if (next_
!= NULL
|| value_
== NULL
) {
357 if (next_
!= NULL
&& next_
->value_
!= NULL
)
364 void CYEmpty::Output(CYOutput
&out
, CYFlags flags
) const {
368 void CYExpress::Output(CYOutput
&out
, CYFlags flags
) const {
369 expression_
->Output(out
, flags
| CYNoBF
);
373 void CYExpression::ClassName(CYOutput
&out
, bool object
) const {
374 Output(out
, CYPA
, CYNoFlags
);
377 const char *CYExpression::ForEachIn() const {
381 void CYExpression::For(CYOutput
&out
) const {
385 void CYExpression::ForEachIn(CYOutput
&out
) const {
386 Output(out
, CYPA
, CYNoRightHand
);
389 void CYExpression::ForIn(CYOutput
&out
, CYFlags flags
) const {
390 Output(out
, flags
| CYNoRightHand
);
393 void CYExpression::Output(CYOutput
&out
) const {
394 Output(out
, CYNoFlags
);
397 void CYExpression::Output(CYOutput
&out
, unsigned precedence
, CYFlags flags
) const {
398 if (precedence
< Precedence() || (flags
& CYNoRightHand
) != 0 && RightHand())
399 out
<< '(' << *this << ')';
404 void CYField::Output(CYOutput
&out
) const {
408 void CYFinally::Output(CYOutput
&out
) const {
409 out
<< "finally" << ' ' << '{';
411 code_
->Multiple(out
);
415 void CYFor::Output(CYOutput
&out
, CYFlags flags
) const {
416 out
<< "for" << ' ' << '(';
417 if (initialiser_
!= NULL
)
418 initialiser_
->For(out
);
424 code_
->Single(out
, CYNoFlags
);
427 void CYForEachIn::Output(CYOutput
&out
, CYFlags flags
) const {
428 out
<< "with({$cys:0,$cyt:0}){";
431 set_
->Output(out
, CYPA
, CYNoFlags
);
434 out
<< "for($cyt in $cys){";
436 initialiser_
->ForEachIn(out
);
437 out
<< "=$cys[$cyt];";
439 code_
->Multiple(out
);
446 void CYForEachInComprehension::Begin_(CYOutput
&out
) const {
447 out
<< "(function($cys){";
449 set_
->Output(out
, CYPA
, CYNoFlags
);
452 out
<< "for(" << *name_
<< " in $cys){";
453 out
<< *name_
<< "=$cys[" << *name_
<< "];";
456 void CYForEachInComprehension::End_(CYOutput
&out
) const {
460 void CYForIn::Output(CYOutput
&out
, CYFlags flags
) const {
461 out
<< "for" << ' ' << '(';
462 initialiser_
->ForIn(out
, CYNoIn
);
463 out
<< "in" << *set_
<< ')';
464 code_
->Single(out
, CYRight(flags
));
467 void CYForInComprehension::Begin_(CYOutput
&out
) const {
468 out
<< "for" << ' ' << '(' << *name_
<< "in" << *set_
<< ')';
471 void CYFunction::Output(CYOutput
&out
, CYFlags flags
) const {
472 bool protect((flags
& CYNoFunction
) != 0);
477 out
<< ' ' << *name_
;
479 if (parameters_
!= NULL
)
482 OutputBody(out
, body_
);
487 void CYFunctionExpression::Output(CYOutput
&out
, CYFlags flags
) const {
488 CYFunction::Output(out
, flags
);
491 void CYFunctionStatement::Output(CYOutput
&out
, CYFlags flags
) const {
492 CYFunction::Output(out
, flags
);
495 void CYFunctionParameter::Output(CYOutput
&out
) const {
498 out
<< ',' << ' ' << *next_
;
501 void CYIf::Output(CYOutput
&out
, CYFlags flags
) const {
503 if (false_
== NULL
&& (flags
& CYNoDangle
) != 0) {
507 out
<< "if" << ' ' << '(';
508 test_
->Output(out
, CYNoFlags
);
510 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
511 CYFlags
jacks(CYNoDangle
);
514 true_
->Single(out
, jacks
);
515 if (false_
!= NULL
) {
517 false_
->Single(out
, right
);
523 void CYIfComprehension::Begin_(CYOutput
&out
) const {
524 out
<< "if" << '(' << *test_
<< ')';
527 void CYIndirect::Output(CYOutput
&out
, CYFlags flags
) const {
528 rhs_
->Output(out
, 1, CYLeft(flags
));
532 void CYIndirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
533 object_
->Output(out
, Precedence(), CYLeft(flags
));
535 if (const char *word
= property_
->Word())
538 out
<< '[' << *property_
<< ']';
541 void CYInfix::Output(CYOutput
&out
, CYFlags flags
) const {
542 const char *name(Operator());
543 bool protect((flags
& CYNoIn
) != 0 && strcmp(name
, "in"));
546 CYFlags
left(protect
? CYNoFlags
: CYLeft(flags
));
547 lhs_
->Output(out
, Precedence(), left
);
548 out
<< ' ' << name
<< ' ';
549 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
550 rhs_
->Output(out
, Precedence() - 1, right
);
555 void CYLet::Output(CYOutput
&out
, CYFlags flags
) const {
556 out
<< "let" << ' ' << '(' << *declarations_
<< ')' << ' ' << '{';
557 if (statements_
!= NULL
)
558 statements_
->Multiple(out
);
562 void CYMessage::Output(CYOutput
&out
, bool replace
) const {
564 next_
->Output(out
, replace
);
565 out
<< "$cyn=new Selector(\"";
566 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
567 if (parameter
->tag_
!= NULL
) {
568 out
<< *parameter
->tag_
;
569 if (parameter
->name_
!= NULL
)
573 out
<< "$cyt=$cyn.type($cy" << (instance_
? 's' : 'p') << ");";
574 out
<< "class_" << (replace
? "replace" : "add") << "Method($cy" << (instance_
? 'c' : 'm') << ",$cyn,";
575 out
<< "new Functor(function(self,_cmd";
576 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
577 if (parameter
->name_
!= NULL
)
578 out
<< ',' << *parameter
->name_
;
579 out
<< "){return function(){";
581 body_
->Multiple(out
);
582 out
<< "}.call(self);},$cyt),$cyt);";
585 void CYNew::Output(CYOutput
&out
, CYFlags flags
) const {
587 CYFlags
jacks(CYNoCall
| CYCenter(flags
));
588 constructor_
->Output(out
, Precedence(), jacks
);
589 if (arguments_
!= NULL
)
590 out
<< '(' << *arguments_
<< ')';
593 void CYNull::Output(CYOutput
&out
, CYFlags flags
) const {
597 void CYNumber::Output(CYOutput
&out
, CYFlags flags
) const {
599 sprintf(value
, "%.17g", Value());
603 void CYNumber::PropertyName(CYOutput
&out
) const {
604 Output(out
, CYNoFlags
);
607 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
608 bool protect((flags
& CYNoBrace
) != 0);
618 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
619 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
623 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
624 const char *name(Operator());
628 rhs_
->Output(out
, Precedence(), CYRight(flags
));
631 void CYProperty::Output(CYOutput
&out
) const {
632 name_
->PropertyName(out
);
634 value_
->Output(out
, CYPA
, CYNoFlags
);
636 out
<< ',' << ' ' << *next_
;
639 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
643 void CYReturn::Output(CYOutput
&out
, CYFlags flags
) const {
644 out
<< "return" << value_
<< ';';
647 void CYSelector::Output(CYOutput
&out
, CYFlags flags
) const {
648 out
<< "new Selector(\"";
654 void CYSelectorPart::Output(CYOutput
&out
) const {
661 void CYSend::Output(CYOutput
&out
, CYFlags flags
) const {
662 out
<< "objc_msgSend(";
663 self_
->Output(out
, CYPA
, CYNoFlags
);
665 std::ostringstream name
;
666 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
667 if (argument
->name_
!= NULL
) {
668 name
<< *argument
->name_
;
669 if (argument
->value_
!= NULL
)
672 out
.out_
<< reinterpret_cast<void *>(sel_registerName(name
.str().c_str()));
673 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
674 if (argument
->value_
!= NULL
) {
676 argument
->value_
->Output(out
, CYPA
, CYNoFlags
);
681 void CYStatement::Multiple(CYOutput
&out
, CYFlags flags
) const {
683 for (const CYStatement
*next(this); next
!= NULL
; next
= next
->next_
) {
684 bool last(next
->next_
== NULL
);
685 CYFlags
jacks(first
? last
? flags
: CYLeft(flags
) : last
? CYCenter(flags
) : CYRight(flags
));
688 next
->Output(out
, jacks
);
694 void CYStatement::Single(CYOutput
&out
, CYFlags flags
) const {
707 for (CYLabel
*label(labels_
); label
!= NULL
; label
= label
->next_
)
708 out
<< *label
->name_
<< ':' << ' ';
718 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
719 unsigned quot(0), apos(0);
720 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
723 else if (*value
== '\'')
726 bool single(quot
> apos
);
728 std::ostringstream str
;
730 str
<< (single
? '\'' : '"');
731 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
733 case '\\': str
<< "\\\\"; break;
734 case '\b': str
<< "\\b"; break;
735 case '\f': str
<< "\\f"; break;
736 case '\n': str
<< "\\n"; break;
737 case '\r': str
<< "\\r"; break;
738 case '\t': str
<< "\\t"; break;
739 case '\v': str
<< "\\v"; break;
754 if (*value
< 0x20 || *value
>= 0x7f)
755 str
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value
);
759 str
<< (single
? '\'' : '"');
761 out
<< str
.str().c_str();
764 void CYString::PropertyName(CYOutput
&out
) const {
765 if (const char *word
= Word())
771 const char *CYString::Word() const {
772 if (size_
== 0 || !WordStartRange_
[value_
[0]])
774 for (size_t i(1); i
!= size_
; ++i
)
775 if (!WordEndRange_
[value_
[i
]])
777 const char *value(Value());
778 // XXX: we should probably include the full ECMAScript3+5 list.
779 static const char *reserveds
[] = {"class", "const", "enum", "export", "extends", "import", "super", NULL
};
780 for (const char **reserved(reserveds
); *reserved
!= NULL
; ++reserved
)
781 if (strcmp(*reserved
, value
) == 0)
786 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
787 out
<< "switch" << ' ' << '(' << *value_
<< ')' << ' ' << '{';
792 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
796 void CYThrow::Output(CYOutput
&out
, CYFlags flags
) const {
797 out
<< "throw" << value_
<< ';';
800 void CYTry::Output(CYOutput
&out
, CYFlags flags
) const {
801 out
<< "try" << ' ' << '{';
803 code_
->Multiple(out
);
809 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
811 declarations_
->Output(out
, flags
);
815 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
819 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
820 out
<< "while" << '(' << *test_
<< ')';
821 code_
->Single(out
, CYRight(flags
));
824 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
825 out
<< "with" << '(' << *scope_
<< ')';
826 code_
->Single(out
, CYRight(flags
));
829 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
831 out
<< "objc_getClass(";
832 out
<< '"' << Value() << '"';
837 void CYWord::Output(CYOutput
&out
) const {
841 void CYWord::PropertyName(CYOutput
&out
) const {