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($
V(cye
), $
S("$cyk")), $
V(unique
)), $$
->* 
 194                     $ 
CYReturn($
M($
V(cye
), $
S("$cyv"))))->* 
 195                 $ 
cy::Syntax::Throw($
V(cye
)))); 
 197         declare 
= declare
->Replace(context
); 
 198         rescue
->Replace(context
); 
 202             $ 
cy::Syntax::Try(statements
, rescue
, NULL
); 
 206 CYIdentifier 
*CYContext::Unique() { 
 207     return $ 
CYIdentifier(apr_psprintf($pool
, "$cy%u", unique_
++)); 
 210 CYStatement 
*CYContinue::Replace(CYContext 
&context
) { 
 214 CYAssignment 
*CYDeclaration::Assignment(CYContext 
&context
) { 
 215     CYExpression 
*variable(Replace(context
)); 
 216     return initialiser_ 
== NULL 
? NULL 
: $ 
CYAssign(variable
, initialiser_
); 
 219 CYExpression 
*CYDeclaration::ForEachIn(CYContext 
&context
) { 
 220     return $
V(identifier_
); 
 223 CYExpression 
*CYDeclaration::Replace(CYContext 
&context
) { 
 224     context
.Replace(identifier_
); 
 225     context
.scope_
->Declare(context
, identifier_
, CYIdentifierVariable
); 
 226     return $
V(identifier_
); 
 229 CYProperty 
*CYDeclarations::Property(CYContext 
&context
) { $
T(NULL
) 
 230     return $ 
CYProperty(declaration_
->identifier_
, declaration_
->initialiser_ 
?: $U
, next_
->Property(context
)); 
 233 CYCompound 
*CYDeclarations::Replace(CYContext 
&context
) { 
 234     CYCompound 
*compound
; 
 235     if (next_ 
== NULL
) compound
: 
 236         compound 
= $ 
CYCompound(); 
 238         compound 
= next_
->Replace(context
); 
 239         if (compound 
== NULL
) 
 243     if (CYAssignment 
*assignment 
= declaration_
->Assignment(context
)) 
 244         compound
->AddPrev(assignment
); 
 248 CYExpression 
*CYDirectMember::Replace(CYContext 
&context
) { 
 253 CYStatement 
*CYDoWhile::Replace(CYContext 
&context
) { 
 254     context
.Replace(test_
); 
 255     context
.Replace(code_
); 
 259 void CYElement::Replace(CYContext 
&context
) { $
T() 
 260     context
.Replace(value_
); 
 261     next_
->Replace(context
); 
 264 CYStatement 
*CYEmpty::Collapse(CYContext 
&context
) { 
 268 CYStatement 
*CYEmpty::Replace(CYContext 
&context
) { 
 272 CYStatement 
*CYExpress::Collapse(CYContext 
&context
) { 
 273     if (CYExpress 
*express 
= dynamic_cast<CYExpress 
*>(next_
)) { 
 274         CYCompound 
*next(dynamic_cast<CYCompound 
*>(express
->expression_
)); 
 276             next 
= $ 
CYCompound(express
->expression_
); 
 277         next
->AddPrev(expression_
); 
 279         SetNext(express
->next_
); 
 285 CYStatement 
*CYExpress::Replace(CYContext 
&context
) { 
 286     context
.Replace(expression_
); 
 287     if (expression_ 
== NULL
) 
 292 CYExpression 
*CYExpression::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 293     return $
C1(this, value
); 
 296 CYExpression 
*CYExpression::ClassName(CYContext 
&context
, bool object
) { 
 300 CYExpression 
*CYExpression::ForEachIn(CYContext 
&context
) { 
 304 CYExpression 
*CYExpression::ReplaceAll(CYContext 
&context
) { $
T(NULL
) 
 305     CYExpression 
*replace(this); 
 306     context
.Replace(replace
); 
 308     if (CYExpression 
*next 
= next_
->ReplaceAll(context
)) 
 309         replace
->SetNext(next
); 
 311         replace
->SetNext(next_
); 
 316 CYNumber 
*CYFalse::Number(CYContext 
&context
) { 
 320 CYString 
*CYFalse::String(CYContext 
&context
) { 
 324 void CYFinally::Replace(CYContext 
&context
) { $
T() 
 325     code_
.Replace(context
); 
 328 CYStatement 
*CYFor::Replace(CYContext 
&context
) { 
 329     context
.Replace(initialiser_
); 
 330     context
.Replace(test_
); 
 331     context
.Replace(increment_
); 
 332     context
.Replace(code_
); 
 336 CYStatement 
*CYForIn::Replace(CYContext 
&context
) { 
 337     // XXX: this actually might need a prefix statement 
 338     context
.Replace(initialiser_
); 
 339     context
.Replace(set_
); 
 340     context
.Replace(code_
); 
 344 CYFunctionParameter 
*CYForInComprehension::Parameter(CYContext 
&context
) const { 
 345     return $ 
CYFunctionParameter(name_
); 
 348 CYStatement 
*CYForInComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 349     return $ 
CYForIn($
V(name_
), set_
, CYComprehension::Replace(context
, statement
)); 
 352 CYStatement 
*CYForEachIn::Replace(CYContext 
&context
) { 
 353     CYIdentifier 
*cys($
I("$cys")), *cyt($
I("$cyt")); 
 355     return $ 
CYLet($
L2($
L(cys
, set_
), $
L(cyt
)), $$
->* 
 356         $ 
CYForIn($
V(cyt
), $
V(cys
), $ 
CYBlock($$
->* 
 357             $
E($ 
CYAssign(initialiser_
->ForEachIn(context
), $
M($
V(cys
), $
V(cyt
))))->* 
 363 CYFunctionParameter 
*CYForEachInComprehension::Parameter(CYContext 
&context
) const { 
 364     return $ 
CYFunctionParameter(name_
); 
 367 CYStatement 
*CYForEachInComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 368     CYIdentifier 
*cys($
I("cys")); 
 370     return $
E($
C0($
F(NULL
, $
P1("$cys"), $$
->* 
 371         $
E($ 
CYAssign($
V(cys
), set_
))->* 
 372         $ 
CYForIn($
V(name_
), $
V(cys
), $ 
CYBlock($$
->* 
 373             $
E($ 
CYAssign($
V(name_
), $
M($
V(cys
), $
V(name_
))))->* 
 374             CYComprehension::Replace(context
, statement
) 
 379 void CYFunction::Inject(CYContext 
&context
) { 
 380     context
.Replace(name_
); 
 381     context
.scope_
->Declare(context
, name_
, CYIdentifierOther
); 
 384 void CYFunction::Replace_(CYContext 
&context
, bool outer
) { 
 388     CYScope 
scope(CYScopeFunction
, context
, code_
.statements_
); 
 390     CYNonLocal 
*nonlocal(context
.nonlocal_
); 
 391     CYNonLocal 
*nextlocal(context
.nextlocal_
); 
 394     if (nonlocal_ 
!= NULL
) { 
 396         context
.nonlocal_ 
= nonlocal_
; 
 399         nonlocal_ 
= $ 
CYNonLocal(); 
 400         context
.nextlocal_ 
= nonlocal_
; 
 403     if (!outer 
&& name_ 
!= NULL
) 
 406     if (parameters_ 
!= NULL
) 
 407         parameters_ 
= parameters_
->Replace(context
, code_
); 
 409     code_
.Replace(context
); 
 412         context
.NonLocal(code_
.statements_
); 
 414     context
.nextlocal_ 
= nextlocal
; 
 415     context
.nonlocal_ 
= nonlocal
; 
 420 CYExpression 
*CYFunctionExpression::Replace(CYContext 
&context
) { 
 421     Replace_(context
, false); 
 425 CYFunctionParameter 
*CYFunctionParameter::Replace(CYContext 
&context
, CYBlock 
&code
) { 
 426     name_ 
= name_
->Replace(context
); 
 427     context
.scope_
->Declare(context
, name_
, CYIdentifierArgument
); 
 429         next_ 
= next_
->Replace(context
, code
); 
 433 CYStatement 
*CYFunctionStatement::Replace(CYContext 
&context
) { 
 434     Replace_(context
, true); 
 438 CYIdentifier 
*CYIdentifier::Replace(CYContext 
&context
) { 
 439     if (replace_ 
!= NULL 
&& replace_ 
!= this) 
 440         return replace_
->Replace(context
); 
 441     replace_ 
= context
.scope_
->Lookup(context
, this); 
 445 CYStatement 
*CYIf::Replace(CYContext 
&context
) { 
 446     context
.Replace(test_
); 
 447     context
.Replace(true_
); 
 448     context
.Replace(false_
); 
 452 CYFunctionParameter 
*CYIfComprehension::Parameter(CYContext 
&context
) const { 
 456 CYStatement 
*CYIfComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 457     return $ 
CYIf(test_
, CYComprehension::Replace(context
, statement
)); 
 460 CYExpression 
*CYIndirect::Replace(CYContext 
&context
) { 
 461     CYPrefix::Replace(context
); 
 462     return $
M(rhs_
, $
S("$cyi")); 
 465 CYExpression 
*CYIndirectMember::Replace(CYContext 
&context
) { 
 467     return $
M($ 
CYIndirect(object_
), property_
); 
 470 CYExpression 
*CYInfix::Replace(CYContext 
&context
) { 
 471     context
.Replace(lhs_
); 
 472     context
.Replace(rhs_
); 
 476 CYStatement 
*CYLabel::Replace(CYContext 
&context
) { 
 477     context
.Replace(statement_
); 
 481 CYStatement 
*CYLet::Replace(CYContext 
&context
) { 
 482     return $ 
CYWith($ 
CYObject(declarations_
->Property(context
)), &code_
); 
 485 void CYMember::Replace_(CYContext 
&context
) { 
 486     context
.Replace(object_
); 
 487     context
.Replace(property_
); 
 493 CYExpression 
*New::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 494     CYArgument 
**argument(&arguments_
); 
 495     while (*argument 
!= NULL
) 
 496         argument 
= &(*argument
)->next_
; 
 497     *argument 
= $ 
CYArgument(value
); 
 501 CYExpression 
*New::Replace(CYContext 
&context
) { 
 502     context
.Replace(constructor_
); 
 503     arguments_
->Replace(context
); 
 509 CYNumber 
*CYNull::Number(CYContext 
&context
) { 
 513 CYString 
*CYNull::String(CYContext 
&context
) { 
 517 CYNumber 
*CYNumber::Number(CYContext 
&context
) { 
 521 CYString 
*CYNumber::String(CYContext 
&context
) { 
 522     // XXX: there is a precise algorithm for this 
 523     return $
S(apr_psprintf($pool
, "%.17g", Value())); 
 526 CYExpression 
*CYObject::Replace(CYContext 
&context
) { 
 527     properties_
->Replace(context
); 
 531 CYFunctionParameter 
*CYOptionalFunctionParameter::Replace(CYContext 
&context
, CYBlock 
&code
) { 
 532     CYFunctionParameter 
*parameter($ 
CYFunctionParameter(name_
, next_
)); 
 533     parameter 
= parameter
->Replace(context
, code
); 
 534     initializer_ 
= initializer_
->Replace(context
); 
 536     CYVariable 
*name($
V(name_
)); 
 537     code
.AddPrev($ 
CYIf($ 
CYIdentical($ 
CYTypeOf(name
), $
S("undefined")), $$
->* 
 538         $
E($ 
CYAssign(name
, initializer_
)) 
 544 CYExpression 
*CYPostfix::Replace(CYContext 
&context
) { 
 545     context
.Replace(lhs_
); 
 549 CYExpression 
*CYPrefix::Replace(CYContext 
&context
) { 
 550     context
.Replace(rhs_
); 
 554 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe! 
 555 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ" 
 556 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_" 
 559     struct IdentifierUsageLess 
: 
 560         std::binary_function
<CYIdentifier 
*, CYIdentifier 
*, bool> 
 562         _finline 
bool operator ()(CYIdentifier 
*lhs
, CYIdentifier 
*rhs
) const { 
 563             if (lhs
->usage_ 
!= rhs
->usage_
) 
 564                 return lhs
->usage_ 
> rhs
->usage_
; 
 569     typedef std::set
<CYIdentifier 
*, IdentifierUsageLess
> IdentifierUsages
; 
 572 void CYProgram::Replace(CYContext 
&context
) { 
 573     CYScope 
scope(CYScopeProgram
, context
, statements_
); 
 575     context
.nextlocal_ 
= $ 
CYNonLocal(); 
 576     statements_ 
= statements_
->ReplaceAll(context
); 
 577     context
.NonLocal(statements_
); 
 583     CYCStringSet external
; 
 584     for (CYIdentifierValueSet::const_iterator 
i(scope
.identifiers_
.begin()); i 
!= scope
.identifiers_
.end(); ++i
) 
 585         external
.insert((*i
)->Word()); 
 587     IdentifierUsages usages
; 
 589     if (offset 
< context
.rename_
.size()) 
 590         for (CYIdentifier 
*i(context
.rename_
[offset
].identifier_
); i 
!= NULL
; i 
= i
->next_
) 
 593     // XXX: totalling the probable occurrences and sorting by them would improve the result 
 594     for (CYIdentifierUsageVector::const_iterator 
i(context
.rename_
.begin()); i 
!= context
.rename_
.end(); ++i
, ++offset
) { 
 595         //std::cout << *i << ":" << (*i)->offset_ << std::endl; 
 599         if (context
.options_
.verbose_
) 
 600             name 
= apr_psprintf($pool
, "$%"APR_SIZE_T_FMT
"", offset
); 
 606             unsigned position(7), local(offset 
+ 1); 
 609                 unsigned index(local 
% (sizeof(MappingSet
) - 1)); 
 610                 local 
/= sizeof(MappingSet
) - 1; 
 611                 id
[--position
] = MappingSet
[index
]; 
 612             } while (local 
!= 0); 
 614             if (external
.find(id 
+ position
) != external
.end()) { 
 619             name 
= apr_pstrmemdup($pool
, id 
+ position
, 7 - position
); 
 620             // XXX: at some point, this could become a keyword 
 623         for (CYIdentifier 
*identifier(i
->identifier_
); identifier 
!= NULL
; identifier 
= identifier
->next_
) 
 624             identifier
->Set(name
); 
 628 void CYProperty::Replace(CYContext 
&context
) { $
T() 
 629     context
.Replace(value_
); 
 630     next_
->Replace(context
); 
 633 CYStatement 
*CYReturn::Replace(CYContext 
&context
) { 
 634     if (context
.nonlocal_ 
!= NULL
) { 
 635         CYProperty 
*value(value_ 
== NULL 
? NULL 
: $ 
CYProperty($
S("$cyv"), value_
)); 
 636         return $ 
cy::Syntax::Throw($ 
CYObject( 
 637             $ 
CYProperty($
S("$cyk"), $
V(context
.nonlocal_
->Target(context
)), value
) 
 641     context
.Replace(value_
); 
 645 CYExpression 
*CYRubyBlock::Replace(CYContext 
&context
) { 
 646     // XXX: this needs to do something much more epic to handle return 
 647     return call_
->AddArgument(context
, proc_
->Replace(context
)); 
 650 CYExpression 
*CYRubyProc::Replace(CYContext 
&context
) { 
 651     CYFunctionExpression 
*function($ 
CYFunctionExpression(NULL
, parameters_
, code_
)); 
 652     function
->nonlocal_ 
= context
.nextlocal_
; 
 656 CYScope::CYScope(CYScopeType type
, CYContext 
&context
, CYStatement 
*&statements
) : 
 659     statements_(statements
), 
 660     parent_(context
.scope_
) 
 662     context_
.scope_ 
= this; 
 665 void CYScope::Close() { 
 666     context_
.scope_ 
= parent_
; 
 667     Scope(context_
, statements_
); 
 670 void CYScope::Declare(CYContext 
&context
, CYIdentifier 
*identifier
, CYIdentifierFlags flags
) { 
 671     if (type_ 
== CYScopeCatch 
&& flags 
!= CYIdentifierCatch
) 
 672         parent_
->Declare(context
, identifier
, flags
); 
 674         internal_
.insert(CYIdentifierAddressFlagsMap::value_type(identifier
, flags
)); 
 677 CYIdentifier 
*CYScope::Lookup(CYContext 
&context
, CYIdentifier 
*identifier
) { 
 678     std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
)); 
 679     return *insert
.first
; 
 682 void CYScope::Merge(CYContext 
&context
, CYIdentifier 
*identifier
) { 
 683     std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
)); 
 684     if (!insert
.second
) { 
 685         if ((*insert
.first
)->offset_ 
< identifier
->offset_
) 
 686             (*insert
.first
)->offset_ 
= identifier
->offset_
; 
 687         identifier
->replace_ 
= *insert
.first
; 
 688         (*insert
.first
)->usage_ 
+= identifier
->usage_ 
+ 1; 
 693     struct IdentifierOffset 
{ 
 695         CYIdentifierFlags flags_
; 
 697         CYIdentifier 
*identifier_
; 
 699         IdentifierOffset(CYIdentifier 
*identifier
, CYIdentifierFlags flags
) : 
 700             offset_(identifier
->offset_
), 
 702             usage_(identifier
->usage_
), 
 703             identifier_(identifier
) 
 708     struct IdentifierOffsetLess 
: 
 709         std::binary_function
<const IdentifierOffset 
&, const IdentifierOffset 
&, bool> 
 711         _finline 
bool operator ()(const IdentifierOffset 
&lhs
, const IdentifierOffset 
&rhs
) const { 
 712             if (lhs
.offset_ 
!= rhs
.offset_
) 
 713                 return lhs
.offset_ 
< rhs
.offset_
; 
 714             if (lhs
.flags_ 
!= rhs
.flags_
) 
 715                 return lhs
.flags_ 
< rhs
.flags_
; 
 716             /*if (lhs.usage_ != rhs.usage_) 
 717                 return lhs.usage_ < rhs.usage_;*/ 
 718             return lhs
.identifier_ 
< rhs
.identifier_
; 
 722     typedef std::set
<IdentifierOffset
, IdentifierOffsetLess
> IdentifierOffsets
; 
 725 void CYScope::Scope(CYContext 
&context
, CYStatement 
*&statements
) { 
 729     CYDeclarations 
*last(NULL
), *curr(NULL
); 
 731     IdentifierOffsets offsets
; 
 733     for (CYIdentifierAddressFlagsMap::const_iterator 
i(internal_
.begin()); i 
!= internal_
.end(); ++i
) 
 734         if (i
->second 
!= CYIdentifierMagic
) 
 735             offsets
.insert(IdentifierOffset(i
->first
, i
->second
)); 
 739     for (IdentifierOffsets::const_iterator 
i(offsets
.begin()); i 
!= offsets
.end(); ++i
) { 
 740         if (i
->flags_ 
== CYIdentifierVariable
) { 
 741             CYDeclarations 
*next($ 
CYDeclarations($ 
CYDeclaration(i
->identifier_
))); 
 749         if (offset 
< i
->offset_
) 
 751         if (context
.rename_
.size() <= offset
) 
 752             context
.rename_
.resize(offset 
+ 1); 
 754         CYIdentifierUsage 
&rename(context
.rename_
[offset
++]); 
 755         i
->identifier_
->SetNext(rename
.identifier_
); 
 756         rename
.identifier_ 
= i
->identifier_
; 
 757         rename
.usage_ 
+= i
->identifier_
->usage_ 
+ 1; 
 761         CYVar 
*var($ 
CYVar(last
)); 
 762         var
->SetNext(statements
); 
 766     for (CYIdentifierValueSet::const_iterator 
i(identifiers_
.begin()); i 
!= identifiers_
.end(); ++i
) 
 767         if (internal_
.find(*i
) == internal_
.end()) { 
 768             //std::cout << *i << '=' << offset << std::endl; 
 769             if ((*i
)->offset_ 
< offset
) 
 770                 (*i
)->offset_ 
= offset
; 
 771             parent_
->Merge(context
, *i
); 
 775 CYStatement 
*CYStatement::Collapse(CYContext 
&context
) { 
 779 CYStatement 
*CYStatement::ReplaceAll(CYContext 
&context
) { $
T(NULL
) 
 780     CYStatement 
*replace(this); 
 781     context
.Replace(replace
); 
 782     replace
->SetNext(next_
->ReplaceAll(context
)); 
 783     return replace
->Collapse(context
); 
 786 CYString 
*CYString::Concat(CYContext 
&context
, CYString 
*rhs
) const { 
 787     size_t size(size_ 
+ rhs
->size_
); 
 788     char *value($ 
char[size 
+ 1]); 
 789     memcpy(value
, value_
, size_
); 
 790     memcpy(value 
+ size_
, rhs
->value_
, rhs
->size_
); 
 792     return $
S(value
, size
); 
 795 CYNumber 
*CYString::Number(CYContext 
&context
) { 
 796     // XXX: there is a precise algorithm for this 
 800 CYString 
*CYString::String(CYContext 
&context
) { 
 804 CYStatement 
*CYSwitch::Replace(CYContext 
&context
) { 
 805     context
.Replace(value_
); 
 806     clauses_
->Replace(context
); 
 810 CYExpression 
*CYThis::Replace(CYContext 
&context
) { 
 817 CYStatement 
*Throw::Replace(CYContext 
&context
) { 
 818     context
.Replace(value_
); 
 824 CYExpression 
*CYTrivial::Replace(CYContext 
&context
) { 
 828 CYNumber 
*CYTrue::Number(CYContext 
&context
) { 
 832 CYString 
*CYTrue::String(CYContext 
&context
) { 
 839 CYStatement 
*Try::Replace(CYContext 
&context
) { 
 840     code_
.Replace(context
); 
 841     catch_
->Replace(context
); 
 842     finally_
->Replace(context
); 
 848 CYStatement 
*CYVar::Replace(CYContext 
&context
) { 
 849     return $
E(declarations_
->Replace(context
)); 
 852 CYExpression 
*CYVariable::Replace(CYContext 
&context
) { 
 853     name_ 
= name_
->Replace(context
); 
 857 CYStatement 
*CYWhile::Replace(CYContext 
&context
) { 
 858     context
.Replace(test_
); 
 859     context
.Replace(code_
); 
 863 CYStatement 
*CYWith::Replace(CYContext 
&context
) { 
 864     context
.Replace(scope_
); 
 865     context
.Replace(code_
); 
 869 CYExpression 
*CYWord::ClassName(CYContext 
&context
, bool object
) { 
 870     CYString 
*name($
S(this)); 
 872         return $
C1($
V("objc_getClass"), name
);