1 /* Cycript - Inlining/Optimizing JavaScript Compiler
2 * Copyright (C) 2009 Jay Freeman (saurik)
5 /* Modified BSD License {{{ */
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include "Replace.hpp"
45 CYExpression
*CYAdd::Replace(CYContext
&context
) {
46 CYInfix::Replace(context
);
48 CYExpression
*lhp(lhs_
->Primitive(context
));
49 CYExpression
*rhp(rhs_
->Primitive(context
));
51 CYString
*lhs(dynamic_cast<CYString
*>(lhp
));
52 CYString
*rhs(dynamic_cast<CYString
*>(rhp
));
54 if (lhs
!= NULL
|| rhs
!= NULL
) {
56 lhs
= lhp
->String(context
);
59 } else if (rhs
== NULL
) {
60 rhs
= rhp
->String(context
);
65 return lhs
->Concat(context
, rhs
);
68 if (CYNumber
*lhn
= lhp
->Number(context
))
69 if (CYNumber
*rhn
= rhp
->Number(context
))
70 return $
D(lhn
->Value() + rhn
->Value());
75 CYExpression
*CYAddressOf::Replace(CYContext
&context
) {
76 CYPrefix::Replace(context
);
77 return $
C0($
M(rhs_
, $
S("$cya")));
80 void CYArgument::Replace(CYContext
&context
) { $
T()
81 context
.Replace(value_
);
82 next_
->Replace(context
);
85 CYExpression
*CYArray::Replace(CYContext
&context
) {
86 elements_
->Replace(context
);
90 CYExpression
*CYArrayComprehension::Replace(CYContext
&context
) {
91 CYVariable
*cyv($
V("$cyv"));
93 return $
C0($
F(NULL
, $
P1("$cyv", comprehensions_
->Parameters(context
)), $$
->*
94 $
E($
CYAssign(cyv
, $
CYArray()))->*
95 comprehensions_
->Replace(context
, $
E($
C1($
M(cyv
, $
S("push")), expression_
)))->*
100 CYExpression
*CYAssignment::Replace(CYContext
&context
) {
101 context
.Replace(lhs_
);
102 context
.Replace(rhs_
);
106 CYStatement
*CYBlock::Replace(CYContext
&context
) {
107 statements_
= statements_
->ReplaceAll(context
);
108 if (statements_
== NULL
)
113 CYStatement
*CYBreak::Replace(CYContext
&context
) {
117 CYExpression
*CYCall::AddArgument(CYContext
&context
, CYExpression
*value
) {
118 CYArgument
**argument(&arguments_
);
119 while (*argument
!= NULL
)
120 argument
= &(*argument
)->next_
;
121 *argument
= $
CYArgument(value
);
125 CYExpression
*CYCall::Replace(CYContext
&context
) {
126 context
.Replace(function_
);
127 arguments_
->Replace(context
);
134 void Catch::Replace(CYContext
&context
) { $
T()
135 CYScope
scope(CYScopeCatch
, context
, code_
.statements_
);
137 context
.Replace(name_
);
138 context
.scope_
->Declare(context
, name_
, CYIdentifierCatch
);
140 code_
.Replace(context
);
146 void CYClause::Replace(CYContext
&context
) { $
T()
147 context
.Replace(case_
);
148 statements_
= statements_
->ReplaceAll(context
);
149 next_
->Replace(context
);
152 CYStatement
*CYComment::Replace(CYContext
&context
) {
156 CYExpression
*CYCompound::Replace(CYContext
&context
) {
157 expressions_
= expressions_
->ReplaceAll(context
);
158 return expressions_
== NULL
? NULL
: this;
161 CYFunctionParameter
*CYComprehension::Parameters(CYContext
&context
) const { $
T(NULL
)
162 CYFunctionParameter
*next(next_
->Parameters(context
));
163 if (CYFunctionParameter
*parameter
= Parameter(context
)) {
164 parameter
->SetNext(next
);
170 CYStatement
*CYComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
171 return next_
== NULL
? statement
: next_
->Replace(context
, statement
);
174 CYExpression
*CYCondition::Replace(CYContext
&context
) {
175 context
.Replace(test_
);
176 context
.Replace(true_
);
177 context
.Replace(false_
);
181 void CYContext::NonLocal(CYStatement
*&statements
) {
182 CYContext
&context(*this);
184 if (nextlocal_
!= NULL
&& nextlocal_
->identifier_
!= NULL
) {
185 CYIdentifier
*cye($
I("$cye")->Replace(context
));
186 CYIdentifier
*unique(nextlocal_
->identifier_
->Replace(context
));
188 CYStatement
*declare(
189 $
CYVar($
L1($
L(unique
, $
CYObject()))));
191 cy::Syntax::Catch
*rescue(
192 $
cy::Syntax::Catch(cye
, $$
->*
193 $
CYIf($
CYIdentical($
M($
CYVariable(cye
), $
S("$cyk")), $
CYVariable(unique
)), $$
->*
194 $
CYReturn($
M($
CYVariable(cye
), $
S("$cyv"))))->*
195 $
cy::Syntax::Throw($
CYVariable(cye
))));
197 declare
= declare
->Replace(context
);
198 rescue
->Replace(context
);
202 $
cy::Syntax::Try(statements
, rescue
, NULL
);
206 CYIdentifier
*CYContext::Unique() {
207 CYContext
&context(*this);
208 return $
CYIdentifier(apr_psprintf(pool_
, "$cy%u", unique_
++));
211 CYStatement
*CYContinue::Replace(CYContext
&context
) {
215 CYAssignment
*CYDeclaration::Assignment(CYContext
&context
) {
216 CYExpression
*variable(Replace(context
));
217 return initialiser_
== NULL
? NULL
: $
CYAssign(variable
, initialiser_
);
220 CYExpression
*CYDeclaration::ForEachIn(CYContext
&context
) {
221 return $
CYVariable(identifier_
);
224 CYExpression
*CYDeclaration::Replace(CYContext
&context
) {
225 context
.Replace(identifier_
);
226 context
.scope_
->Declare(context
, identifier_
, CYIdentifierVariable
);
227 return $
CYVariable(identifier_
);
230 CYProperty
*CYDeclarations::Property(CYContext
&context
) { $
T(NULL
)
231 return $
CYProperty(declaration_
->identifier_
, declaration_
->initialiser_
?: $U
, next_
->Property(context
));
234 CYCompound
*CYDeclarations::Replace(CYContext
&context
) {
235 CYCompound
*compound
;
236 if (next_
== NULL
) compound
:
237 compound
= $
CYCompound();
239 compound
= next_
->Replace(context
);
240 if (compound
== NULL
)
244 if (CYAssignment
*assignment
= declaration_
->Assignment(context
))
245 compound
->AddPrev(assignment
);
249 CYExpression
*CYDirectMember::Replace(CYContext
&context
) {
254 CYStatement
*CYDoWhile::Replace(CYContext
&context
) {
255 context
.Replace(test_
);
256 context
.Replace(code_
);
260 void CYElement::Replace(CYContext
&context
) { $
T()
261 context
.Replace(value_
);
262 next_
->Replace(context
);
265 CYStatement
*CYEmpty::Collapse(CYContext
&context
) {
269 CYStatement
*CYEmpty::Replace(CYContext
&context
) {
273 CYStatement
*CYExpress::Collapse(CYContext
&context
) {
274 if (CYExpress
*express
= dynamic_cast<CYExpress
*>(next_
)) {
275 CYCompound
*next(dynamic_cast<CYCompound
*>(express
->expression_
));
277 next
= $
CYCompound(express
->expression_
);
278 next
->AddPrev(expression_
);
280 SetNext(express
->next_
);
286 CYStatement
*CYExpress::Replace(CYContext
&context
) {
287 context
.Replace(expression_
);
288 if (expression_
== NULL
)
293 CYExpression
*CYExpression::AddArgument(CYContext
&context
, CYExpression
*value
) {
294 return $
C1(this, value
);
297 CYExpression
*CYExpression::ClassName(CYContext
&context
, bool object
) {
301 CYExpression
*CYExpression::ForEachIn(CYContext
&context
) {
305 CYExpression
*CYExpression::ReplaceAll(CYContext
&context
) { $
T(NULL
)
306 CYExpression
*replace(this);
307 context
.Replace(replace
);
309 if (CYExpression
*next
= next_
->ReplaceAll(context
))
310 replace
->SetNext(next
);
312 replace
->SetNext(next_
);
317 CYNumber
*CYFalse::Number(CYContext
&context
) {
321 CYString
*CYFalse::String(CYContext
&context
) {
325 void CYFinally::Replace(CYContext
&context
) { $
T()
326 code_
.Replace(context
);
329 CYStatement
*CYFor::Replace(CYContext
&context
) {
330 context
.Replace(initialiser_
);
331 context
.Replace(test_
);
332 context
.Replace(increment_
);
333 context
.Replace(code_
);
337 CYStatement
*CYForIn::Replace(CYContext
&context
) {
338 // XXX: this actually might need a prefix statement
339 context
.Replace(initialiser_
);
340 context
.Replace(set_
);
341 context
.Replace(code_
);
345 CYFunctionParameter
*CYForInComprehension::Parameter(CYContext
&context
) const {
346 return $
CYFunctionParameter(name_
);
349 CYStatement
*CYForInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
350 return $
CYForIn($
CYVariable(name_
), set_
, CYComprehension::Replace(context
, statement
));
353 CYStatement
*CYForEachIn::Replace(CYContext
&context
) {
354 CYVariable
*cys($
V("$cys")), *cyt($
V("$cyt"));
356 return $
CYLet($
L2($
L($
I("$cys"), set_
), $
L($
I("$cyt"))), $$
->*
357 $
CYForIn(cyt
, cys
, $
CYBlock($$
->*
358 $
E($
CYAssign(initialiser_
->ForEachIn(context
), $
M(cys
, cyt
)))->*
364 CYFunctionParameter
*CYForEachInComprehension::Parameter(CYContext
&context
) const {
365 return $
CYFunctionParameter(name_
);
368 CYStatement
*CYForEachInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
369 CYVariable
*cys($
V("$cys")), *name($
CYVariable(name_
));
371 return $
E($
C0($
F(NULL
, $
P1("$cys"), $$
->*
372 $
E($
CYAssign(cys
, set_
))->*
373 $
CYForIn(name
, cys
, $
CYBlock($$
->*
374 $
E($
CYAssign(name
, $
M(cys
, name
)))->*
375 CYComprehension::Replace(context
, statement
)
380 void CYFunction::Inject(CYContext
&context
) {
381 context
.Replace(name_
);
382 context
.scope_
->Declare(context
, name_
, CYIdentifierOther
);
385 void CYFunction::Replace_(CYContext
&context
, bool outer
) {
389 CYScope
scope(CYScopeFunction
, context
, code_
.statements_
);
391 CYNonLocal
*nonlocal(context
.nonlocal_
);
392 CYNonLocal
*nextlocal(context
.nextlocal_
);
395 if (nonlocal_
!= NULL
) {
397 context
.nonlocal_
= nonlocal_
;
400 nonlocal_
= $
CYNonLocal();
401 context
.nextlocal_
= nonlocal_
;
404 if (!outer
&& name_
!= NULL
)
407 if (parameters_
!= NULL
)
408 parameters_
= parameters_
->Replace(context
, code_
);
410 code_
.Replace(context
);
413 context
.NonLocal(code_
.statements_
);
415 context
.nextlocal_
= nextlocal
;
416 context
.nonlocal_
= nonlocal
;
421 CYExpression
*CYFunctionExpression::Replace(CYContext
&context
) {
422 Replace_(context
, false);
426 CYFunctionParameter
*CYFunctionParameter::Replace(CYContext
&context
, CYBlock
&code
) {
427 name_
= name_
->Replace(context
);
428 context
.scope_
->Declare(context
, name_
, CYIdentifierArgument
);
430 next_
= next_
->Replace(context
, code
);
434 CYStatement
*CYFunctionStatement::Replace(CYContext
&context
) {
435 Replace_(context
, true);
439 CYIdentifier
*CYIdentifier::Replace(CYContext
&context
) {
440 if (replace_
!= NULL
&& replace_
!= this)
441 return replace_
->Replace(context
);
442 replace_
= context
.scope_
->Lookup(context
, this);
446 CYStatement
*CYIf::Replace(CYContext
&context
) {
447 context
.Replace(test_
);
448 context
.Replace(true_
);
449 context
.Replace(false_
);
453 CYFunctionParameter
*CYIfComprehension::Parameter(CYContext
&context
) const {
457 CYStatement
*CYIfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
458 return $
CYIf(test_
, CYComprehension::Replace(context
, statement
));
461 CYExpression
*CYIndirect::Replace(CYContext
&context
) {
462 CYPrefix::Replace(context
);
463 return $
M(rhs_
, $
S("$cyi"));
466 CYExpression
*CYIndirectMember::Replace(CYContext
&context
) {
468 return $
M($
CYIndirect(object_
), property_
);
471 CYExpression
*CYInfix::Replace(CYContext
&context
) {
472 context
.Replace(lhs_
);
473 context
.Replace(rhs_
);
477 CYStatement
*CYLabel::Replace(CYContext
&context
) {
478 context
.Replace(statement_
);
482 CYStatement
*CYLet::Replace(CYContext
&context
) {
483 return $
CYWith($
CYObject(declarations_
->Property(context
)), &code_
);
486 void CYMember::Replace_(CYContext
&context
) {
487 context
.Replace(object_
);
488 context
.Replace(property_
);
491 CYExpression
*CYNew::AddArgument(CYContext
&context
, CYExpression
*value
) {
492 CYArgument
**argument(&arguments_
);
493 while (*argument
!= NULL
)
494 argument
= &(*argument
)->next_
;
495 *argument
= $
CYArgument(value
);
499 CYExpression
*CYNew::Replace(CYContext
&context
) {
500 context
.Replace(constructor_
);
501 arguments_
->Replace(context
);
505 CYNumber
*CYNull::Number(CYContext
&context
) {
509 CYString
*CYNull::String(CYContext
&context
) {
513 CYNumber
*CYNumber::Number(CYContext
&context
) {
517 CYString
*CYNumber::String(CYContext
&context
) {
518 // XXX: there is a precise algorithm for this
519 return $
S(apr_psprintf(context
.pool_
, "%.17g", Value()));
522 CYExpression
*CYObject::Replace(CYContext
&context
) {
523 properties_
->Replace(context
);
527 CYFunctionParameter
*CYOptionalFunctionParameter::Replace(CYContext
&context
, CYBlock
&code
) {
528 CYFunctionParameter
*parameter($
CYFunctionParameter(name_
, next_
));
529 parameter
= parameter
->Replace(context
, code
);
530 initializer_
= initializer_
->Replace(context
);
532 CYVariable
*name($
CYVariable(name_
));
533 code
.AddPrev($
CYIf($
CYIdentical($
CYTypeOf(name
), $
S("undefined")), $$
->*
534 $
E($
CYAssign(name
, initializer_
))
540 CYExpression
*CYPostfix::Replace(CYContext
&context
) {
541 context
.Replace(lhs_
);
545 CYExpression
*CYPrefix::Replace(CYContext
&context
) {
546 context
.Replace(rhs_
);
550 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
551 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
552 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
555 struct IdentifierUsageLess
:
556 std::binary_function
<CYIdentifier
*, CYIdentifier
*, bool>
558 _finline
bool operator ()(CYIdentifier
*lhs
, CYIdentifier
*rhs
) const {
559 if (lhs
->usage_
!= rhs
->usage_
)
560 return lhs
->usage_
> rhs
->usage_
;
565 typedef std::set
<CYIdentifier
*, IdentifierUsageLess
> IdentifierUsages
;
568 void CYProgram::Replace(CYContext
&context
) {
569 CYScope
scope(CYScopeProgram
, context
, statements_
);
571 context
.nextlocal_
= $
CYNonLocal();
572 statements_
= statements_
->ReplaceAll(context
);
573 context
.NonLocal(statements_
);
579 CYCStringSet external
;
580 for (CYIdentifierValueSet::const_iterator
i(scope
.identifiers_
.begin()); i
!= scope
.identifiers_
.end(); ++i
)
581 external
.insert((*i
)->Word());
583 IdentifierUsages usages
;
585 if (offset
< context
.rename_
.size())
586 for (CYIdentifier
*i(context
.rename_
[offset
].identifier_
); i
!= NULL
; i
= i
->next_
)
589 // XXX: totalling the probable occurrences and sorting by them would improve the result
590 for (CYIdentifierUsageVector::const_iterator
i(context
.rename_
.begin()); i
!= context
.rename_
.end(); ++i
, ++offset
) {
591 //std::cout << *i << ":" << (*i)->offset_ << std::endl;
595 if (context
.options_
.verbose_
)
596 name
= apr_psprintf(context
.pool_
, "$%"APR_SIZE_T_FMT
"", offset
);
602 unsigned position(7), local(offset
+ 1);
605 unsigned index(local
% (sizeof(MappingSet
) - 1));
606 local
/= sizeof(MappingSet
) - 1;
607 id
[--position
] = MappingSet
[index
];
608 } while (local
!= 0);
610 if (external
.find(id
+ position
) != external
.end()) {
615 name
= apr_pstrmemdup(context
.pool_
, id
+ position
, 7 - position
);
616 // XXX: at some point, this could become a keyword
619 for (CYIdentifier
*identifier(i
->identifier_
); identifier
!= NULL
; identifier
= identifier
->next_
)
620 identifier
->Set(name
);
624 void CYProperty::Replace(CYContext
&context
) { $
T()
625 context
.Replace(value_
);
626 next_
->Replace(context
);
629 CYStatement
*CYReturn::Replace(CYContext
&context
) {
630 if (context
.nonlocal_
!= NULL
) {
631 CYProperty
*value(value_
== NULL
? NULL
: $
CYProperty($
S("$cyv"), value_
));
632 return $
cy::Syntax::Throw($
CYObject(
633 $
CYProperty($
S("$cyk"), $
CYVariable(context
.nonlocal_
->Target(context
)), value
)
637 context
.Replace(value_
);
641 CYExpression
*CYRubyBlock::Replace(CYContext
&context
) {
642 // XXX: this needs to do something much more epic to handle return
643 return call_
->AddArgument(context
, proc_
->Replace(context
));
646 CYExpression
*CYRubyProc::Replace(CYContext
&context
) {
647 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
648 function
->nonlocal_
= context
.nextlocal_
;
652 CYScope::CYScope(CYScopeType type
, CYContext
&context
, CYStatement
*&statements
) :
655 statements_(statements
),
656 parent_(context
.scope_
)
658 context_
.scope_
= this;
661 void CYScope::Close() {
662 context_
.scope_
= parent_
;
663 Scope(context_
, statements_
);
666 void CYScope::Declare(CYContext
&context
, CYIdentifier
*identifier
, CYIdentifierFlags flags
) {
667 if (type_
== CYScopeCatch
&& flags
!= CYIdentifierCatch
)
668 parent_
->Declare(context
, identifier
, flags
);
670 internal_
.insert(CYIdentifierAddressFlagsMap::value_type(identifier
, flags
));
673 CYIdentifier
*CYScope::Lookup(CYContext
&context
, CYIdentifier
*identifier
) {
674 std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
));
675 return *insert
.first
;
678 void CYScope::Merge(CYContext
&context
, CYIdentifier
*identifier
) {
679 std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
));
680 if (!insert
.second
) {
681 if ((*insert
.first
)->offset_
< identifier
->offset_
)
682 (*insert
.first
)->offset_
= identifier
->offset_
;
683 identifier
->replace_
= *insert
.first
;
684 (*insert
.first
)->usage_
+= identifier
->usage_
+ 1;
689 struct IdentifierOffset
{
691 CYIdentifierFlags flags_
;
693 CYIdentifier
*identifier_
;
695 IdentifierOffset(CYIdentifier
*identifier
, CYIdentifierFlags flags
) :
696 offset_(identifier
->offset_
),
698 usage_(identifier
->usage_
),
699 identifier_(identifier
)
704 struct IdentifierOffsetLess
:
705 std::binary_function
<const IdentifierOffset
&, const IdentifierOffset
&, bool>
707 _finline
bool operator ()(const IdentifierOffset
&lhs
, const IdentifierOffset
&rhs
) const {
708 if (lhs
.offset_
!= rhs
.offset_
)
709 return lhs
.offset_
< rhs
.offset_
;
710 if (lhs
.flags_
!= rhs
.flags_
)
711 return lhs
.flags_
< rhs
.flags_
;
712 /*if (lhs.usage_ != rhs.usage_)
713 return lhs.usage_ < rhs.usage_;*/
714 return lhs
.identifier_
< rhs
.identifier_
;
718 typedef std::set
<IdentifierOffset
, IdentifierOffsetLess
> IdentifierOffsets
;
721 void CYScope::Scope(CYContext
&context
, CYStatement
*&statements
) {
725 CYDeclarations
*last(NULL
), *curr(NULL
);
727 IdentifierOffsets offsets
;
729 for (CYIdentifierAddressFlagsMap::const_iterator
i(internal_
.begin()); i
!= internal_
.end(); ++i
)
730 if (i
->second
!= CYIdentifierMagic
)
731 offsets
.insert(IdentifierOffset(i
->first
, i
->second
));
735 for (IdentifierOffsets::const_iterator
i(offsets
.begin()); i
!= offsets
.end(); ++i
) {
736 if (i
->flags_
== CYIdentifierVariable
) {
737 CYDeclarations
*next($
CYDeclarations($
CYDeclaration(i
->identifier_
)));
745 if (offset
< i
->offset_
)
747 if (context
.rename_
.size() <= offset
)
748 context
.rename_
.resize(offset
+ 1);
750 CYIdentifierUsage
&rename(context
.rename_
[offset
++]);
751 i
->identifier_
->SetNext(rename
.identifier_
);
752 rename
.identifier_
= i
->identifier_
;
753 rename
.usage_
+= i
->identifier_
->usage_
+ 1;
757 CYVar
*var($
CYVar(last
));
758 var
->SetNext(statements
);
762 for (CYIdentifierValueSet::const_iterator
i(identifiers_
.begin()); i
!= identifiers_
.end(); ++i
)
763 if (internal_
.find(*i
) == internal_
.end()) {
764 //std::cout << *i << '=' << offset << std::endl;
765 if ((*i
)->offset_
< offset
)
766 (*i
)->offset_
= offset
;
767 parent_
->Merge(context
, *i
);
771 CYStatement
*CYStatement::Collapse(CYContext
&context
) {
775 CYStatement
*CYStatement::ReplaceAll(CYContext
&context
) { $
T(NULL
)
776 CYStatement
*replace(this);
777 context
.Replace(replace
);
778 replace
->SetNext(next_
->ReplaceAll(context
));
779 return replace
->Collapse(context
);
782 CYString
*CYString::Concat(CYContext
&context
, CYString
*rhs
) const {
783 size_t size(size_
+ rhs
->size_
);
784 char *value(new(context
.pool_
) char[size
+ 1]);
785 memcpy(value
, value_
, size_
);
786 memcpy(value
+ size_
, rhs
->value_
, rhs
->size_
);
788 return $
S(value
, size
);
791 CYNumber
*CYString::Number(CYContext
&context
) {
792 // XXX: there is a precise algorithm for this
796 CYString
*CYString::String(CYContext
&context
) {
800 CYStatement
*CYSwitch::Replace(CYContext
&context
) {
801 context
.Replace(value_
);
802 clauses_
->Replace(context
);
806 CYExpression
*CYThis::Replace(CYContext
&context
) {
813 CYStatement
*Throw::Replace(CYContext
&context
) {
814 context
.Replace(value_
);
820 CYExpression
*CYTrivial::Replace(CYContext
&context
) {
824 CYNumber
*CYTrue::Number(CYContext
&context
) {
828 CYString
*CYTrue::String(CYContext
&context
) {
835 CYStatement
*Try::Replace(CYContext
&context
) {
836 code_
.Replace(context
);
837 catch_
->Replace(context
);
838 finally_
->Replace(context
);
844 CYStatement
*CYVar::Replace(CYContext
&context
) {
845 return $
E(declarations_
->Replace(context
));
848 CYExpression
*CYVariable::Replace(CYContext
&context
) {
849 name_
= name_
->Replace(context
);
853 CYStatement
*CYWhile::Replace(CYContext
&context
) {
854 context
.Replace(test_
);
855 context
.Replace(code_
);
859 CYStatement
*CYWith::Replace(CYContext
&context
) {
860 context
.Replace(scope_
);
861 context
.Replace(code_
);
865 CYExpression
*CYWord::ClassName(CYContext
&context
, bool object
) {
866 CYString
*name($
S(this));
868 return $
C1($
V("objc_getClass"), name
);