X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/4e3c905634abeaeea78747ce2be0adce06cc777a..51b2dc6b0c969f9297c8464cb91e93d65819e0ae:/Replace.cpp?ds=inline diff --git a/Replace.cpp b/Replace.cpp index 54e931e..ac673ad 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -29,6 +29,18 @@ CYFunctionExpression *CYNonLocalize(CYContext &context, CYFunctionExpression *fu return function; } +CYFunctionExpression *CYSuperize(CYContext &context, CYFunctionExpression *function) { + function->super_ = context.super_; + return function; +} + +CYStatement *CYDefineProperty(CYExpression *object, CYExpression *name, bool configurable, bool enumerable, CYProperty *descriptor) { + return $E($C3($M($V("Object"), $S("defineProperty")), object, name, $ CYObject(CYList() + ->* (configurable ? $ CYPropertyValue($S("configurable"), $ CYTrue()) : NULL) + ->* (enumerable ? $ CYPropertyValue($S("enumerable"), $ CYTrue()) : NULL) + ->* descriptor))); +} + static void CYImplicitReturn(CYStatement *&code) { if (CYStatement *&last = CYGetLast(code)) last = last->Return(); @@ -88,7 +100,7 @@ CYExpression *CYArray::Replace(CYContext &context) { CYExpression *CYArrayComprehension::Replace(CYContext &context) { CYVariable *cyv($V("$cyv")); - return $C0($F(NULL, $P1($L("$cyv"), comprehensions_->Parameters(context)), $$->* + return $C0($F(NULL, $P1($L($I("$cyv")), comprehensions_->Parameters(context)), $$->* $E($ CYAssign(cyv, $ CYArray()))->* comprehensions_->Replace(context, $E($C1($M(cyv, $S("push")), expression_)))->* $ CYReturn(cyv) @@ -146,6 +158,45 @@ void Catch::Replace(CYContext &context) { $T() } } +CYExpression *CYClassExpression::Replace(CYContext &context) { + CYBuilder builder; + + CYIdentifier *super(context.Unique()); + + CYIdentifier *old(context.super_); + context.super_ = super; + + CYIdentifier *constructor(context.Unique()); + CYForEach (member, tail_->static_) + member->Replace(context, builder, $V(constructor), true); + + CYIdentifier *prototype(context.Unique()); + CYForEach (member, tail_->instance_) + member->Replace(context, builder, $V(prototype), true); + + if (tail_->constructor_ == NULL) + tail_->constructor_ = $ CYFunctionExpression(NULL, NULL, NULL); + tail_->constructor_ = CYSuperize(context, tail_->constructor_); + + context.super_ = old; + + return $C1($ CYFunctionExpression(NULL, $P($L(super)), $$ + ->* $ CYVar($L1($L(constructor, tail_->constructor_))) + ->* $ CYVar($L1($L(prototype, $ CYFunctionExpression(NULL, NULL, NULL)))) + ->* $E($ CYAssign($M($V(prototype), $S("prototype")), $M($V(super), $S("prototype")))) + ->* $E($ CYAssign($V(prototype), $N($V(prototype)))) + ->* CYDefineProperty($V(prototype), $S("constructor"), false, false, $ CYPropertyValue($S("value"), $V(constructor))) + ->* $ CYVar(builder.declarations_) + ->* builder.statements_ + ->* CYDefineProperty($V(constructor), $S("prototype"), false, false, $ CYPropertyValue($S("value"), $V(prototype))) + ->* $ CYReturn($V(constructor)) + ), tail_->extends_ ?: $V($I("Object"))); +} + +CYStatement *CYClassStatement::Replace(CYContext &context) { + return $ CYVar($L1($L(name_, $ CYClassExpression(name_, tail_)))); +} + void CYClause::Replace(CYContext &context) { $T() context.Replace(case_); context.ReplaceAll(code_); @@ -192,6 +243,10 @@ CYStatement *CYComprehension::Replace(CYContext &context, CYStatement *statement return next_ == NULL ? statement : next_->Replace(context, statement); } +CYExpression *CYComputed::PropertyName(CYContext &context) { + return expression_; +} + CYExpression *CYCondition::Replace(CYContext &context) { context.Replace(test_); context.Replace(true_); @@ -207,7 +262,7 @@ void CYContext::NonLocal(CYStatement *&statements) { CYIdentifier *unique(nextlocal_->identifier_->Replace(context)); CYStatement *declare( - $ CYVar($L1($ CYDeclaration(unique, $ CYObject())))); + $ CYVar($L1($L(unique, $ CYObject())))); cy::Syntax::Catch *rescue( $ cy::Syntax::Catch(cye, $$->* @@ -265,10 +320,6 @@ void CYDeclarations::Replace(CYContext &context) { $T() next_->Replace(context); } -CYProperty *CYDeclarations::Property(CYContext &context) { $T(NULL) - return $ CYProperty(declaration_->identifier_, declaration_->initialiser_, next_->Property(context)); -} - CYFunctionParameter *CYDeclarations::Parameter(CYContext &context) { $T(NULL) return $ CYFunctionParameter($ CYDeclaration(declaration_->identifier_), next_->Parameter(context)); } @@ -330,10 +381,6 @@ CYExpression *CYExpression::AddArgument(CYContext &context, CYExpression *value) return $C1(this, value); } -CYExpression *CYExpression::ClassName(CYContext &context, bool object) { - return this; -} - CYStatement *CYExpression::ForEachIn(CYContext &context, CYExpression *value) { return $E($ CYAssign(this, value)); } @@ -410,14 +457,14 @@ CYStatement *CYForOf::Replace(CYContext &context) { this ); - CYIdentifier *cys($I("$cys")), *cyt($I("$cyt")); + CYIdentifier *cys(context.Unique()), *cyt(context.Unique()); - return $ CYLetStatement($L2($ CYDeclaration(cys, set_), $ CYDeclaration(cyt)), $$->* - $ CYForIn($V(cyt), $V(cys), $ CYBlock($$->* - initialiser_->ForEachIn(context, $M($V(cys), $V(cyt)))->* - code_ - )) - ); + return $ CYBlock($$ + ->* $ CYLet($L2($L(cys, set_), $L(cyt))) + ->* $ CYForIn($V(cyt), $V(cys), $ CYBlock($$ + ->* initialiser_->ForEachIn(context, $M($V(cys), $V(cyt))) + ->* code_ + ))); } CYFunctionParameter *CYForOfComprehension::Parameter(CYContext &context) const { @@ -427,7 +474,7 @@ CYFunctionParameter *CYForOfComprehension::Parameter(CYContext &context) const { CYStatement *CYForOfComprehension::Replace(CYContext &context, CYStatement *statement) const { CYIdentifier *cys($I("$cys")); - return $E($C0($F(NULL, $P1($L("$cys")), $$->* + return $E($C0($F(NULL, $P1($L($I("$cys"))), $$->* $E($ CYAssign($V(cys), set_))->* $ CYForIn(declaration_->Variable(context), $V(cys), $ CYBlock($$->* $E($ CYAssign(declaration_->Variable(context), $M($V(cys), declaration_->Variable(context))))->* @@ -436,19 +483,14 @@ CYStatement *CYForOfComprehension::Replace(CYContext &context, CYStatement *stat ))); } -void CYFunction::Inject(CYContext &context) { - context.Replace(name_); - context.scope_->Declare(context, name_, CYIdentifierOther); -} - -void CYFunction::Replace_(CYContext &context, bool outer) { - if (outer) - Inject(context); - +void CYFunction::Replace(CYContext &context) { CYThisScope *_this(context.this_); context.this_ = &this_; context.this_ = CYGetLast(context.this_); + CYIdentifier *super(context.super_); + context.super_ = super_; + CYNonLocal *nonlocal(context.nonlocal_); CYNonLocal *nextlocal(context.nextlocal_); @@ -464,19 +506,20 @@ void CYFunction::Replace_(CYContext &context, bool outer) { CYScope scope(!localize, context); - if (!outer && name_ != NULL) - Inject(context); - parameters_->Replace(context, code_); + context.ReplaceAll(code_); if (implicit_) CYImplicitReturn(code_); - if (CYIdentifier *identifier = this_.identifier_) - code_ = $$->* - $ CYVar($L1($ CYDeclaration(identifier, $ CYThis())))->* - code_; + if (CYIdentifier *identifier = this_.identifier_) { + context.scope_->Declare(context, identifier, CYIdentifierVariable); + code_ = $$ + ->*$E($ CYAssign($V(identifier), $ CYThis())) + ->*code_ + ; + } if (localize) context.NonLocal(code_); @@ -484,13 +527,18 @@ void CYFunction::Replace_(CYContext &context, bool outer) { context.nextlocal_ = nextlocal; context.nonlocal_ = nonlocal; + context.super_ = super; context.this_ = _this; scope.Close(context, code_); } CYExpression *CYFunctionExpression::Replace(CYContext &context) { - Replace_(context, false); + CYScope scope(false, context); + if (name_ != NULL) + context.scope_->Declare(context, name_, CYIdentifierOther); + CYFunction::Replace(context); + scope.Close(context, code_); return this; } @@ -510,7 +558,8 @@ void CYFunctionParameter::Replace(CYContext &context, CYStatement *&statements) } CYStatement *CYFunctionStatement::Replace(CYContext &context) { - Replace_(context, true); + context.scope_->Declare(context, name_, CYIdentifierOther); + CYFunction::Replace(context); return this; } @@ -543,7 +592,7 @@ CYStatement *CYIfComprehension::Replace(CYContext &context, CYStatement *stateme } CYStatement *CYImport::Replace(CYContext &context) { - return $ CYVar($L1($L(module_->part_->Word(), $C1($V("require"), module_->Replace(context, "/"))))); + return $ CYVar($L1($L($I(module_->part_->Word()), $C1($V("require"), module_->Replace(context, "/"))))); } CYExpression *CYIndirect::Replace(CYContext &context) { @@ -569,8 +618,19 @@ CYExpression *CYLambda::Replace(CYContext &context) { return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_), parameters_->TypeSignature(context, typed_->Replace(context))); } -CYStatement *CYLetStatement::Replace(CYContext &context) { - return $E($ CYCall(CYNonLocalize(context, $ CYFunctionExpression(NULL, declarations_->Parameter(context), code_)), declarations_->Argument(context))); +CYStatement *CYLet::Replace(CYContext &context) { + declarations_->Replace(context); + if (CYExpression *expression = declarations_->Expression(context)) + return $E(expression); + return $ CYEmpty(); +} + +CYFunctionExpression *CYMethod::Constructor() { + return NULL; +} + +void CYMethod::Replace(CYContext &context) { + CYFunction::Replace(context); } CYString *CYModule::Replace(CYContext &context, const char *separator) const { @@ -622,8 +682,24 @@ CYString *CYNumber::String(CYContext &context) { return $S($pool.sprintf(24, "%.17g", Value())); } +CYExpression *CYNumber::PropertyName(CYContext &context) { + return String(context); +} + CYExpression *CYObject::Replace(CYContext &context) { - properties_->Replace(context); + CYBuilder builder; + if (properties_ != NULL) + properties_ = properties_->ReplaceAll(context, builder, $ CYThis(), false); + + if (builder) { + return $C1($M($ CYFunctionExpression(NULL, builder.declarations_->Parameter(context), + builder.statements_->* + $ CYReturn($ CYThis()) + ), $S("call")), this, builder.declarations_->Argument(context)); + } + + CYForEach (property, properties_) + property->Replace(context); return this; } @@ -641,6 +717,68 @@ CYExpression *CYPrefix::Replace(CYContext &context) { return this; } +CYProperty *CYProperty::ReplaceAll(CYContext &context, CYBuilder &builder, CYExpression *self, bool update) { + update |= name_->Computed(); + if (update) + Replace(context, builder, self, false); + if (next_ != NULL) + next_ = next_->ReplaceAll(context, builder, self, update); + return update ? next_ : this; +} + +void CYProperty::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, bool protect) { + CYExpression *name(name_->PropertyName(context)); + if (name_->Computed()) { + CYIdentifier *unique(context.Unique()); + builder.declarations_->*$L1($L(unique, name)); + name = $V(unique); + } + + Replace(context, builder, self, name, protect); +} + +void CYPropertyGetter::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name, bool protect) { + CYIdentifier *unique(context.Unique()); + builder.declarations_ + ->* $L1($L(unique, CYSuperize(context, $ CYFunctionExpression(NULL, parameters_, code_)))); + builder.statements_ + ->* CYDefineProperty(self, name, true, !protect, $ CYPropertyValue($S("get"), $V(unique))); +} + +CYFunctionExpression *CYPropertyMethod::Constructor() { + return name_->Constructor() ? $ CYFunctionExpression(NULL, parameters_, code_) : NULL; +} + +void CYPropertyMethod::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name, bool protect) { + CYIdentifier *unique(context.Unique()); + builder.declarations_ + ->* $L1($L(unique, CYSuperize(context, $ CYFunctionExpression(NULL, parameters_, code_)))); + builder.statements_ + ->* (!protect ? $E($ CYAssign($M(self, name), $V(unique))) : + CYDefineProperty(self, name, true, !protect, $ CYPropertyValue($S("value"), $V(unique), $ CYPropertyValue($S("writable"), $ CYTrue())))); +} + +void CYPropertySetter::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name, bool protect) { + CYIdentifier *unique(context.Unique()); + builder.declarations_ + ->* $L1($L(unique, CYSuperize(context, $ CYFunctionExpression(NULL, parameters_, code_)))); + builder.statements_ + ->* CYDefineProperty(self, name, true, !protect, $ CYPropertyValue($S("set"), $V(unique))); +} + +void CYPropertyValue::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name, bool protect) { + _assert(!protect); + CYIdentifier *unique(context.Unique()); + builder.declarations_ + ->* $L1($L(unique, value_)); + builder.statements_ + ->* $E($ CYAssign($M(self, name), $V(unique))); +} + +void CYPropertyValue::Replace(CYContext &context) { + context.Replace(value_); +} + // XXX: this is evil evil black magic. don't ask, don't tell... don't believe! #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ" //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_" @@ -715,18 +853,11 @@ void CYScript::Replace(CYContext &context) { } } -void CYProperty::Replace(CYContext &context) { $T() - context.Replace(value_); - next_->Replace(context); - if (value_ == NULL) - value_ = $U; -} - CYStatement *CYReturn::Replace(CYContext &context) { if (context.nonlocal_ != NULL) { - CYProperty *value(value_ == NULL ? NULL : $ CYProperty($S("$cyv"), value_)); + CYProperty *value(value_ == NULL ? NULL : $ CYPropertyValue($S("$cyv"), value_)); return $ cy::Syntax::Throw($ CYObject( - $ CYProperty($S("$cyk"), $V(context.nonlocal_->Target(context)), value) + $ CYPropertyValue($S("$cyk"), $V(context.nonlocal_->Target(context)), value) )); } @@ -738,6 +869,10 @@ CYExpression *CYRubyBlock::Replace(CYContext &context) { return call_->AddArgument(context, proc_->Replace(context)); } +CYExpression *CYRubyBlock::AddArgument(CYContext &context, CYExpression *value) { + return Replace(context)->AddArgument(context, value); +} + CYExpression *CYRubyProc::Replace(CYContext &context) { CYFunctionExpression *function($ CYFunctionExpression(NULL, parameters_, code_)); function = CYNonLocalize(context, function); @@ -881,10 +1016,22 @@ CYNumber *CYString::Number(CYContext &context) { return NULL; } +CYExpression *CYString::PropertyName(CYContext &context) { + return this; +} + CYString *CYString::String(CYContext &context) { return this; } +CYExpression *CYSuperAccess::Replace(CYContext &context) { + return $C1($M($M($M($V(context.super_), $S("prototype")), property_), $S("bind")), $ CYThis()); +} + +CYExpression *CYSuperCall::Replace(CYContext &context) { + return $C($C1($M($V(context.super_), $S("bind")), $ CYThis()), arguments_); +} + CYStatement *CYSwitch::Replace(CYContext &context) { context.Replace(value_); clauses_->Replace(context); @@ -1053,10 +1200,6 @@ CYStatement *CYWith::Replace(CYContext &context) { return this; } -CYExpression *CYWord::ClassName(CYContext &context, bool object) { - CYString *name($S(this)); - if (object) - return $C1($V("objc_getClass"), name); - else - return name; +CYExpression *CYWord::PropertyName(CYContext &context) { + return $S(this); }