1 /* Cycript - Optimizing JavaScript Compiler/Runtime 
   2  * Copyright (C) 2009-2015  Jay Freeman (saurik) 
   5 /* GNU Affero General Public License, Version 3 {{{ */ 
   7  * This program is free software: you can redistribute it and/or modify 
   8  * it under the terms of the GNU Affero General Public License as published by 
   9  * the Free Software Foundation, either version 3 of the License, or 
  10  * (at your option) any later version. 
  12  * This program is distributed in the hope that it will be useful, 
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  * GNU Affero General Public License for more details. 
  17  * You should have received a copy of the GNU Affero General Public License 
  18  * along with this program.  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 static void CYImplicitReturn(CYStatement 
*&code
) { 
  33     if (CYStatement 
*&last 
= CYGetLast(code
)) 
  34         last 
= last
->Return(); 
  37 CYExpression 
*CYAdd::Replace(CYContext 
&context
) { 
  38     CYInfix::Replace(context
); 
  40     CYString 
*lhs(dynamic_cast<CYString 
*>(lhs_
)); 
  41     CYString 
*rhs(dynamic_cast<CYString 
*>(rhs_
)); 
  43     if (lhs 
!= NULL 
|| rhs 
!= NULL
) { 
  45             lhs 
= lhs_
->String(context
); 
  48         } else if (rhs 
== NULL
) { 
  49             rhs 
= rhs_
->String(context
); 
  54         return lhs
->Concat(context
, rhs
); 
  57     if (CYNumber 
*lhn 
= lhs_
->Number(context
)) 
  58         if (CYNumber 
*rhn 
= rhs_
->Number(context
)) 
  59             return $
D(lhn
->Value() + rhn
->Value()); 
  64 CYExpression 
*CYAddressOf::Replace(CYContext 
&context
) { 
  65     return $
C0($
M(rhs_
, $
S("$cya"))); 
  68 CYArgument 
*CYArgument::Replace(CYContext 
&context
) { $
T(NULL
) 
  69     context
.Replace(value_
); 
  70     next_ 
= next_
->Replace(context
); 
  82 CYExpression 
*CYArray::Replace(CYContext 
&context
) { 
  83     elements_
->Replace(context
); 
  87 CYExpression 
*CYArrayComprehension::Replace(CYContext 
&context
) { 
  88     CYVariable 
*cyv($
V("$cyv")); 
  90     return $
C0($
F(NULL
, $
P1($
L("$cyv"), comprehensions_
->Parameters(context
)), $$
->* 
  91         $
E($ 
CYAssign(cyv
, $ 
CYArray()))->* 
  92         comprehensions_
->Replace(context
, $
E($
C1($
M(cyv
, $
S("push")), expression_
)))->* 
  97 CYExpression 
*CYAssignment::Replace(CYContext 
&context
) { 
  98     context
.Replace(lhs_
); 
  99     context
.Replace(rhs_
); 
 103 CYStatement 
*CYBlock::Return() { 
 104     CYImplicitReturn(code_
); 
 108 CYStatement 
*CYBlock::Replace(CYContext 
&context
) { 
 109     context
.ReplaceAll(code_
); 
 115 CYStatement 
*CYBreak::Replace(CYContext 
&context
) { 
 119 CYExpression 
*CYCall::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 120     CYArgument 
**argument(&arguments_
); 
 121     while (*argument 
!= NULL
) 
 122         argument 
= &(*argument
)->next_
; 
 123     *argument 
= $ 
CYArgument(value
); 
 127 CYExpression 
*CYCall::Replace(CYContext 
&context
) { 
 128     context
.Replace(function_
); 
 129     arguments_
->Replace(context
); 
 136 void Catch::Replace(CYContext 
&context
) { $
T() 
 137     CYScope 
scope(true, context
); 
 139     context
.Replace(name_
); 
 140     context
.scope_
->Declare(context
, name_
, CYIdentifierCatch
); 
 142     context
.ReplaceAll(code_
); 
 143     scope
.Close(context
, code_
); 
 148 void CYClause::Replace(CYContext 
&context
) { $
T() 
 149     context
.Replace(case_
); 
 150     context
.ReplaceAll(code_
); 
 151     next_
->Replace(context
); 
 154 CYStatement 
*CYComment::Replace(CYContext 
&context
) { 
 158 CYExpression 
*CYCompound::Replace(CYContext 
&context
) { 
 159     context
.Replace(expression_
); 
 160     context
.Replace(next_
); 
 162     if (CYCompound 
*compound 
= dynamic_cast<CYCompound 
*>(expression_
)) { 
 163         expression_ 
= compound
->expression_
; 
 164         compound
->expression_ 
= compound
->next_
; 
 165         compound
->next_ 
= next_
; 
 172 CYFunctionParameter 
*CYCompound::Parameter() const { 
 173     CYFunctionParameter 
*next(next_
->Parameter()); 
 177     CYFunctionParameter 
*parameter(expression_
->Parameter()); 
 178     if (parameter 
== NULL
) 
 181     parameter
->SetNext(next
); 
 185 CYFunctionParameter 
*CYComprehension::Parameters(CYContext 
&context
) const { $
T(NULL
) 
 186     CYFunctionParameter 
*next(next_
->Parameters(context
)); 
 187     if (CYFunctionParameter 
*parameter 
= Parameter(context
)) { 
 188         parameter
->SetNext(next
); 
 194 CYStatement 
*CYComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 195     return next_ 
== NULL 
? statement 
: next_
->Replace(context
, statement
); 
 198 CYExpression 
*CYCondition::Replace(CYContext 
&context
) { 
 199     context
.Replace(test_
); 
 200     context
.Replace(true_
); 
 201     context
.Replace(false_
); 
 205 void CYContext::NonLocal(CYStatement 
*&statements
) { 
 206     CYContext 
&context(*this); 
 208     if (nextlocal_ 
!= NULL 
&& nextlocal_
->identifier_ 
!= NULL
) { 
 209         CYIdentifier 
*cye($
I("$cye")->Replace(context
)); 
 210         CYIdentifier 
*unique(nextlocal_
->identifier_
->Replace(context
)); 
 212         CYStatement 
*declare( 
 213             $ 
CYVar($
L1($ 
CYDeclaration(unique
, $ 
CYObject())))); 
 215         cy::Syntax::Catch 
*rescue( 
 216             $ 
cy::Syntax::Catch(cye
, $$
->* 
 217                 $ 
CYIf($ 
CYIdentical($
M($
V(cye
), $
S("$cyk")), $
V(unique
)), $$
->* 
 218                     $ 
CYReturn($
M($
V(cye
), $
S("$cyv"))))->* 
 219                 $ 
cy::Syntax::Throw($
V(cye
)))); 
 221         // XXX: I don't understand any of this 
 222         context
.Replace(declare
); 
 223         rescue
->Replace(context
); 
 227             $ 
cy::Syntax::Try(statements
, rescue
, NULL
); 
 231 CYIdentifier 
*CYContext::Unique() { 
 232     return $ 
CYIdentifier($pool
.strcat("$cy", $pool
.itoa(unique_
++), NULL
)); 
 235 CYStatement 
*CYContinue::Replace(CYContext 
&context
) { 
 239 CYStatement 
*CYDebugger::Replace(CYContext 
&context
) { 
 243 CYAssignment 
*CYDeclaration::Assignment(CYContext 
&context
) { 
 244     if (initialiser_ 
== NULL
) 
 247     CYAssignment 
*value($ 
CYAssign(Variable(context
), initialiser_
)); 
 252 CYVariable 
*CYDeclaration::Variable(CYContext 
&context
) { 
 253     return $
V(identifier_
); 
 256 CYStatement 
*CYDeclaration::ForEachIn(CYContext 
&context
, CYExpression 
*value
) { 
 257     return $ 
CYVar($
L1($ 
CYDeclaration(identifier_
, value
))); 
 260 CYExpression 
*CYDeclaration::Replace(CYContext 
&context
) { 
 261     context
.Replace(identifier_
); 
 262     context
.scope_
->Declare(context
, identifier_
, CYIdentifierVariable
); 
 263     return Variable(context
); 
 266 void CYDeclarations::Replace(CYContext 
&context
) { $
T() 
 267     declaration_
->Replace(context
); 
 268     next_
->Replace(context
); 
 271 CYProperty 
*CYDeclarations::Property(CYContext 
&context
) { $
T(NULL
) 
 272     return $ 
CYProperty(declaration_
->identifier_
, declaration_
->initialiser_
, next_
->Property(context
)); 
 275 CYFunctionParameter 
*CYDeclarations::Parameter(CYContext 
&context
) { $
T(NULL
) 
 276     return $ 
CYFunctionParameter($ 
CYDeclaration(declaration_
->identifier_
), next_
->Parameter(context
)); 
 279 CYArgument 
*CYDeclarations::Argument(CYContext 
&context
) { $
T(NULL
) 
 280     return $ 
CYArgument(declaration_
->initialiser_
, next_
->Argument(context
)); 
 283 CYExpression 
*CYDeclarations::Expression(CYContext 
&context
) { $
T(NULL
) 
 284     CYExpression 
*compound(next_
->Expression(context
)); 
 285     if (CYAssignment 
*assignment 
= declaration_
->Assignment(context
)) 
 286         if (compound 
== NULL
) 
 287             compound 
= assignment
; 
 289             compound 
= $ 
CYCompound(assignment
, compound
); 
 293 CYExpression 
*CYDirectMember::Replace(CYContext 
&context
) { 
 294     context
.Replace(object_
); 
 295     context
.Replace(property_
); 
 299 CYStatement 
*CYDoWhile::Replace(CYContext 
&context
) { 
 300     context
.Replace(test_
); 
 301     context
.ReplaceAll(code_
); 
 305 void CYElement::Replace(CYContext 
&context
) { $
T() 
 306     context
.Replace(value_
); 
 307     next_
->Replace(context
); 
 310 CYStatement 
*CYEmpty::Replace(CYContext 
&context
) { 
 314 CYExpression 
*CYEncodedType::Replace(CYContext 
&context
) { 
 315     return typed_
->Replace(context
); 
 318 CYStatement 
*CYExpress::Return() { 
 319     return $ 
CYReturn(expression_
); 
 322 CYStatement 
*CYExpress::Replace(CYContext 
&context
) { 
 323     context
.Replace(expression_
); 
 327 CYExpression 
*CYExpression::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 328     return $
C1(this, value
); 
 331 CYExpression 
*CYExpression::ClassName(CYContext 
&context
, bool object
) { 
 335 CYStatement 
*CYExpression::ForEachIn(CYContext 
&context
, CYExpression 
*value
) { 
 336     return $
E($ 
CYAssign(this, value
)); 
 339 CYAssignment 
*CYExpression::Assignment(CYContext 
&context
) { 
 343 CYFunctionParameter 
*CYExpression::Parameter() const { 
 347 CYStatement 
*CYExternal::Replace(CYContext 
&context
) { 
 348     return $
E($ 
CYAssign($
V(typed_
->identifier_
), $
C1(typed_
->Replace(context
), $
C2($
V("dlsym"), $
V("RTLD_DEFAULT"), $
S(typed_
->identifier_
->Word()))))); 
 351 CYNumber 
*CYFalse::Number(CYContext 
&context
) { 
 355 CYString 
*CYFalse::String(CYContext 
&context
) { 
 359 CYExpression 
*CYFatArrow::Replace(CYContext 
&context
) { 
 360     CYFunctionExpression 
*function($ 
CYFunctionExpression(NULL
, parameters_
, code_
)); 
 361     function
->this_
.SetNext(context
.this_
); 
 365 void CYFinally::Replace(CYContext 
&context
) { $
T() 
 366     context
.ReplaceAll(code_
); 
 369 CYStatement 
*CYFor::Replace(CYContext 
&context
) { 
 370     context
.Replace(initialiser_
); 
 371     context
.Replace(test_
); 
 372     context
.Replace(increment_
); 
 373     context
.ReplaceAll(code_
); 
 377 CYExpression 
*CYForDeclarations::Replace(CYContext 
&context
) { 
 378     declarations_
->Replace(context
); 
 379     return declarations_
->Expression(context
); 
 382 // XXX: this still feels highly suboptimal 
 383 CYStatement 
*CYForIn::Replace(CYContext 
&context
) { 
 384     if (CYAssignment 
*assignment 
= initialiser_
->Assignment(context
)) 
 385         return $ 
CYBlock($$
->* 
 390     context
.Replace(initialiser_
); 
 391     context
.Replace(set_
); 
 392     context
.ReplaceAll(code_
); 
 396 CYFunctionParameter 
*CYForInComprehension::Parameter(CYContext 
&context
) const { 
 397     return $ 
CYFunctionParameter($ 
CYDeclaration(name_
)); 
 400 CYStatement 
*CYForInComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 401     return $ 
CYForIn($
V(name_
), set_
, CYComprehension::Replace(context
, statement
)); 
 404 CYStatement 
*CYForOf::Replace(CYContext 
&context
) { 
 405     if (CYAssignment 
*assignment 
= initialiser_
->Assignment(context
)) 
 406         return $ 
CYBlock($$
->* 
 411     CYIdentifier 
*cys($
I("$cys")), *cyt($
I("$cyt")); 
 413     return $ 
CYLetStatement($
L2($ 
CYDeclaration(cys
, set_
), $ 
CYDeclaration(cyt
)), $$
->* 
 414         $ 
CYForIn($
V(cyt
), $
V(cys
), $ 
CYBlock($$
->* 
 415             initialiser_
->ForEachIn(context
, $
M($
V(cys
), $
V(cyt
)))->* 
 421 CYFunctionParameter 
*CYForOfComprehension::Parameter(CYContext 
&context
) const { 
 422     return $ 
CYFunctionParameter($ 
CYDeclaration(name_
)); 
 425 CYStatement 
*CYForOfComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 426     CYIdentifier 
*cys($
I("$cys")); 
 428     return $
E($
C0($
F(NULL
, $
P1($
L("$cys")), $$
->* 
 429         $
E($ 
CYAssign($
V(cys
), set_
))->* 
 430         $ 
CYForIn($
V(name_
), $
V(cys
), $ 
CYBlock($$
->* 
 431             $
E($ 
CYAssign($
V(name_
), $
M($
V(cys
), $
V(name_
))))->* 
 432             CYComprehension::Replace(context
, statement
) 
 437 void CYFunction::Inject(CYContext 
&context
) { 
 438     context
.Replace(name_
); 
 439     context
.scope_
->Declare(context
, name_
, CYIdentifierOther
); 
 442 void CYFunction::Replace_(CYContext 
&context
, bool outer
) { 
 446     CYThisScope 
*_this(context
.this_
); 
 447     context
.this_ 
= &this_
; 
 448     context
.this_ 
= CYGetLast(context
.this_
); 
 450     CYNonLocal 
*nonlocal(context
.nonlocal_
); 
 451     CYNonLocal 
*nextlocal(context
.nextlocal_
); 
 454     if (nonlocal_ 
!= NULL
) { 
 456         context
.nonlocal_ 
= nonlocal_
; 
 459         nonlocal_ 
= $ 
CYNonLocal(); 
 460         context
.nextlocal_ 
= nonlocal_
; 
 463     CYScope 
scope(!localize
, context
); 
 465     if (!outer 
&& name_ 
!= NULL
) 
 468     parameters_
->Replace(context
, code_
); 
 469     context
.ReplaceAll(code_
); 
 472         CYImplicitReturn(code_
); 
 474     if (CYIdentifier 
*identifier 
= this_
.identifier_
) 
 476             $ 
CYVar($
L1($ 
CYDeclaration(identifier
, $ 
CYThis())))->* 
 480         context
.NonLocal(code_
); 
 482     context
.nextlocal_ 
= nextlocal
; 
 483     context
.nonlocal_ 
= nonlocal
; 
 485     context
.this_ 
= _this
; 
 487     scope
.Close(context
, code_
); 
 490 CYExpression 
*CYFunctionExpression::Replace(CYContext 
&context
) { 
 491     Replace_(context
, false); 
 495 void CYFunctionParameter::Replace(CYContext 
&context
, CYStatement 
*&statements
) { $
T() 
 496     CYAssignment 
*assignment(initialiser_
->Assignment(context
)); 
 497     context
.Replace(initialiser_
); 
 499     next_
->Replace(context
, statements
); 
 501     if (assignment 
!= NULL
) 
 503             // XXX: this cast is quite incorrect 
 504             $ 
CYIf($ 
CYIdentical($ 
CYTypeOf(dynamic_cast<CYExpression 
*>(initialiser_
)), $
S("undefined")), $$
->* 
 510 CYStatement 
*CYFunctionStatement::Replace(CYContext 
&context
) { 
 511     Replace_(context
, true); 
 515 CYIdentifier 
*CYIdentifier::Replace(CYContext 
&context
) { 
 516     if (replace_ 
!= NULL 
&& replace_ 
!= this) 
 517         return replace_
->Replace(context
); 
 518     replace_ 
= context
.scope_
->Lookup(context
, this); 
 522 CYStatement 
*CYIf::Return() { 
 523     CYImplicitReturn(true_
); 
 524     CYImplicitReturn(false_
); 
 528 CYStatement 
*CYIf::Replace(CYContext 
&context
) { 
 529     context
.Replace(test_
); 
 530     context
.ReplaceAll(true_
); 
 531     context
.ReplaceAll(false_
); 
 535 CYFunctionParameter 
*CYIfComprehension::Parameter(CYContext 
&context
) const { 
 539 CYStatement 
*CYIfComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 540     return $ 
CYIf(test_
, CYComprehension::Replace(context
, statement
)); 
 543 CYStatement 
*CYImport::Replace(CYContext 
&context
) { 
 544     return $ 
CYVar($
L1($
L(module_
->part_
->Word(), $
C1($
V("require"), module_
->Replace(context
, "/"))))); 
 547 CYExpression 
*CYIndirect::Replace(CYContext 
&context
) { 
 548     return $
M(rhs_
, $
S("$cyi")); 
 551 CYExpression 
*CYIndirectMember::Replace(CYContext 
&context
) { 
 552     return $
M($ 
CYIndirect(object_
), property_
); 
 555 CYExpression 
*CYInfix::Replace(CYContext 
&context
) { 
 556     context
.Replace(lhs_
); 
 557     context
.Replace(rhs_
); 
 561 CYStatement 
*CYLabel::Replace(CYContext 
&context
) { 
 562     context
.Replace(statement_
); 
 566 CYExpression 
*CYLambda::Replace(CYContext 
&context
) { 
 567     return $
N2($
V("Functor"), $ 
CYFunctionExpression(NULL
, parameters_
->Parameters(context
), code_
), parameters_
->TypeSignature(context
, typed_
->Replace(context
))); 
 570 CYStatement 
*CYLetStatement::Replace(CYContext 
&context
) { 
 571     return $
E($ 
CYCall(CYNonLocalize(context
, $ 
CYFunctionExpression(NULL
, declarations_
->Parameter(context
), code_
)), declarations_
->Argument(context
))); 
 574 CYString 
*CYModule::Replace(CYContext 
&context
, const char *separator
) const { 
 576         return $ 
CYString(part_
); 
 577     return $ 
CYString($pool
.strcat(next_
->Replace(context
, separator
)->Value(), separator
, part_
->Word(), NULL
)); 
 580 CYExpression 
*CYMultiply::Replace(CYContext 
&context
) { 
 581     CYInfix::Replace(context
); 
 583     if (CYNumber 
*lhn 
= lhs_
->Number(context
)) 
 584         if (CYNumber 
*rhn 
= rhs_
->Number(context
)) 
 585             return $
D(lhn
->Value() * rhn
->Value()); 
 593 CYExpression 
*New::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 594     CYSetLast(arguments_
) = $ 
CYArgument(value
); 
 598 CYExpression 
*New::Replace(CYContext 
&context
) { 
 599     context
.Replace(constructor_
); 
 600     arguments_
->Replace(context
); 
 606 CYNumber 
*CYNull::Number(CYContext 
&context
) { 
 610 CYString 
*CYNull::String(CYContext 
&context
) { 
 614 CYNumber 
*CYNumber::Number(CYContext 
&context
) { 
 618 CYString 
*CYNumber::String(CYContext 
&context
) { 
 619     // XXX: there is a precise algorithm for this 
 620     return $
S($pool
.sprintf(24, "%.17g", Value())); 
 623 CYExpression 
*CYObject::Replace(CYContext 
&context
) { 
 624     properties_
->Replace(context
); 
 628 CYExpression 
*CYParenthetical::Replace(CYContext 
&context
) { 
 632 CYExpression 
*CYPostfix::Replace(CYContext 
&context
) { 
 633     context
.Replace(lhs_
); 
 637 CYExpression 
*CYPrefix::Replace(CYContext 
&context
) { 
 638     context
.Replace(rhs_
); 
 642 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe! 
 643 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ" 
 644 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_" 
 647     struct IdentifierUsageLess 
: 
 648         std::binary_function
<CYIdentifier 
*, CYIdentifier 
*, bool> 
 650         _finline 
bool operator ()(CYIdentifier 
*lhs
, CYIdentifier 
*rhs
) const { 
 651             if (lhs
->usage_ 
!= rhs
->usage_
) 
 652                 return lhs
->usage_ 
> rhs
->usage_
; 
 657     typedef std::set
<CYIdentifier 
*, IdentifierUsageLess
> IdentifierUsages
; 
 660 void CYProgram::Replace(CYContext 
&context
) { 
 661     CYScope 
scope(true, context
); 
 663     context
.nextlocal_ 
= $ 
CYNonLocal(); 
 664     context
.ReplaceAll(code_
); 
 665     context
.NonLocal(code_
); 
 667     scope
.Close(context
, code_
); 
 671     CYCStringSet external
; 
 672     for (CYIdentifierValueSet::const_iterator 
i(scope
.identifiers_
.begin()); i 
!= scope
.identifiers_
.end(); ++i
) 
 673         external
.insert((*i
)->Word()); 
 675     IdentifierUsages usages
; 
 677     if (offset 
< context
.rename_
.size()) 
 678         CYForEach (i
, context
.rename_
[offset
].identifier_
) 
 681     // XXX: totalling the probable occurrences and sorting by them would improve the result 
 682     for (CYIdentifierUsageVector::const_iterator 
i(context
.rename_
.begin()); i 
!= context
.rename_
.end(); ++i
, ++offset
) { 
 683         //std::cout << *i << ":" << (*i)->offset_ << std::endl; 
 687         if (context
.options_
.verbose_
) 
 688             name 
= $pool
.strcat("$", $pool
.itoa(offset
), NULL
); 
 694             unsigned position(7), local(offset 
+ 1); 
 697                 unsigned index(local 
% (sizeof(MappingSet
) - 1)); 
 698                 local 
/= sizeof(MappingSet
) - 1; 
 699                 id
[--position
] = MappingSet
[index
]; 
 700             } while (local 
!= 0); 
 702             if (external
.find(id 
+ position
) != external
.end()) { 
 707             name 
= $pool
.strmemdup(id 
+ position
, 7 - position
); 
 708             // XXX: at some point, this could become a keyword 
 711         CYForEach (identifier
, i
->identifier_
) 
 712             identifier
->Set(name
); 
 716 void CYProperty::Replace(CYContext 
&context
) { $
T() 
 717     context
.Replace(value_
); 
 718     next_
->Replace(context
); 
 723 CYStatement 
*CYReturn::Replace(CYContext 
&context
) { 
 724     if (context
.nonlocal_ 
!= NULL
) { 
 725         CYProperty 
*value(value_ 
== NULL 
? NULL 
: $ 
CYProperty($
S("$cyv"), value_
)); 
 726         return $ 
cy::Syntax::Throw($ 
CYObject( 
 727             $ 
CYProperty($
S("$cyk"), $
V(context
.nonlocal_
->Target(context
)), value
) 
 731     context
.Replace(value_
); 
 735 CYExpression 
*CYRubyBlock::Replace(CYContext 
&context
) { 
 736     return call_
->AddArgument(context
, proc_
->Replace(context
)); 
 739 CYExpression 
*CYRubyProc::Replace(CYContext 
&context
) { 
 740     CYFunctionExpression 
*function($ 
CYFunctionExpression(NULL
, parameters_
, code_
)); 
 741     function 
= CYNonLocalize(context
, function
); 
 742     function
->implicit_ 
= true; 
 746 CYScope::CYScope(bool transparent
, CYContext 
&context
) : 
 747     transparent_(transparent
), 
 748     parent_(context
.scope_
) 
 750     context
.scope_ 
= this; 
 753 void CYScope::Declare(CYContext 
&context
, CYIdentifier 
*identifier
, CYIdentifierFlags flags
) { 
 754     if (!transparent_ 
|| flags 
== CYIdentifierArgument 
|| flags 
== CYIdentifierCatch
) 
 755         internal_
.insert(CYIdentifierAddressFlagsMap::value_type(identifier
, flags
)); 
 756     else if (parent_ 
!= NULL
) 
 757         parent_
->Declare(context
, identifier
, flags
); 
 760 CYIdentifier 
*CYScope::Lookup(CYContext 
&context
, CYIdentifier 
*identifier
) { 
 761     std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
)); 
 762     return *insert
.first
; 
 765 void CYScope::Merge(CYContext 
&context
, CYIdentifier 
*identifier
) { 
 766     std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
)); 
 767     if (!insert
.second
) { 
 768         if ((*insert
.first
)->offset_ 
< identifier
->offset_
) 
 769             (*insert
.first
)->offset_ 
= identifier
->offset_
; 
 770         identifier
->replace_ 
= *insert
.first
; 
 771         (*insert
.first
)->usage_ 
+= identifier
->usage_ 
+ 1; 
 776     struct IdentifierOffset 
{ 
 778         CYIdentifierFlags flags_
; 
 780         CYIdentifier 
*identifier_
; 
 782         IdentifierOffset(CYIdentifier 
*identifier
, CYIdentifierFlags flags
) : 
 783             offset_(identifier
->offset_
), 
 785             usage_(identifier
->usage_
), 
 786             identifier_(identifier
) 
 791     struct IdentifierOffsetLess 
: 
 792         std::binary_function
<const IdentifierOffset 
&, const IdentifierOffset 
&, bool> 
 794         _finline 
bool operator ()(const IdentifierOffset 
&lhs
, const IdentifierOffset 
&rhs
) const { 
 795             if (lhs
.offset_ 
!= rhs
.offset_
) 
 796                 return lhs
.offset_ 
< rhs
.offset_
; 
 797             if (lhs
.flags_ 
!= rhs
.flags_
) 
 798                 return lhs
.flags_ 
< rhs
.flags_
; 
 799             /*if (lhs.usage_ != rhs.usage_) 
 800                 return lhs.usage_ < rhs.usage_;*/ 
 801             return lhs
.identifier_ 
< rhs
.identifier_
; 
 805     typedef std::set
<IdentifierOffset
, IdentifierOffsetLess
> IdentifierOffsets
; 
 808 void CYScope::Close(CYContext 
&context
, CYStatement 
*&statements
) { 
 809     context
.scope_ 
= parent_
; 
 814     CYDeclarations 
*last(NULL
), *curr(NULL
); 
 816     IdentifierOffsets offsets
; 
 818     for (CYIdentifierAddressFlagsMap::const_iterator 
i(internal_
.begin()); i 
!= internal_
.end(); ++i
) 
 819         if (i
->second 
!= CYIdentifierMagic
) 
 820             offsets
.insert(IdentifierOffset(i
->first
, i
->second
)); 
 824     for (IdentifierOffsets::const_iterator 
i(offsets
.begin()); i 
!= offsets
.end(); ++i
) { 
 825         if (i
->flags_ 
== CYIdentifierVariable
) { 
 826             CYDeclarations 
*next($ 
CYDeclarations($ 
CYDeclaration(i
->identifier_
))); 
 834         if (offset 
< i
->offset_
) 
 836         if (context
.rename_
.size() <= offset
) 
 837             context
.rename_
.resize(offset 
+ 1); 
 839         CYIdentifierUsage 
&rename(context
.rename_
[offset
++]); 
 840         i
->identifier_
->SetNext(rename
.identifier_
); 
 841         rename
.identifier_ 
= i
->identifier_
; 
 842         rename
.usage_ 
+= i
->identifier_
->usage_ 
+ 1; 
 846         CYVar 
*var($ 
CYVar(last
)); 
 847         var
->SetNext(statements
); 
 851     for (CYIdentifierValueSet::const_iterator 
i(identifiers_
.begin()); i 
!= identifiers_
.end(); ++i
) 
 852         if (internal_
.find(*i
) == internal_
.end()) { 
 853             //std::cout << *i << '=' << offset << std::endl; 
 854             if ((*i
)->offset_ 
< offset
) 
 855                 (*i
)->offset_ 
= offset
; 
 856             parent_
->Merge(context
, *i
); 
 860 CYStatement 
*CYStatement::Return() { 
 864 CYString 
*CYString::Concat(CYContext 
&context
, CYString 
*rhs
) const { 
 865     size_t size(size_ 
+ rhs
->size_
); 
 866     char *value($ 
char[size 
+ 1]); 
 867     memcpy(value
, value_
, size_
); 
 868     memcpy(value 
+ size_
, rhs
->value_
, rhs
->size_
); 
 870     return $
S(value
, size
); 
 873 CYNumber 
*CYString::Number(CYContext 
&context
) { 
 874     // XXX: there is a precise algorithm for this 
 878 CYString 
*CYString::String(CYContext 
&context
) { 
 882 CYStatement 
*CYSwitch::Replace(CYContext 
&context
) { 
 883     context
.Replace(value_
); 
 884     clauses_
->Replace(context
); 
 888 CYExpression 
*CYThis::Replace(CYContext 
&context
) { 
 889     if (context
.this_ 
!= NULL
) 
 890         return $
V(context
.this_
->Identifier(context
)); 
 897 CYStatement 
*Throw::Replace(CYContext 
&context
) { 
 898     context
.Replace(value_
); 
 904 CYExpression 
*CYTrivial::Replace(CYContext 
&context
) { 
 908 CYNumber 
*CYTrue::Number(CYContext 
&context
) { 
 912 CYString 
*CYTrue::String(CYContext 
&context
) { 
 919 CYStatement 
*Try::Replace(CYContext 
&context
) { 
 920     context
.ReplaceAll(code_
); 
 921     catch_
->Replace(context
); 
 922     finally_
->Replace(context
); 
 928 CYExpression 
*CYTypeArrayOf::Replace_(CYContext 
&context
, CYExpression 
*type
) { 
 929     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("arrayOf")), $ 
CYArgument(size_
))); 
 932 CYExpression 
*CYTypeBlockWith::Replace_(CYContext 
&context
, CYExpression 
*type
) { 
 933     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("blockWith")), parameters_
->Argument(context
))); 
 936 CYExpression 
*CYTypeConstant::Replace_(CYContext 
&context
, CYExpression 
*type
) { 
 937     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("constant")))); 
 940 CYStatement 
*CYTypeDefinition::Replace(CYContext 
&context
) { 
 941     return $
E($ 
CYAssign($
V(typed_
->identifier_
), typed_
->Replace(context
))); 
 944 CYExpression 
*CYTypeError::Replace(CYContext 
&context
) { 
 949 CYExpression 
*CYTypeModifier::Replace(CYContext 
&context
, CYExpression 
*type
) { $
T(type
) 
 950     return Replace_(context
, type
); 
 953 CYExpression 
*CYTypeFunctionWith::Replace_(CYContext 
&context
, CYExpression 
*type
) { 
 954     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("functionWith")), parameters_
->Argument(context
))); 
 957 CYExpression 
*CYTypeLong::Replace(CYContext 
&context
) { 
 958     return $ 
CYCall($ 
CYDirectMember(specifier_
->Replace(context
), $ 
CYString("long"))); 
 961 CYExpression 
*CYTypePointerTo::Replace_(CYContext 
&context
, CYExpression 
*type
) { 
 962     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("pointerTo")))); 
 965 CYExpression 
*CYTypeShort::Replace(CYContext 
&context
) { 
 966     return $ 
CYCall($ 
CYDirectMember(specifier_
->Replace(context
), $ 
CYString("short"))); 
 969 CYExpression 
*CYTypeSigned::Replace(CYContext 
&context
) { 
 970     return $ 
CYCall($ 
CYDirectMember(specifier_
->Replace(context
), $ 
CYString("signed"))); 
 973 CYExpression 
*CYTypeUnsigned::Replace(CYContext 
&context
) { 
 974     return $ 
CYCall($ 
CYDirectMember(specifier_
->Replace(context
), $ 
CYString("unsigned"))); 
 977 CYExpression 
*CYTypeVariable::Replace(CYContext 
&context
) { 
 981 CYExpression 
*CYTypeVoid::Replace(CYContext 
&context
) { 
 982     return $
N1($
V("Type"), $ 
CYString("v")); 
 985 CYExpression 
*CYTypeVolatile::Replace_(CYContext 
&context
, CYExpression 
*type
) { 
 986     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("volatile")))); 
 989 CYExpression 
*CYTypedIdentifier::Replace(CYContext 
&context
) { 
 990     return modifier_
->Replace(context
, specifier_
->Replace(context
)); 
 993 CYTypeFunctionWith 
*CYTypedIdentifier::Function() { 
 994     CYTypeModifier 
**modifier(&modifier_
); 
 995     if (*modifier 
== NULL
) 
 997     while ((*modifier
)->next_ 
!= NULL
) 
 998         modifier 
= &(*modifier
)->next_
; 
 999     CYTypeFunctionWith 
*function((*modifier
)->Function()); 
1000     if (function 
== NULL
) 
1006 CYArgument 
*CYTypedParameter::Argument(CYContext 
&context
) { $
T(NULL
) 
1007     return $ 
CYArgument(typed_
->Replace(context
), next_
->Argument(context
)); 
1010 CYFunctionParameter 
*CYTypedParameter::Parameters(CYContext 
&context
) { $
T(NULL
) 
1011     return $ 
CYFunctionParameter($ 
CYDeclaration(typed_
->identifier_ 
?: context
.Unique()), next_
->Parameters(context
)); 
1014 CYExpression 
*CYTypedParameter::TypeSignature(CYContext 
&context
, CYExpression 
*prefix
) { $
T(prefix
) 
1015     return next_
->TypeSignature(context
, $ 
CYAdd(prefix
, typed_
->Replace(context
))); 
1018 CYStatement 
*CYVar::Replace(CYContext 
&context
) { 
1019     declarations_
->Replace(context
); 
1020     if (CYExpression 
*expression 
= declarations_
->Expression(context
)) 
1021         return $
E(expression
); 
1025 CYExpression 
*CYVariable::Replace(CYContext 
&context
) { 
1026     context
.Replace(name_
); 
1030 CYFunctionParameter 
*CYVariable::Parameter() const { 
1031     return $ 
CYFunctionParameter($ 
CYDeclaration(name_
)); 
1034 CYStatement 
*CYWhile::Replace(CYContext 
&context
) { 
1035     context
.Replace(test_
); 
1036     context
.ReplaceAll(code_
); 
1040 CYStatement 
*CYWith::Replace(CYContext 
&context
) { 
1041     context
.Replace(scope_
); 
1042     context
.ReplaceAll(code_
); 
1046 CYExpression 
*CYWord::ClassName(CYContext 
&context
, bool object
) { 
1047     CYString 
*name($
S(this)); 
1049         return $
C1($
V("objc_getClass"), name
);