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/>. 
  25 #include "Replace.hpp" 
  28 CYFunctionExpression 
*CYNonLocalize(CYContext 
&context
, CYFunctionExpression 
*function
) { 
  29     function
->nonlocal_ 
= context
.nextlocal_
; 
  33 CYFunctionExpression 
*CYSuperize(CYContext 
&context
, CYFunctionExpression 
*function
) { 
  34     function
->super_ 
= context
.super_
; 
  38 CYStatement 
*CYDefineProperty(CYExpression 
*object
, CYExpression 
*name
, bool configurable
, bool enumerable
, CYProperty 
*descriptor
) { 
  39     return $
E($
C3($
M($
V("Object"), $
S("defineProperty")), object
, name
, $ 
CYObject(CYList
<CYProperty
>() 
  40         ->* (configurable 
? $ 
CYPropertyValue($
S("configurable"), $ 
CYTrue()) : NULL
) 
  41         ->* (enumerable 
? $ 
CYPropertyValue($
S("enumerable"), $ 
CYTrue()) : NULL
) 
  45 static void CYImplicitReturn(CYStatement 
*&code
) { 
  46     if (CYStatement 
*&last 
= CYGetLast(code
)) 
  47         last 
= last
->Return(); 
  50 CYExpression 
*CYAdd::Replace(CYContext 
&context
) { 
  51     CYInfix::Replace(context
); 
  53     CYString 
*lhs(dynamic_cast<CYString 
*>(lhs_
)); 
  54     CYString 
*rhs(dynamic_cast<CYString 
*>(rhs_
)); 
  56     if (lhs 
!= NULL 
|| rhs 
!= NULL
) { 
  58             lhs 
= lhs_
->String(context
); 
  61         } else if (rhs 
== NULL
) { 
  62             rhs 
= rhs_
->String(context
); 
  67         return lhs
->Concat(context
, rhs
); 
  70     if (CYNumber 
*lhn 
= lhs_
->Number(context
)) 
  71         if (CYNumber 
*rhn 
= rhs_
->Number(context
)) 
  72             return $
D(lhn
->Value() + rhn
->Value()); 
  77 CYExpression 
*CYAddressOf::Replace(CYContext 
&context
) { 
  78     return $
C0($
M(rhs_
, $
S("$cya"))); 
  81 CYTarget 
*CYApply::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
  82     CYArgument 
**argument(&arguments_
); 
  83     while (*argument 
!= NULL
) 
  84         argument 
= &(*argument
)->next_
; 
  85     *argument 
= $ 
CYArgument(value
); 
  89 CYArgument 
*CYArgument::Replace(CYContext 
&context
) { $
T(NULL
) 
  90     context
.Replace(value_
); 
  91     next_ 
= next_
->Replace(context
); 
 103 CYTarget 
*CYArray::Replace(CYContext 
&context
) { 
 104     if (elements_ 
!= NULL
) 
 105         elements_
->Replace(context
); 
 109 CYTarget 
*CYArrayComprehension::Replace(CYContext 
&context
) { 
 110     CYIdentifier 
*cyv(context
.Unique()); 
 112     return $
C0($
F(NULL
, $
P1($
L(cyv
), comprehensions_
->Parameters(context
)), $$
 
 113         ->* $
E($ 
CYAssign($
V(cyv
), $ 
CYArray())) 
 114         ->* comprehensions_
->Replace(context
, $
E($
C1($
M($
V(cyv
), $
S("push")), expression_
))) 
 115         ->* $ 
CYReturn($
V(cyv
)) 
 119 CYExpression 
*CYAssignment::Replace(CYContext 
&context
) { 
 120     context
.Replace(lhs_
); 
 121     context
.Replace(rhs_
); 
 125 CYStatement 
*CYBlock::Return() { 
 126     CYImplicitReturn(code_
); 
 130 CYStatement 
*CYBlock::Replace(CYContext 
&context
) { 
 131     CYScope 
scope(true, context
); 
 132     context
.ReplaceAll(code_
); 
 133     scope
.Close(context
); 
 140 CYStatement 
*CYBreak::Replace(CYContext 
&context
) { 
 144 CYTarget 
*CYCall::Replace(CYContext 
&context
) { 
 145     context
.Replace(function_
); 
 146     arguments_
->Replace(context
); 
 153 void Catch::Replace(CYContext 
&context
) { $
T() 
 154     CYScope 
scope(true, context
); 
 156     name_ 
= name_
->Replace(context
, CYIdentifierCatch
); 
 158     context
.ReplaceAll(code_
); 
 159     scope
.Close(context
); 
 164 CYTarget 
*CYClassExpression::Replace(CYContext 
&context
) { 
 167     CYIdentifier 
*super(context
.Unique()); 
 169     CYIdentifier 
*old(context
.super_
); 
 170     context
.super_ 
= super
; 
 172     CYIdentifier 
*constructor(context
.Unique()); 
 173     CYForEach (member
, tail_
->static_
) 
 174         member
->Replace(context
, builder
, $
V(constructor
), true); 
 176     CYIdentifier 
*prototype(context
.Unique()); 
 177     CYForEach (member
, tail_
->instance_
) 
 178         member
->Replace(context
, builder
, $
V(prototype
), true); 
 180     if (tail_
->constructor_ 
== NULL
) 
 181         tail_
->constructor_ 
= $ 
CYFunctionExpression(NULL
, NULL
, NULL
); 
 182     tail_
->constructor_ 
= CYSuperize(context
, tail_
->constructor_
); 
 184     context
.super_ 
= old
; 
 186     return $
C1($ 
CYFunctionExpression(NULL
, $
P($
L(super
)), $$
 
 187         ->* $ 
CYVar($
L1($
L(constructor
, tail_
->constructor_
))) 
 188         ->* $ 
CYVar($
L1($
L(prototype
, $ 
CYFunctionExpression(NULL
, NULL
, NULL
)))) 
 189         ->* $
E($ 
CYAssign($
M($
V(prototype
), $
S("prototype")), $
M($
V(super
), $
S("prototype")))) 
 190         ->* $
E($ 
CYAssign($
V(prototype
), $
N($
V(prototype
)))) 
 191         ->* CYDefineProperty($
V(prototype
), $
S("constructor"), false, false, $ 
CYPropertyValue($
S("value"), $
V(constructor
))) 
 192         ->* $ 
CYVar(builder
.declarations_
) 
 193         ->* builder
.statements_
 
 194         ->* CYDefineProperty($
V(constructor
), $
S("prototype"), false, false, $ 
CYPropertyValue($
S("value"), $
V(prototype
))) 
 195         ->* $ 
CYReturn($
V(constructor
)) 
 196     ), tail_
->extends_ 
?: $
V($
I("Object"))); 
 199 CYStatement 
*CYClassStatement::Replace(CYContext 
&context
) { 
 200     return $ 
CYVar($
L1($
L(name_
, $ 
CYClassExpression(name_
, tail_
)))); 
 203 void CYClause::Replace(CYContext 
&context
) { $
T() 
 204     context
.Replace(case_
); 
 205     context
.ReplaceAll(code_
); 
 206     next_
->Replace(context
); 
 209 CYExpression 
*CYCompound::Replace(CYContext 
&context
) { 
 210     context
.Replace(expression_
); 
 211     context
.Replace(next_
); 
 213     if (CYCompound 
*compound 
= dynamic_cast<CYCompound 
*>(expression_
)) { 
 214         expression_ 
= compound
->expression_
; 
 215         compound
->expression_ 
= compound
->next_
; 
 216         compound
->next_ 
= next_
; 
 223 CYFunctionParameter 
*CYCompound::Parameter() const { 
 224     CYFunctionParameter 
*next(next_
->Parameter()); 
 228     CYFunctionParameter 
*parameter(expression_
->Parameter()); 
 229     if (parameter 
== NULL
) 
 232     parameter
->SetNext(next
); 
 236 CYFunctionParameter 
*CYComprehension::Parameters(CYContext 
&context
) const { $
T(NULL
) 
 237     CYFunctionParameter 
*next(next_
->Parameters(context
)); 
 238     if (CYFunctionParameter 
*parameter 
= Parameter(context
)) { 
 239         parameter
->SetNext(next
); 
 245 CYStatement 
*CYComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 246     return next_ 
== NULL 
? statement 
: next_
->Replace(context
, statement
); 
 249 CYExpression 
*CYComputed::PropertyName(CYContext 
&context
) { 
 253 CYExpression 
*CYCondition::Replace(CYContext 
&context
) { 
 254     context
.Replace(test_
); 
 255     context
.Replace(true_
); 
 256     context
.Replace(false_
); 
 260 void CYContext::NonLocal(CYStatement 
*&statements
) { 
 261     CYContext 
&context(*this); 
 263     if (nextlocal_ 
!= NULL 
&& nextlocal_
->identifier_ 
!= NULL
) { 
 264         CYIdentifier 
*cye($
I("$cye")->Replace(context
, CYIdentifierGlobal
)); 
 265         CYIdentifier 
*unique(nextlocal_
->identifier_
->Replace(context
, CYIdentifierGlobal
)); 
 267         CYStatement 
*declare( 
 268             $ 
CYVar($
L1($
L(unique
, $ 
CYObject())))); 
 270         cy::Syntax::Catch 
*rescue( 
 271             $ 
cy::Syntax::Catch(cye
, $$
 
 272                 ->* $ 
CYIf($ 
CYIdentical($
M($
V(cye
), $
S("$cyk")), $
V(unique
)), $$
 
 273                     ->* $ 
CYReturn($
M($
V(cye
), $
S("$cyv")))) 
 274                 ->* $ 
cy::Syntax::Throw($
V(cye
)))); 
 276         context
.Replace(declare
); 
 277         rescue
->Replace(context
); 
 281             ->* $ 
cy::Syntax::Try(statements
, rescue
, NULL
); 
 285 CYIdentifier 
*CYContext::Unique() { 
 286     return $ 
CYIdentifier($pool
.strcat("$cy", $pool
.itoa(unique_
++), NULL
)); 
 289 CYStatement 
*CYContinue::Replace(CYContext 
&context
) { 
 293 CYStatement 
*CYDebugger::Replace(CYContext 
&context
) { 
 297 CYTarget 
*CYDeclaration::Target(CYContext 
&context
) { 
 298     return $
V(identifier_
); 
 301 CYAssignment 
*CYDeclaration::Replace(CYContext 
&context
, CYIdentifierKind kind
) { 
 302     identifier_ 
= identifier_
->Replace(context
, kind
); 
 304     if (initialiser_ 
== NULL
) 
 307     CYAssignment 
*value($ 
CYAssign(Target(context
), initialiser_
)); 
 312 CYExpression 
*CYDeclarations::Replace(CYContext 
&context
, CYIdentifierKind kind
) { $
T(NULL
) 
 313     CYAssignment 
*assignment(declaration_
->Replace(context
, kind
)); 
 314     CYExpression 
*compound(next_
->Replace(context
, kind
)); 
 316     if (assignment 
!= NULL
) 
 317         if (compound 
== NULL
) 
 318             compound 
= assignment
; 
 320             compound 
= $ 
CYCompound(assignment
, compound
); 
 324 CYFunctionParameter 
*CYDeclarations::Parameter(CYContext 
&context
) { $
T(NULL
) 
 325     return $ 
CYFunctionParameter($ 
CYDeclaration(declaration_
->identifier_
), next_
->Parameter(context
)); 
 328 CYArgument 
*CYDeclarations::Argument(CYContext 
&context
) { $
T(NULL
) 
 329     return $ 
CYArgument(declaration_
->initialiser_
, next_
->Argument(context
)); 
 332 CYTarget 
*CYDirectMember::Replace(CYContext 
&context
) { 
 333     context
.Replace(object_
); 
 334     context
.Replace(property_
); 
 338 CYStatement 
*CYDoWhile::Replace(CYContext 
&context
) { 
 339     context
.Replace(test_
); 
 340     context
.ReplaceAll(code_
); 
 344 void CYElementSpread::Replace(CYContext 
&context
) { 
 345     context
.Replace(value_
); 
 348 void CYElementValue::Replace(CYContext 
&context
) { 
 349     context
.Replace(value_
); 
 351         next_
->Replace(context
); 
 354 CYForInitializer 
*CYEmpty::Replace(CYContext 
&context
) { 
 358 CYTarget 
*CYEncodedType::Replace(CYContext 
&context
) { 
 359     return typed_
->Replace(context
); 
 362 CYTarget 
*CYEval::Replace(CYContext 
&context
) { 
 363     context
.scope_
->Damage(); 
 364     if (arguments_ 
!= NULL
) 
 365         arguments_
->value_ 
= $
C1($
M($
V("Cycript"), $
S("compile")), arguments_
->value_
); 
 366     return $
C($
V("eval"), arguments_
); 
 369 CYStatement 
*CYExpress::Return() { 
 370     return $ 
CYReturn(expression_
); 
 373 CYForInitializer 
*CYExpress::Replace(CYContext 
&context
) { 
 374     context
.Replace(expression_
); 
 378 CYTarget 
*CYExpression::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 379     return $
C1(this, value
); 
 382 CYFunctionParameter 
*CYExpression::Parameter() const { 
 386 CYStatement 
*CYExternal::Replace(CYContext 
&context
) { 
 387     return $
E($ 
CYAssign($
V(typed_
->identifier_
), $
C1(typed_
->Replace(context
), $
C2($
V("dlsym"), $
V("RTLD_DEFAULT"), $
S(typed_
->identifier_
->Word()))))); 
 390 CYNumber 
*CYFalse::Number(CYContext 
&context
) { 
 394 CYString 
*CYFalse::String(CYContext 
&context
) { 
 398 CYExpression 
*CYFatArrow::Replace(CYContext 
&context
) { 
 399     CYFunctionExpression 
*function($ 
CYFunctionExpression(NULL
, parameters_
, code_
)); 
 400     function
->this_
.SetNext(context
.this_
); 
 404 void CYFinally::Replace(CYContext 
&context
) { $
T() 
 405     CYScope 
scope(true, context
); 
 406     context
.ReplaceAll(code_
); 
 407     scope
.Close(context
); 
 410 CYStatement 
*CYFor::Replace(CYContext 
&context
) { 
 411     CYScope 
outer(true, context
); 
 412     context
.Replace(initialiser_
); 
 414     context
.Replace(test_
); 
 417         CYScope 
inner(true, context
); 
 418         context
.ReplaceAll(code_
); 
 419         inner
.Close(context
); 
 422     context
.Replace(increment_
); 
 424     outer
.Close(context
); 
 428 CYStatement 
*CYForLexical::Initialize(CYContext 
&context
, CYExpression 
*value
) { 
 430         if (declaration_
->initialiser_ 
== NULL
) 
 432         value 
= declaration_
->initialiser_
; 
 435     return $ 
CYLet(constant_
, $
L1($ 
CYDeclaration(declaration_
->identifier_
, value
))); 
 438 CYTarget 
*CYForLexical::Replace(CYContext 
&context
) { 
 439     _assert(declaration_
->Replace(context
, CYIdentifierLexical
) == NULL
); 
 440     return declaration_
->Target(context
); 
 443 CYStatement 
*CYForIn::Replace(CYContext 
&context
) { 
 444     CYScope 
scope(true, context
); 
 445     context
.Replace(initialiser_
); 
 446     context
.Replace(set_
); 
 447     context
.ReplaceAll(code_
); 
 448     scope
.Close(context
); 
 452 CYStatement 
*CYForInitialized::Replace(CYContext 
&context
) { 
 453     CYAssignment 
*assignment(declaration_
->Replace(context
, CYIdentifierVariable
)); 
 455         ->* (assignment 
== NULL 
? NULL 
: $ 
CYExpress(assignment
)) 
 456         ->* $ 
CYForIn(declaration_
->Target(context
), set_
, code_
)); 
 459 CYFunctionParameter 
*CYForInComprehension::Parameter(CYContext 
&context
) const { 
 460     return $ 
CYFunctionParameter(declaration_
); 
 463 CYStatement 
*CYForInComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 464     return $ 
CYForIn(declaration_
->Target(context
), set_
, CYComprehension::Replace(context
, statement
)); 
 467 CYStatement 
*CYForOf::Replace(CYContext 
&context
) { 
 468     CYIdentifier 
*item(context
.Unique()), *list(context
.Unique()); 
 471         ->* initialiser_
->Initialize(context
, NULL
) 
 472         ->* $ 
CYLet(false, $
L2($
L(list
, set_
), $
L(item
))) 
 473         ->* $ 
CYForIn($
V(item
), $
V(list
), $ 
CYBlock($$
 
 474             ->* initialiser_
->Initialize(context
, $
M($
V(list
), $
V(item
))) 
 479 CYFunctionParameter 
*CYForOfComprehension::Parameter(CYContext 
&context
) const { 
 480     return $ 
CYFunctionParameter(declaration_
); 
 483 CYStatement 
*CYForOfComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 484     CYIdentifier 
*cys(context
.Unique()); 
 487         ->* $ 
CYLet(false, $
L1($
L(cys
, set_
))) 
 488         ->* $ 
CYForIn(declaration_
->Target(context
), $
V(cys
), $ 
CYBlock($$
 
 489             ->* $
E($ 
CYAssign(declaration_
->Target(context
), $
M($
V(cys
), declaration_
->Target(context
)))) 
 490             ->* CYComprehension::Replace(context
, statement
) 
 494 CYStatement 
*CYForVariable::Initialize(CYContext 
&context
, CYExpression 
*value
) { 
 496         if (declaration_
->initialiser_ 
== NULL
) 
 498         value 
= declaration_
->initialiser_
; 
 501     return $ 
CYVar($
L1($ 
CYDeclaration(declaration_
->identifier_
, value
))); 
 504 CYTarget 
*CYForVariable::Replace(CYContext 
&context
) { 
 505     _assert(declaration_
->Replace(context
, CYIdentifierVariable
) == NULL
); 
 506     return declaration_
->Target(context
); 
 509 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe! 
 510 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ" 
 511 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_" 
 513 void CYFunction::Replace(CYContext 
&context
) { 
 514     CYThisScope 
*_this(context
.this_
); 
 515     context
.this_ 
= &this_
; 
 516     context
.this_ 
= CYGetLast(context
.this_
); 
 518     CYIdentifier 
*super(context
.super_
); 
 519     context
.super_ 
= super_
; 
 521     CYNonLocal 
*nonlocal(context
.nonlocal_
); 
 522     CYNonLocal 
*nextlocal(context
.nextlocal_
); 
 525     if (nonlocal_ 
!= NULL
) { 
 527         context
.nonlocal_ 
= nonlocal_
; 
 530         nonlocal_ 
= $ 
CYNonLocal(); 
 531         context
.nextlocal_ 
= nonlocal_
; 
 534     CYScope 
scope(!localize
, context
); 
 536     $
I("arguments")->Replace(context
, CYIdentifierMagic
); 
 538     parameters_
->Replace(context
, code_
); 
 540     context
.ReplaceAll(code_
); 
 543         CYImplicitReturn(code_
); 
 545     if (CYIdentifier 
*identifier 
= this_
.identifier_
) { 
 546         context
.scope_
->Declare(context
, identifier
, CYIdentifierVariable
); 
 548             ->* $
E($ 
CYAssign($
V(identifier
), $ 
CYThis())) 
 553         context
.NonLocal(code_
); 
 555     context
.nextlocal_ 
= nextlocal
; 
 556     context
.nonlocal_ 
= nonlocal
; 
 558     context
.super_ 
= super
; 
 559     context
.this_ 
= _this
; 
 561     scope
.Close(context
, code_
); 
 564 CYTarget 
*CYFunctionExpression::Replace(CYContext 
&context
) { 
 565     CYScope 
scope(false, context
); 
 567         name_ 
= name_
->Replace(context
, CYIdentifierOther
); 
 569     CYFunction::Replace(context
); 
 570     scope
.Close(context
); 
 574 void CYFunctionParameter::Replace(CYContext 
&context
, CYStatement 
*&statements
) { $
T() 
 575     CYAssignment 
*assignment(initialiser_
->Replace(context
, CYIdentifierArgument
)); 
 577     next_
->Replace(context
, statements
); 
 579     if (assignment 
!= NULL
) 
 581             ->* $ 
CYIf($ 
CYIdentical($ 
CYTypeOf(initialiser_
->Target(context
)), $
S("undefined")), $$
 
 586 CYStatement 
*CYFunctionStatement::Replace(CYContext 
&context
) { 
 587     name_ 
= name_
->Replace(context
, CYIdentifierOther
); 
 588     CYFunction::Replace(context
); 
 592 CYIdentifier 
*CYIdentifier::Replace(CYContext 
&context
, CYIdentifierKind kind
) { 
 596         return next_
->Replace(context
, kind
); 
 597     next_ 
= context
.scope_
->Declare(context
, this, kind
)->identifier_
; 
 601 CYStatement 
*CYIf::Return() { 
 602     CYImplicitReturn(true_
); 
 603     CYImplicitReturn(false_
); 
 607 CYStatement 
*CYIf::Replace(CYContext 
&context
) { 
 608     context
.Replace(test_
); 
 609     context
.ReplaceAll(true_
); 
 610     context
.ReplaceAll(false_
); 
 614 CYFunctionParameter 
*CYIfComprehension::Parameter(CYContext 
&context
) const { 
 618 CYStatement 
*CYIfComprehension::Replace(CYContext 
&context
, CYStatement 
*statement
) const { 
 619     return $ 
CYIf(test_
, CYComprehension::Replace(context
, statement
)); 
 622 CYStatement 
*CYImport::Replace(CYContext 
&context
) { 
 623     return $ 
CYVar($
L1($
L($
I(module_
->part_
->Word()), $
C1($
V("require"), module_
->Replace(context
, "/"))))); 
 626 CYTarget 
*CYIndirect::Replace(CYContext 
&context
) { 
 627     return $
M(rhs_
, $
S("$cyi")); 
 630 CYTarget 
*CYIndirectMember::Replace(CYContext 
&context
) { 
 631     return $
M($ 
CYIndirect(object_
), property_
); 
 634 CYExpression 
*CYInfix::Replace(CYContext 
&context
) { 
 635     context
.Replace(lhs_
); 
 636     context
.Replace(rhs_
); 
 640 CYStatement 
*CYLabel::Replace(CYContext 
&context
) { 
 641     context
.Replace(statement_
); 
 645 CYTarget 
*CYLambda::Replace(CYContext 
&context
) { 
 646     return $
N2($
V("Functor"), $ 
CYFunctionExpression(NULL
, parameters_
->Parameters(context
), code_
), parameters_
->TypeSignature(context
, typed_
->Replace(context
))); 
 649 CYForInitializer 
*CYLet::Replace(CYContext 
&context
) { 
 650     if (CYExpression 
*expression 
= declarations_
->Replace(context
, CYIdentifierLexical
)) 
 651         return $
E(expression
); 
 655 CYFunctionExpression 
*CYMethod::Constructor() { 
 659 void CYMethod::Replace(CYContext 
&context
) { 
 660     CYFunction::Replace(context
); 
 663 CYString 
*CYModule::Replace(CYContext 
&context
, const char *separator
) const { 
 665         return $ 
CYString(part_
); 
 666     return $ 
CYString($pool
.strcat(next_
->Replace(context
, separator
)->Value(), separator
, part_
->Word(), NULL
)); 
 669 CYExpression 
*CYMultiply::Replace(CYContext 
&context
) { 
 670     CYInfix::Replace(context
); 
 672     if (CYNumber 
*lhn 
= lhs_
->Number(context
)) 
 673         if (CYNumber 
*rhn 
= rhs_
->Number(context
)) 
 674             return $
D(lhn
->Value() * rhn
->Value()); 
 682 CYTarget 
*New::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 683     CYSetLast(arguments_
) = $ 
CYArgument(value
); 
 687 CYTarget 
*New::Replace(CYContext 
&context
) { 
 688     context
.Replace(constructor_
); 
 689     arguments_
->Replace(context
); 
 695 CYNumber 
*CYNull::Number(CYContext 
&context
) { 
 699 CYString 
*CYNull::String(CYContext 
&context
) { 
 703 CYNumber 
*CYNumber::Number(CYContext 
&context
) { 
 707 CYString 
*CYNumber::String(CYContext 
&context
) { 
 708     // XXX: there is a precise algorithm for this 
 709     return $
S($pool
.sprintf(24, "%.17g", Value())); 
 712 CYExpression 
*CYNumber::PropertyName(CYContext 
&context
) { 
 713     return String(context
); 
 716 CYTarget 
*CYObject::Replace(CYContext 
&context
) { 
 718     if (properties_ 
!= NULL
) 
 719         properties_ 
= properties_
->ReplaceAll(context
, builder
, $ 
CYThis(), false); 
 722         return $
C1($
M($ 
CYFunctionExpression(NULL
, builder
.declarations_
->Parameter(context
), 
 724                 ->* $ 
CYReturn($ 
CYThis()) 
 725         ), $
S("call")), this, builder
.declarations_
->Argument(context
)); 
 728     CYForEach (property
, properties_
) 
 729         property
->Replace(context
); 
 733 CYTarget 
*CYParenthetical::Replace(CYContext 
&context
) { 
 734     // XXX: return expression_; 
 735     context
.Replace(expression_
); 
 739 CYExpression 
*CYPostfix::Replace(CYContext 
&context
) { 
 740     context
.Replace(lhs_
); 
 744 CYExpression 
*CYPrefix::Replace(CYContext 
&context
) { 
 745     context
.Replace(rhs_
); 
 749 CYProperty 
*CYProperty::ReplaceAll(CYContext 
&context
, CYBuilder 
&builder
, CYExpression 
*self
, bool update
) { 
 752         Replace(context
, builder
, self
, false); 
 754         next_ 
= next_
->ReplaceAll(context
, builder
, self
, update
); 
 755     return update 
? next_ 
: this; 
 758 void CYProperty::Replace(CYContext 
&context
, CYBuilder 
&builder
, CYExpression 
*self
, bool protect
) { 
 759     CYExpression 
*name(name_
->PropertyName(context
)); 
 760     if (name_
->Computed()) { 
 761         CYIdentifier 
*unique(context
.Unique()); 
 762         builder
.declarations_
 
 763             ->* $
L1($
L(unique
, name
)); 
 767     Replace(context
, builder
, self
, name
, protect
); 
 770 bool CYProperty::Update() const { 
 771     return name_
->Computed(); 
 774 void CYPropertyGetter::Replace(CYContext 
&context
, CYBuilder 
&builder
, CYExpression 
*self
, CYExpression 
*name
, bool protect
) { 
 775     CYIdentifier 
*unique(context
.Unique()); 
 776     builder
.declarations_
 
 777         ->* $
L1($
L(unique
, CYSuperize(context
, $ 
CYFunctionExpression(NULL
, parameters_
, code_
)))); 
 779         ->* CYDefineProperty(self
, name
, true, !protect
, $ 
CYPropertyValue($
S("get"), $
V(unique
))); 
 782 CYFunctionExpression 
*CYPropertyMethod::Constructor() { 
 783     return name_
->Constructor() ? $ 
CYFunctionExpression(NULL
, parameters_
, code_
) : NULL
; 
 786 void CYPropertyMethod::Replace(CYContext 
&context
, CYBuilder 
&builder
, CYExpression 
*self
, CYExpression 
*name
, bool protect
) { 
 787     CYIdentifier 
*unique(context
.Unique()); 
 788     builder
.declarations_
 
 789         ->* $
L1($
L(unique
, CYSuperize(context
, $ 
CYFunctionExpression(NULL
, parameters_
, code_
)))); 
 791         ->* (!protect 
? $
E($ 
CYAssign($
M(self
, name
), $
V(unique
))) : 
 792             CYDefineProperty(self
, name
, true, !protect
, $ 
CYPropertyValue($
S("value"), $
V(unique
), $ 
CYPropertyValue($
S("writable"), $ 
CYTrue())))); 
 795 bool CYPropertyMethod::Update() const { 
 799 void CYPropertySetter::Replace(CYContext 
&context
, CYBuilder 
&builder
, CYExpression 
*self
, CYExpression 
*name
, bool protect
) { 
 800     CYIdentifier 
*unique(context
.Unique()); 
 801     builder
.declarations_
 
 802         ->* $
L1($
L(unique
, CYSuperize(context
, $ 
CYFunctionExpression(NULL
, parameters_
, code_
)))); 
 804         ->* CYDefineProperty(self
, name
, true, !protect
, $ 
CYPropertyValue($
S("set"), $
V(unique
))); 
 807 void CYPropertyValue::Replace(CYContext 
&context
, CYBuilder 
&builder
, CYExpression 
*self
, CYExpression 
*name
, bool protect
) { 
 809     CYIdentifier 
*unique(context
.Unique()); 
 810     builder
.declarations_
 
 811         ->* $
L1($
L(unique
, value_
)); 
 813         ->* $
E($ 
CYAssign($
M(self
, name
), $
V(unique
))); 
 816 void CYPropertyValue::Replace(CYContext 
&context
) { 
 817     context
.Replace(value_
); 
 820 void CYScript::Replace(CYContext 
&context
) { 
 821     CYScope 
scope(false, context
); 
 822     context
.scope_
->Damage(); 
 824     context
.nextlocal_ 
= $ 
CYNonLocal(); 
 825     context
.ReplaceAll(code_
); 
 826     context
.NonLocal(code_
); 
 828     scope
.Close(context
, code_
); 
 832     for (std::vector
<CYIdentifier 
*>::const_iterator 
i(context
.replace_
.begin()); i 
!= context
.replace_
.end(); ++i
) { 
 834         if (context
.options_
.verbose_
) 
 835             name 
= $pool
.strcat("$", $pool
.itoa(offset
++), NULL
); 
 841             unsigned position(7), local(offset
++ + 1); 
 844                 unsigned index(local 
% (sizeof(MappingSet
) - 1)); 
 845                 local 
/= sizeof(MappingSet
) - 1; 
 846                 id
[--position
] = MappingSet
[index
]; 
 847             } while (local 
!= 0); 
 849             if (scope
.Lookup(context
, id 
+ position
) != NULL
) 
 851             // XXX: at some point, this could become a keyword 
 853             name 
= $pool
.strmemdup(id 
+ position
, 7 - position
); 
 856         CYIdentifier 
*identifier(*i
); 
 857         _assert(identifier
->next_ 
== identifier
); 
 858         identifier
->next_ 
= $
I(name
); 
 862 CYStatement 
*CYReturn::Replace(CYContext 
&context
) { 
 863     if (context
.nonlocal_ 
!= NULL
) { 
 864         CYProperty 
*value(value_ 
== NULL 
? NULL 
: $ 
CYPropertyValue($
S("$cyv"), value_
)); 
 865         return $ 
cy::Syntax::Throw($ 
CYObject( 
 866             $ 
CYPropertyValue($
S("$cyk"), $
V(context
.nonlocal_
->Target(context
)), value
) 
 870     context
.Replace(value_
); 
 874 CYTarget 
*CYRubyBlock::Replace(CYContext 
&context
) { 
 875     return call_
->AddArgument(context
, proc_
->Replace(context
)); 
 878 CYTarget 
*CYRubyBlock::AddArgument(CYContext 
&context
, CYExpression 
*value
) { 
 879     return Replace(context
)->AddArgument(context
, value
); 
 882 CYTarget 
*CYRubyProc::Replace(CYContext 
&context
) { 
 883     CYFunctionExpression 
*function($ 
CYFunctionExpression(NULL
, parameters_
, code_
)); 
 884     function 
= CYNonLocalize(context
, function
); 
 885     function
->implicit_ 
= true; 
 889 CYScope::CYScope(bool transparent
, CYContext 
&context
) : 
 890     transparent_(transparent
), 
 891     parent_(context
.scope_
), 
 896     _assert(!transparent_ 
|| parent_ 
!= NULL
); 
 897     context
.scope_ 
= this; 
 900 void CYScope::Damage() { 
 906 CYIdentifierFlags 
*CYScope::Lookup(CYContext 
&context
, const char *word
) { 
 907     CYForEach (i
, internal_
) 
 908         if (strcmp(i
->identifier_
->Word(), word
) == 0) 
 913 CYIdentifierFlags 
*CYScope::Lookup(CYContext 
&context
, CYIdentifier 
*identifier
) { 
 914     return Lookup(context
, identifier
->Word()); 
 917 CYIdentifierFlags 
*CYScope::Declare(CYContext 
&context
, CYIdentifier 
*identifier
, CYIdentifierKind kind
) { 
 918     _assert(identifier
->next_ 
== NULL 
|| identifier
->next_ 
== identifier
); 
 920     CYIdentifierFlags 
*existing(Lookup(context
, identifier
)); 
 921     if (existing 
== NULL
) 
 922         internal_ 
= $ 
CYIdentifierFlags(identifier
, kind
, internal_
); 
 924     if (existing 
== NULL
) 
 927     if (kind 
== CYIdentifierGlobal
); 
 928     else if (existing
->kind_ 
== CYIdentifierGlobal 
|| existing
->kind_ 
== CYIdentifierMagic
) 
 929         existing
->kind_ 
= kind
; 
 930     else if (existing
->kind_ 
== CYIdentifierLexical 
|| kind 
== CYIdentifierLexical
) 
 931         _assert(false); // XXX: throw new SyntaxError() 
 936 void CYScope::Merge(CYContext 
&context
, const CYIdentifierFlags 
*flags
) { 
 937     _assert(flags
->identifier_
->next_ 
== flags
->identifier_
); 
 938     CYIdentifierFlags 
*existing(Declare(context
, flags
->identifier_
, flags
->kind_
)); 
 939     flags
->identifier_
->next_ 
= existing
->identifier_
; 
 941     existing
->count_ 
+= flags
->count_
; 
 942     if (existing
->offset_ 
< flags
->offset_
) 
 943         existing
->offset_ 
= flags
->offset_
; 
 946 void CYScope::Close(CYContext 
&context
, CYStatement 
*&statements
) { 
 949     CYList
<CYDeclarations
> declarations
; 
 951     CYForEach (i
, internal_
) 
 952         if (i
->kind_ 
== CYIdentifierVariable
) 
 954                 ->* $ 
CYDeclarations($ 
CYDeclaration(i
->identifier_
)); 
 957         CYVar 
*var($ 
CYVar(declarations
)); 
 958         var
->SetNext(statements
); 
 963 void CYScope::Close(CYContext 
&context
) { 
 964     context
.scope_ 
= parent_
; 
 966     CYForEach (i
, internal_
) { 
 967         _assert(i
->identifier_
->next_ 
== i
->identifier_
); 
 969         case CYIdentifierArgument
: { 
 970             _assert(!transparent_
); 
 973         case CYIdentifierLexical
: { 
 975                 CYIdentifier 
*replace(context
.Unique()); 
 976                 replace
->next_ 
= replace
; 
 977                 i
->identifier_
->next_ 
= replace
; 
 978                 i
->identifier_ 
= replace
; 
 982                 i
->kind_ 
= CYIdentifierVariable
; 
 984                 parent_
->Declare(context
, i
->identifier_
, CYIdentifierVariable
); 
 987         case CYIdentifierVariable
: { 
 989                 parent_
->Declare(context
, i
->identifier_
, i
->kind_
); 
 990                 i
->kind_ 
= CYIdentifierGlobal
; 
 998     typedef std::multimap
<unsigned, CYIdentifier 
*> CYIdentifierOffsetMap
; 
 999     CYIdentifierOffsetMap offsets
; 
1001     CYForEach (i
, internal_
) { 
1002         _assert(i
->identifier_
->next_ 
== i
->identifier_
); 
1004         case CYIdentifierArgument
: 
1005         case CYIdentifierVariable
: 
1006             offsets
.insert(CYIdentifierOffsetMap::value_type(i
->offset_
, i
->identifier_
)); 
1012     for (CYIdentifierOffsetMap::const_iterator 
i(offsets
.begin()); i 
!= offsets
.end(); ++i
) { 
1013         if (offset 
< i
->first
) 
1015         CYIdentifier 
*identifier(i
->second
); 
1017         if (offset 
>= context
.replace_
.size()) 
1018             context
.replace_
.resize(offset 
+ 1, NULL
); 
1019         CYIdentifier 
*&replace(context
.replace_
[offset
++]); 
1021         if (replace 
== NULL
) 
1022             replace 
= identifier
; 
1024             _assert(replace
->next_ 
== replace
); 
1025             identifier
->next_ 
= replace
; 
1029     if (parent_ 
== NULL
) 
1032     CYForEach (i
, internal_
) { 
1034         case CYIdentifierGlobal
: { 
1035             if (i
->offset_ 
< offset
) 
1036                 i
->offset_ 
= offset
; 
1037             parent_
->Merge(context
, i
); 
1042 CYElementValue 
*CYSpan::Replace(CYContext 
&context
) { $
T(NULL
) 
1043     return $ 
CYElementValue(expression_
, $ 
CYElementValue(string_
, next_
->Replace(context
))); 
1046 CYStatement 
*CYStatement::Return() { 
1050 CYString 
*CYString::Concat(CYContext 
&context
, CYString 
*rhs
) const { 
1051     size_t size(size_ 
+ rhs
->size_
); 
1052     char *value($ 
char[size 
+ 1]); 
1053     memcpy(value
, value_
, size_
); 
1054     memcpy(value 
+ size_
, rhs
->value_
, rhs
->size_
); 
1056     return $
S(value
, size
); 
1059 CYNumber 
*CYString::Number(CYContext 
&context
) { 
1060     // XXX: there is a precise algorithm for this 
1064 CYExpression 
*CYString::PropertyName(CYContext 
&context
) { 
1068 CYString 
*CYString::String(CYContext 
&context
) { 
1072 CYTarget 
*CYSuperAccess::Replace(CYContext 
&context
) { 
1073     return $
C1($
M($
M($
M($
V(context
.super_
), $
S("prototype")), property_
), $
S("bind")), $ 
CYThis()); 
1076 CYTarget 
*CYSuperCall::Replace(CYContext 
&context
) { 
1077     return $
C($
C1($
M($
V(context
.super_
), $
S("bind")), $ 
CYThis()), arguments_
); 
1080 CYStatement 
*CYSwitch::Replace(CYContext 
&context
) { 
1081     context
.Replace(value_
); 
1082     clauses_
->Replace(context
); 
1086 CYStatement 
*CYTarget::Initialize(CYContext 
&context
, CYExpression 
*value
) { 
1089     return $
E($ 
CYAssign(this, value
)); 
1092 CYTarget 
*CYTemplate::Replace(CYContext 
&context
) { 
1093     return $
C2($
M($
M($
M($
V("String"), $
S("prototype")), $
S("concat")), $
S("apply")), $
S(""), $ 
CYArray($ 
CYElementValue(string_
, spans_
->Replace(context
)))); 
1096 CYTarget 
*CYThis::Replace(CYContext 
&context
) { 
1097     if (context
.this_ 
!= NULL
) 
1098         return $
V(context
.this_
->Identifier(context
)); 
1105 CYStatement 
*Throw::Replace(CYContext 
&context
) { 
1106     context
.Replace(value_
); 
1112 CYTarget 
*CYTrivial::Replace(CYContext 
&context
) { 
1116 CYNumber 
*CYTrue::Number(CYContext 
&context
) { 
1120 CYString 
*CYTrue::String(CYContext 
&context
) { 
1127 CYStatement 
*Try::Replace(CYContext 
&context
) { 
1128     CYScope 
scope(true, context
); 
1129     context
.ReplaceAll(code_
); 
1130     scope
.Close(context
); 
1132     catch_
->Replace(context
); 
1133     finally_
->Replace(context
); 
1139 CYTarget 
*CYTypeArrayOf::Replace_(CYContext 
&context
, CYTarget 
*type
) { 
1140     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("arrayOf")), $ 
CYArgument(size_
))); 
1143 CYTarget 
*CYTypeBlockWith::Replace_(CYContext 
&context
, CYTarget 
*type
) { 
1144     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("blockWith")), parameters_
->Argument(context
))); 
1147 CYTarget 
*CYTypeConstant::Replace_(CYContext 
&context
, CYTarget 
*type
) { 
1148     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("constant")))); 
1151 CYStatement 
*CYTypeDefinition::Replace(CYContext 
&context
) { 
1152     return $
E($ 
CYAssign($
V(typed_
->identifier_
), typed_
->Replace(context
))); 
1155 CYTarget 
*CYTypeError::Replace(CYContext 
&context
) { 
1160 CYTarget 
*CYTypeModifier::Replace(CYContext 
&context
, CYTarget 
*type
) { $
T(type
) 
1161     return Replace_(context
, type
); 
1164 CYTarget 
*CYTypeFunctionWith::Replace_(CYContext 
&context
, CYTarget 
*type
) { 
1165     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("functionWith")), parameters_
->Argument(context
))); 
1168 CYTarget 
*CYTypeLong::Replace(CYContext 
&context
) { 
1169     return $ 
CYCall($ 
CYDirectMember(specifier_
->Replace(context
), $ 
CYString("long"))); 
1172 CYTarget 
*CYTypePointerTo::Replace_(CYContext 
&context
, CYTarget 
*type
) { 
1173     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("pointerTo")))); 
1176 CYTarget 
*CYTypeShort::Replace(CYContext 
&context
) { 
1177     return $ 
CYCall($ 
CYDirectMember(specifier_
->Replace(context
), $ 
CYString("short"))); 
1180 CYTarget 
*CYTypeSigned::Replace(CYContext 
&context
) { 
1181     return $ 
CYCall($ 
CYDirectMember(specifier_
->Replace(context
), $ 
CYString("signed"))); 
1184 CYTarget 
*CYTypeUnsigned::Replace(CYContext 
&context
) { 
1185     return $ 
CYCall($ 
CYDirectMember(specifier_
->Replace(context
), $ 
CYString("unsigned"))); 
1188 CYTarget 
*CYTypeVariable::Replace(CYContext 
&context
) { 
1192 CYTarget 
*CYTypeVoid::Replace(CYContext 
&context
) { 
1193     return $
N1($
V("Type"), $ 
CYString("v")); 
1196 CYTarget 
*CYTypeVolatile::Replace_(CYContext 
&context
, CYTarget 
*type
) { 
1197     return next_
->Replace(context
, $ 
CYCall($ 
CYDirectMember(type
, $ 
CYString("volatile")))); 
1200 CYTarget 
*CYTypedIdentifier::Replace(CYContext 
&context
) { 
1201     return modifier_
->Replace(context
, specifier_
->Replace(context
)); 
1204 CYTypeFunctionWith 
*CYTypedIdentifier::Function() { 
1205     CYTypeModifier 
**modifier(&modifier_
); 
1206     if (*modifier 
== NULL
) 
1208     while ((*modifier
)->next_ 
!= NULL
) 
1209         modifier 
= &(*modifier
)->next_
; 
1210     CYTypeFunctionWith 
*function((*modifier
)->Function()); 
1211     if (function 
== NULL
) 
1217 CYArgument 
*CYTypedParameter::Argument(CYContext 
&context
) { $
T(NULL
) 
1218     return $ 
CYArgument(typed_
->Replace(context
), next_
->Argument(context
)); 
1221 CYFunctionParameter 
*CYTypedParameter::Parameters(CYContext 
&context
) { $
T(NULL
) 
1222     return $ 
CYFunctionParameter($ 
CYDeclaration(typed_
->identifier_ 
?: context
.Unique()), next_
->Parameters(context
)); 
1225 CYExpression 
*CYTypedParameter::TypeSignature(CYContext 
&context
, CYExpression 
*prefix
) { $
T(prefix
) 
1226     return next_
->TypeSignature(context
, $ 
CYAdd(prefix
, typed_
->Replace(context
))); 
1229 CYForInitializer 
*CYVar::Replace(CYContext 
&context
) { 
1230     if (CYExpression 
*expression 
= declarations_
->Replace(context
, CYIdentifierVariable
)) 
1231         return $
E(expression
); 
1235 CYTarget 
*CYVariable::Replace(CYContext 
&context
) { 
1236     name_ 
= name_
->Replace(context
, CYIdentifierGlobal
); 
1240 CYFunctionParameter 
*CYVariable::Parameter() const { 
1241     return $ 
CYFunctionParameter($ 
CYDeclaration(name_
)); 
1244 CYStatement 
*CYWhile::Replace(CYContext 
&context
) { 
1245     context
.Replace(test_
); 
1246     context
.ReplaceAll(code_
); 
1250 CYStatement 
*CYWith::Replace(CYContext 
&context
) { 
1251     context
.Replace(scope_
); 
1252     context
.ReplaceAll(code_
); 
1256 CYExpression 
*CYWord::PropertyName(CYContext 
&context
) {