1 /* Cycript - Optimizing JavaScript Compiler/Runtime 
   2  * Copyright (C) 2009-2012  Jay Freeman (saurik) 
   5 /* GNU Lesser General Public License, Version 3 {{{ */ 
   7  * Cycript is free software: you can redistribute it and/or modify it under 
   8  * the terms of the GNU Lesser General Public License as published by the 
   9  * Free Software Foundation, either version 3 of the License, or (at your 
  10  * option) any later version. 
  12  * Cycript is distributed in the hope that it will be useful, but WITHOUT 
  13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
  15  * License for more details. 
  17  * You should have received a copy of the GNU Lesser General Public License 
  18  * along with Cycript.  If not, see <http://www.gnu.org/licenses/>. 
  23 #include "Replace.hpp" 
  27 CYFunctionExpression 
*CYNonLocalize(CYContext 
&context
, CYFunctionExpression 
*function
) { 
  28     function
->nonlocal_ 
= context
.nextlocal_
; 
  32 CYExpression 
*CYAdd::Replace(CYContext 
&context
) { 
  33     CYInfix::Replace(context
); 
  35     CYExpression 
*lhp(lhs_
->Primitive(context
)); 
  36     CYExpression 
*rhp(rhs_
->Primitive(context
)); 
  38     CYString 
*lhs(dynamic_cast<CYString 
*>(lhp
)); 
  39     CYString 
*rhs(dynamic_cast<CYString 
*>(rhp
)); 
  41     if (lhs 
!= NULL 
|| rhs 
!= NULL
) { 
  43             lhs 
= lhp
->String(context
); 
  46         } else if (rhs 
== NULL
) { 
  47             rhs 
= rhp
->String(context
); 
  52         return lhs
->Concat(context
, rhs
); 
  55     if (CYNumber 
*lhn 
= lhp
->Number(context
)) 
  56         if (CYNumber 
*rhn 
= rhp
->Number(context
)) 
  57             return $
D(lhn
->Value() + rhn
->Value()); 
  62 CYExpression 
*CYAddressOf::Replace(CYContext 
&context
) { 
  63     return $
C0($
M(rhs_
, $
S("$cya"))); 
  66 CYArgument 
*CYArgument::Replace(CYContext 
&context
) { $
T(NULL
) 
  67     context
.Replace(value_
); 
  68     next_ 
= next_
->Replace(context
); 
  80 CYExpression 
*CYArray::Replace(CYContext 
&context
) { 
  81     elements_
->Replace(context
); 
  85 CYExpression 
*CYArrayComprehension::Replace(CYContext 
&context
) { 
  86     CYVariable 
*cyv($
V("$cyv")); 
  88     return $
C0($
F(NULL
, $
P1($
L("$cyv"), comprehensions_
->Parameters(context
)), $$
->* 
  89         $
E($ 
CYAssign(cyv
, $ 
CYArray()))->* 
  90         comprehensions_
->Replace(context
, $
E($
C1($
M(cyv
, $
S("push")), expression_
)))->* 
  95 CYExpression 
*CYAssignment::Replace(CYContext 
&context
) { 
  96     context
.Replace(lhs_
); 
  97     context
.Replace(rhs_
); 
 101 CYStatement 
*CYBlock::Replace(CYContext 
&context
) { 
 102     context
.ReplaceAll(statements_
); 
 103     if (statements_ 
== NULL
) 
 108 CYStatement 
*CYBreak::Replace(CYContext 
&context
) { 
 112 CYExpression 
*CYCall::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 113     CYArgument 
**argument(&arguments_
); 
 114     while (*argument 
!= NULL
) 
 115         argument 
= &(*argument
)->next_
; 
 116     *argument 
= $ 
CYArgument(value
); 
 120 CYExpression 
*CYCall::Replace(CYContext 
&context
) { 
 121     context
.Replace(function_
); 
 122     arguments_
->Replace(context
); 
 129 void Catch::Replace(CYContext 
&context
) { $
T() 
 130     CYScope 
scope(true, context
, code_
.statements_
); 
 132     context
.Replace(name_
); 
 133     context
.scope_
->Declare(context
, name_
, CYIdentifierCatch
); 
 135     code_
.Replace(context
); 
 141 void CYClause::Replace(CYContext 
&context
) { $
T() 
 142     context
.Replace(case_
); 
 143     context
.ReplaceAll(statements_
); 
 144     next_
->Replace(context
); 
 147 CYStatement 
*CYComment::Replace(CYContext 
&context
) { 
 151 CYExpression 
*CYCompound::Replace(CYContext 
&context
) { 
 152     context
.ReplaceAll(expressions_
); 
 153     if (expressions_ 
== NULL
) 
 158 CYExpression 
*CYCompound::Primitive(CYContext 
&context
) { 
 159     CYExpression 
*expression(expressions_
); 
 160     if (expression 
== NULL
) 
 162     while (expression
->next_ 
!= NULL
) 
 163         expression 
= expression
->next_
; 
 164     return expression
->Primitive(context
); 
 167 CYFunctionParameter 
*CYComprehension::Parameters(CYContext 
&context
) const { $
T(NULL
) 
 168     CYFunctionParameter 
*next(next_
->Parameters(context
)); 
 169     if (CYFunctionParameter 
*parameter 
= Parameter(context
)) { 
 170         parameter
->SetNext(next
); 
 176 CYStatement 
*CYComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 177     return next_ 
== NULL 
? statement 
: next_
->Replace(context
, statement
); 
 180 CYExpression 
*CYCondition::Replace(CYContext 
&context
) { 
 181     context
.Replace(test_
); 
 182     context
.Replace(true_
); 
 183     context
.Replace(false_
); 
 187 void CYContext::NonLocal(CYStatement 
*&statements
) { 
 188     CYContext 
&context(*this); 
 190     if (nextlocal_ 
!= NULL 
&& nextlocal_
->identifier_ 
!= NULL
) { 
 191         CYIdentifier 
*cye($
I("$cye")->Replace(context
)); 
 192         CYIdentifier 
*unique(nextlocal_
->identifier_
->Replace(context
)); 
 194         CYStatement 
*declare( 
 195             $ 
CYVar($
L1($ 
CYDeclaration(unique
, $ 
CYObject())))); 
 197         cy::Syntax::Catch 
*rescue( 
 198             $ 
cy::Syntax::Catch(cye
, $$
->* 
 199                 $ 
CYIf($ 
CYIdentical($
M($
V(cye
), $
S("$cyk")), $
V(unique
)), $$
->* 
 200                     $ 
CYReturn($
M($
V(cye
), $
S("$cyv"))))->* 
 201                 $ 
cy::Syntax::Throw($
V(cye
)))); 
 203         context
.Replace(declare
); 
 204         rescue
->Replace(context
); 
 208             $ 
cy::Syntax::Try(statements
, rescue
, NULL
); 
 212 CYIdentifier 
*CYContext::Unique() { 
 213     return $ 
CYIdentifier(apr_psprintf($pool
, "$cy%u", unique_
++)); 
 216 CYStatement 
*CYContinue::Replace(CYContext 
&context
) { 
 220 CYStatement 
*CYDebugger::Replace(CYContext 
&context
) { 
 224 CYAssignment 
*CYDeclaration::Assignment(CYContext 
&context
) { 
 225     if (initialiser_ 
== NULL
) 
 228     CYAssignment 
*value($ 
CYAssign(Variable(context
), initialiser_
)); 
 233 CYVariable 
*CYDeclaration::Variable(CYContext 
&context
) { 
 234     return $
V(identifier_
); 
 237 CYStatement 
*CYDeclaration::ForEachIn(CYContext 
&context
, CYExpression 
*value
) { 
 238     return $ 
CYVar($
L1($ 
CYDeclaration(identifier_
, value
))); 
 241 CYExpression 
*CYDeclaration::Replace(CYContext 
&context
) { 
 242     context
.Replace(identifier_
); 
 243     context
.scope_
->Declare(context
, identifier_
, CYIdentifierVariable
); 
 244     return Variable(context
); 
 247 void CYDeclarations::Replace(CYContext 
&context
) { $
T() 
 248     declaration_
->Replace(context
); 
 249     next_
->Replace(context
); 
 252 CYProperty 
*CYDeclarations::Property(CYContext 
&context
) { $
T(NULL
) 
 253     return $ 
CYProperty(declaration_
->identifier_
, declaration_
->initialiser_
, next_
->Property(context
)); 
 256 CYFunctionParameter 
*CYDeclarations::Parameter(CYContext 
&context
) { $
T(NULL
) 
 257     return $ 
CYFunctionParameter($ 
CYDeclaration(declaration_
->identifier_
), next_
->Parameter(context
)); 
 260 CYArgument 
*CYDeclarations::Argument(CYContext 
&context
) { $
T(NULL
) 
 261     return $ 
CYArgument(declaration_
->initialiser_
, next_
->Argument(context
)); 
 264 CYCompound 
*CYDeclarations::Compound(CYContext 
&context
) { $
T(NULL
) 
 265     CYCompound 
*compound(next_
->Compound(context
) ?: $ 
CYCompound()); 
 266     if (CYAssignment 
*assignment 
= declaration_
->Assignment(context
)) 
 267         compound
->AddPrev(assignment
); 
 271 CYExpression 
*CYDirectMember::Replace(CYContext 
&context
) { 
 272     context
.Replace(object_
); 
 273     context
.Replace(property_
); 
 277 CYStatement 
*CYDoWhile::Replace(CYContext 
&context
) { 
 278     context
.Replace(test_
); 
 279     context
.Replace(code_
); 
 283 void CYElement::Replace(CYContext 
&context
) { $
T() 
 284     context
.Replace(value_
); 
 285     next_
->Replace(context
); 
 288 CYStatement 
*CYEmpty::Replace(CYContext 
&context
) { 
 292 CYStatement 
*CYExpress::Replace(CYContext 
&context
) { 
 293     while (CYExpress 
*express 
= dynamic_cast<CYExpress 
*>(next_
)) { 
 294         CYCompound 
*compound(dynamic_cast<CYCompound 
*>(express
->expression_
)); 
 295         if (compound 
== NULL
) 
 296             compound 
= $ 
CYCompound(express
->expression_
); 
 297         compound
->AddPrev(expression_
); 
 298         expression_ 
= compound
; 
 299         SetNext(express
->next_
); 
 302     context
.Replace(expression_
); 
 303     if (expression_ 
== NULL
) 
 309 CYExpression 
*CYExpression::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 310     return $
C1(this, value
); 
 313 CYExpression 
*CYExpression::ClassName(CYContext 
&context
, bool object
) { 
 317 CYStatement 
*CYExpression::ForEachIn(CYContext 
&context
, CYExpression 
*value
) { 
 318     return $
E($ 
CYAssign(this, value
)); 
 321 CYAssignment 
*CYExpression::Assignment(CYContext 
&context
) { 
 325 CYNumber 
*CYFalse::Number(CYContext 
&context
) { 
 329 CYString 
*CYFalse::String(CYContext 
&context
) { 
 333 void CYFinally::Replace(CYContext 
&context
) { $
T() 
 334     code_
.Replace(context
); 
 337 CYStatement 
*CYFor::Replace(CYContext 
&context
) { 
 338     context
.Replace(initialiser_
); 
 339     context
.Replace(test_
); 
 340     context
.Replace(increment_
); 
 341     context
.Replace(code_
); 
 345 CYCompound 
*CYForDeclarations::Replace(CYContext 
&context
) { 
 346     declarations_
->Replace(context
); 
 347     return declarations_
->Compound(context
); 
 350 // XXX: this still feels highly suboptimal 
 351 CYStatement 
*CYForIn::Replace(CYContext 
&context
) { 
 352     if (CYAssignment 
*assignment 
= initialiser_
->Assignment(context
)) 
 353         return $ 
CYBlock($$
->* 
 358     context
.Replace(initialiser_
); 
 359     context
.Replace(set_
); 
 360     context
.Replace(code_
); 
 364 CYFunctionParameter 
*CYForInComprehension::Parameter(CYContext 
&context
) const { 
 365     return $ 
CYFunctionParameter($ 
CYDeclaration(name_
)); 
 368 CYStatement 
*CYForInComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 369     return $ 
CYForIn($
V(name_
), set_
, CYComprehension::Replace(context
, statement
)); 
 372 CYStatement 
*CYForOf::Replace(CYContext 
&context
) { 
 373     if (CYAssignment 
*assignment 
= initialiser_
->Assignment(context
)) 
 374         return $ 
CYBlock($$
->* 
 379     CYIdentifier 
*cys($
I("$cys")), *cyt($
I("$cyt")); 
 381     return $ 
CYLetStatement($
L2($ 
CYDeclaration(cys
, set_
), $ 
CYDeclaration(cyt
)), $$
->* 
 382         $ 
CYForIn($
V(cyt
), $
V(cys
), $ 
CYBlock($$
->* 
 383             initialiser_
->ForEachIn(context
, $
M($
V(cys
), $
V(cyt
)))->* 
 389 CYFunctionParameter 
*CYForOfComprehension::Parameter(CYContext 
&context
) const { 
 390     return $ 
CYFunctionParameter($ 
CYDeclaration(name_
)); 
 393 CYStatement 
*CYForOfComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 394     CYIdentifier 
*cys($
I("cys")); 
 396     return $
E($
C0($
F(NULL
, $
P1($
L("$cys")), $$
->* 
 397         $
E($ 
CYAssign($
V(cys
), set_
))->* 
 398         $ 
CYForIn($
V(name_
), $
V(cys
), $ 
CYBlock($$
->* 
 399             $
E($ 
CYAssign($
V(name_
), $
M($
V(cys
), $
V(name_
))))->* 
 400             CYComprehension::Replace(context
, statement
) 
 405 void CYFunction::Inject(CYContext 
&context
) { 
 406     context
.Replace(name_
); 
 407     context
.scope_
->Declare(context
, name_
, CYIdentifierOther
); 
 410 void CYFunction::Replace_(CYContext 
&context
, bool outer
) { 
 414     CYNonLocal 
*nonlocal(context
.nonlocal_
); 
 415     CYNonLocal 
*nextlocal(context
.nextlocal_
); 
 418     if (nonlocal_ 
!= NULL
) { 
 420         context
.nonlocal_ 
= nonlocal_
; 
 423         nonlocal_ 
= $ 
CYNonLocal(); 
 424         context
.nextlocal_ 
= nonlocal_
; 
 427     CYScope 
scope(!localize
, context
, code_
.statements_
); 
 429     if (!outer 
&& name_ 
!= NULL
) 
 432     parameters_
->Replace(context
, code_
); 
 433     code_
.Replace(context
); 
 436         context
.NonLocal(code_
.statements_
); 
 438     context
.nextlocal_ 
= nextlocal
; 
 439     context
.nonlocal_ 
= nonlocal
; 
 444 CYExpression 
*CYFunctionExpression::Replace(CYContext 
&context
) { 
 445     Replace_(context
, false); 
 449 void CYFunctionParameter::Replace(CYContext 
&context
, CYBlock 
&code
) { $
T() 
 450     CYAssignment 
*assignment(initialiser_
->Assignment(context
)); 
 451     context
.Replace(initialiser_
); 
 453     next_
->Replace(context
, code
); 
 455     if (assignment 
!= NULL
) 
 456         // XXX: this cast is quite incorrect 
 457         code
.AddPrev($ 
CYIf($ 
CYIdentical($ 
CYTypeOf(dynamic_cast<CYExpression 
*>(initialiser_
)), $
S("undefined")), $$
->* 
 462 CYStatement 
*CYFunctionStatement::Replace(CYContext 
&context
) { 
 463     Replace_(context
, true); 
 467 CYIdentifier 
*CYIdentifier::Replace(CYContext 
&context
) { 
 468     if (replace_ 
!= NULL 
&& replace_ 
!= this) 
 469         return replace_
->Replace(context
); 
 470     replace_ 
= context
.scope_
->Lookup(context
, this); 
 474 CYStatement 
*CYIf::Replace(CYContext 
&context
) { 
 475     context
.Replace(test_
); 
 476     context
.Replace(true_
); 
 477     context
.Replace(false_
); 
 481 CYFunctionParameter 
*CYIfComprehension::Parameter(CYContext 
&context
) const { 
 485 CYStatement 
*CYIfComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 486     return $ 
CYIf(test_
, CYComprehension::Replace(context
, statement
)); 
 489 CYExpression 
*CYIndirect::Replace(CYContext 
&context
) { 
 490     return $
M(rhs_
, $
S("$cyi")); 
 493 CYExpression 
*CYIndirectMember::Replace(CYContext 
&context
) { 
 494     return $
M($ 
CYIndirect(object_
), property_
); 
 497 CYExpression 
*CYInfix::Replace(CYContext 
&context
) { 
 498     context
.Replace(lhs_
); 
 499     context
.Replace(rhs_
); 
 503 CYStatement 
*CYLabel::Replace(CYContext 
&context
) { 
 504     context
.Replace(statement_
); 
 508 CYStatement 
*CYLetStatement::Replace(CYContext 
&context
) { 
 509     return $
E($ 
CYCall(CYNonLocalize(context
, $ 
CYFunctionExpression(NULL
, declarations_
->Parameter(context
), code_
)), declarations_
->Argument(context
))); 
 515 CYExpression 
*New::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 516     CYLast(arguments_
) = $ 
CYArgument(value
); 
 520 CYExpression 
*New::Replace(CYContext 
&context
) { 
 521     context
.Replace(constructor_
); 
 522     arguments_
->Replace(context
); 
 528 CYNumber 
*CYNull::Number(CYContext 
&context
) { 
 532 CYString 
*CYNull::String(CYContext 
&context
) { 
 536 CYNumber 
*CYNumber::Number(CYContext 
&context
) { 
 540 CYString 
*CYNumber::String(CYContext 
&context
) { 
 541     // XXX: there is a precise algorithm for this 
 542     return $
S(apr_psprintf($pool
, "%.17g", Value())); 
 545 CYExpression 
*CYObject::Replace(CYContext 
&context
) { 
 546     properties_
->Replace(context
); 
 550 CYExpression 
*CYPostfix::Replace(CYContext 
&context
) { 
 551     context
.Replace(lhs_
); 
 555 CYExpression 
*CYPrefix::Replace(CYContext 
&context
) { 
 556     context
.Replace(rhs_
); 
 560 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe! 
 561 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ" 
 562 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_" 
 565     struct IdentifierUsageLess 
: 
 566         std::binary_function
<CYIdentifier 
*, CYIdentifier 
*, bool> 
 568         _finline 
bool operator ()(CYIdentifier 
*lhs
, CYIdentifier 
*rhs
) const { 
 569             if (lhs
->usage_ 
!= rhs
->usage_
) 
 570                 return lhs
->usage_ 
> rhs
->usage_
; 
 575     typedef std::set
<CYIdentifier 
*, IdentifierUsageLess
> IdentifierUsages
; 
 578 void CYProgram::Replace(CYContext 
&context
) { 
 579     CYScope 
scope(true, context
, statements_
); 
 581     context
.nextlocal_ 
= $ 
CYNonLocal(); 
 582     context
.ReplaceAll(statements_
); 
 583     context
.NonLocal(statements_
); 
 589     CYCStringSet external
; 
 590     for (CYIdentifierValueSet::const_iterator 
i(scope
.identifiers_
.begin()); i 
!= scope
.identifiers_
.end(); ++i
) 
 591         external
.insert((*i
)->Word()); 
 593     IdentifierUsages usages
; 
 595     if (offset 
< context
.rename_
.size()) 
 596         CYForEach (i
, context
.rename_
[offset
].identifier_
) 
 599     // XXX: totalling the probable occurrences and sorting by them would improve the result 
 600     for (CYIdentifierUsageVector::const_iterator 
i(context
.rename_
.begin()); i 
!= context
.rename_
.end(); ++i
, ++offset
) { 
 601         //std::cout << *i << ":" << (*i)->offset_ << std::endl; 
 605         if (context
.options_
.verbose_
) 
 606             name 
= apr_psprintf($pool
, "$%"APR_SIZE_T_FMT
"", offset
); 
 612             unsigned position(7), local(offset 
+ 1); 
 615                 unsigned index(local 
% (sizeof(MappingSet
) - 1)); 
 616                 local 
/= sizeof(MappingSet
) - 1; 
 617                 id
[--position
] = MappingSet
[index
]; 
 618             } while (local 
!= 0); 
 620             if (external
.find(id 
+ position
) != external
.end()) { 
 625             name 
= apr_pstrmemdup($pool
, id 
+ position
, 7 - position
); 
 626             // XXX: at some point, this could become a keyword 
 629         CYForEach (identifier
, i
->identifier_
) 
 630             identifier
->Set(name
); 
 634 void CYProperty::Replace(CYContext 
&context
) { $
T() 
 635     context
.Replace(value_
); 
 636     next_
->Replace(context
); 
 641 CYStatement 
*CYReturn::Replace(CYContext 
&context
) { 
 642     if (context
.nonlocal_ 
!= NULL
) { 
 643         CYProperty 
*value(value_ 
== NULL 
? NULL 
: $ 
CYProperty($
S("$cyv"), value_
)); 
 644         return $ 
cy::Syntax::Throw($ 
CYObject( 
 645             $ 
CYProperty($
S("$cyk"), $
V(context
.nonlocal_
->Target(context
)), value
) 
 649     context
.Replace(value_
); 
 653 CYExpression 
*CYRubyBlock::Replace(CYContext 
&context
) { 
 654     // XXX: this needs to do something much more epic to handle return 
 655     return call_
->AddArgument(context
, proc_
->Replace(context
)); 
 658 CYExpression 
*CYRubyProc::Replace(CYContext 
&context
) { 
 659     return CYNonLocalize(context
, $ 
CYFunctionExpression(NULL
, parameters_
, code_
)); 
 662 CYScope::CYScope(bool transparent
, CYContext 
&context
, CYStatement 
*&statements
) : 
 663     transparent_(transparent
), 
 665     statements_(statements
), 
 666     parent_(context
.scope_
) 
 668     context_
.scope_ 
= this; 
 671 CYScope::~CYScope() { 
 674 void CYScope::Close() { 
 675     context_
.scope_ 
= parent_
; 
 676     Scope(context_
, statements_
); 
 679 void CYScope::Declare(CYContext 
&context
, CYIdentifier 
*identifier
, CYIdentifierFlags flags
) { 
 680     if (!transparent_ 
|| flags 
== CYIdentifierArgument 
|| flags 
== CYIdentifierCatch
) 
 681         internal_
.insert(CYIdentifierAddressFlagsMap::value_type(identifier
, flags
)); 
 682     else if (parent_ 
!= NULL
) 
 683         parent_
->Declare(context
, identifier
, flags
); 
 686 CYIdentifier 
*CYScope::Lookup(CYContext 
&context
, CYIdentifier 
*identifier
) { 
 687     std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
)); 
 688     return *insert
.first
; 
 691 void CYScope::Merge(CYContext 
&context
, CYIdentifier 
*identifier
) { 
 692     std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
)); 
 693     if (!insert
.second
) { 
 694         if ((*insert
.first
)->offset_ 
< identifier
->offset_
) 
 695             (*insert
.first
)->offset_ 
= identifier
->offset_
; 
 696         identifier
->replace_ 
= *insert
.first
; 
 697         (*insert
.first
)->usage_ 
+= identifier
->usage_ 
+ 1; 
 702     struct IdentifierOffset 
{ 
 704         CYIdentifierFlags flags_
; 
 706         CYIdentifier 
*identifier_
; 
 708         IdentifierOffset(CYIdentifier 
*identifier
, CYIdentifierFlags flags
) : 
 709             offset_(identifier
->offset_
), 
 711             usage_(identifier
->usage_
), 
 712             identifier_(identifier
) 
 717     struct IdentifierOffsetLess 
: 
 718         std::binary_function
<const IdentifierOffset 
&, const IdentifierOffset 
&, bool> 
 720         _finline 
bool operator ()(const IdentifierOffset 
&lhs
, const IdentifierOffset 
&rhs
) const { 
 721             if (lhs
.offset_ 
!= rhs
.offset_
) 
 722                 return lhs
.offset_ 
< rhs
.offset_
; 
 723             if (lhs
.flags_ 
!= rhs
.flags_
) 
 724                 return lhs
.flags_ 
< rhs
.flags_
; 
 725             /*if (lhs.usage_ != rhs.usage_) 
 726                 return lhs.usage_ < rhs.usage_;*/ 
 727             return lhs
.identifier_ 
< rhs
.identifier_
; 
 731     typedef std::set
<IdentifierOffset
, IdentifierOffsetLess
> IdentifierOffsets
; 
 734 void CYScope::Scope(CYContext 
&context
, CYStatement 
*&statements
) { 
 738     CYDeclarations 
*last(NULL
), *curr(NULL
); 
 740     IdentifierOffsets offsets
; 
 742     for (CYIdentifierAddressFlagsMap::const_iterator 
i(internal_
.begin()); i 
!= internal_
.end(); ++i
) 
 743         if (i
->second 
!= CYIdentifierMagic
) 
 744             offsets
.insert(IdentifierOffset(i
->first
, i
->second
)); 
 748     for (IdentifierOffsets::const_iterator 
i(offsets
.begin()); i 
!= offsets
.end(); ++i
) { 
 749         if (i
->flags_ 
== CYIdentifierVariable
) { 
 750             CYDeclarations 
*next($ 
CYDeclarations($ 
CYDeclaration(i
->identifier_
))); 
 758         if (offset 
< i
->offset_
) 
 760         if (context
.rename_
.size() <= offset
) 
 761             context
.rename_
.resize(offset 
+ 1); 
 763         CYIdentifierUsage 
&rename(context
.rename_
[offset
++]); 
 764         i
->identifier_
->SetNext(rename
.identifier_
); 
 765         rename
.identifier_ 
= i
->identifier_
; 
 766         rename
.usage_ 
+= i
->identifier_
->usage_ 
+ 1; 
 770         CYVar 
*var($ 
CYVar(last
)); 
 771         var
->SetNext(statements
); 
 775     for (CYIdentifierValueSet::const_iterator 
i(identifiers_
.begin()); i 
!= identifiers_
.end(); ++i
) 
 776         if (internal_
.find(*i
) == internal_
.end()) { 
 777             //std::cout << *i << '=' << offset << std::endl; 
 778             if ((*i
)->offset_ 
< offset
) 
 779                 (*i
)->offset_ 
= offset
; 
 780             parent_
->Merge(context
, *i
); 
 784 CYString 
*CYString::Concat(CYContext 
&context
, CYString 
*rhs
) const { 
 785     size_t size(size_ 
+ rhs
->size_
); 
 786     char *value($ 
char[size 
+ 1]); 
 787     memcpy(value
, value_
, size_
); 
 788     memcpy(value 
+ size_
, rhs
->value_
, rhs
->size_
); 
 790     return $
S(value
, size
); 
 793 CYNumber 
*CYString::Number(CYContext 
&context
) { 
 794     // XXX: there is a precise algorithm for this 
 798 CYString 
*CYString::String(CYContext 
&context
) { 
 802 CYStatement 
*CYSwitch::Replace(CYContext 
&context
) { 
 803     context
.Replace(value_
); 
 804     clauses_
->Replace(context
); 
 808 CYExpression 
*CYThis::Replace(CYContext 
&context
) { 
 815 CYStatement 
*Throw::Replace(CYContext 
&context
) { 
 816     context
.Replace(value_
); 
 822 CYExpression 
*CYTrivial::Replace(CYContext 
&context
) { 
 826 CYNumber 
*CYTrue::Number(CYContext 
&context
) { 
 830 CYString 
*CYTrue::String(CYContext 
&context
) { 
 837 CYStatement 
*Try::Replace(CYContext 
&context
) { 
 838     code_
.Replace(context
); 
 839     catch_
->Replace(context
); 
 840     finally_
->Replace(context
); 
 846 CYStatement 
*CYVar::Replace(CYContext 
&context
) { 
 847     declarations_
->Replace(context
); 
 848     return $
E(declarations_
->Compound(context
)); 
 851 CYExpression 
*CYVariable::Replace(CYContext 
&context
) { 
 852     context
.Replace(name_
); 
 856 CYStatement 
*CYWhile::Replace(CYContext 
&context
) { 
 857     context
.Replace(test_
); 
 858     context
.Replace(code_
); 
 862 CYStatement 
*CYWith::Replace(CYContext 
&context
) { 
 863     context
.Replace(scope_
); 
 864     context
.Replace(code_
); 
 868 CYExpression 
*CYWord::ClassName(CYContext 
&context
, bool object
) { 
 869     CYString 
*name($
S(this)); 
 871         return $
C1($
V("objc_getClass"), name
);