From: Jay Freeman (saurik) Date: Fri, 2 Jul 2010 09:02:06 +0000 (+0000) Subject: Improved scope compliance on catch() while attempting to pesudo-Replace() the non... X-Git-Tag: v0.9.432~32 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/daf22a654ea0e85ead19f2248e3f94d5651a77f5?hp=06293152b6505062453463ef34c0d90e0c8db17e Improved scope compliance on catch() while attempting to pesudo-Replace() the non-local return prologue. --- diff --git a/Parser.hpp b/Parser.hpp index 361beaa..ceb4b6f 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -310,6 +310,7 @@ enum CYIdentifierFlags { CYIdentifierVariable, CYIdentifierOther, CYIdentifierMagic, + CYIdentifierCatch, }; typedef std::set CYCStringSet; @@ -323,19 +324,27 @@ struct CYIdentifierUsage { typedef std::vector CYIdentifierUsageVector; +// XXX: strategy pattern, maybe subclass +enum CYScopeType { + CYScopeCatch, + CYScopeFunction, + CYScopeProgram, +}; + struct CYScope { + CYScopeType type_; + + CYContext &context_; + CYStatement *&statements_; + CYScope *parent_; CYIdentifierAddressFlagsMap internal_; CYIdentifierValueSet identifiers_; - CYScope() : - parent_(NULL) - { - } + CYScope(CYScopeType type, CYContext &context, CYStatement *&statements); - virtual ~CYScope() { - } + void Close(); void Declare(CYContext &context, CYIdentifier *identifier, CYIdentifierFlags flags); virtual CYIdentifier *Lookup(CYContext &context, CYIdentifier *identifier); diff --git a/Replace.cpp b/Replace.cpp index 9cbd30f..3fd02aa 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -132,7 +132,13 @@ namespace cy { namespace Syntax { void Catch::Replace(CYContext &context) { $T() + CYScope scope(CYScopeCatch, context, code_.statements_); + + context.Replace(name_); + context.scope_->Declare(context, name_, CYIdentifierCatch); + code_.Replace(context); + scope.Close(); } } } @@ -176,16 +182,24 @@ void CYContext::NonLocal(CYStatement *&statements) { CYContext &context(*this); if (nextlocal_ != NULL && nextlocal_->identifier_ != NULL) { - CYVariable *cye($V("$cye")); - CYVariable *unique($ CYVariable(nextlocal_->identifier_)); + CYIdentifier *cye($I("$cye")->Replace(context)); + CYIdentifier *unique(nextlocal_->identifier_->Replace(context)); + + CYStatement *declare( + $ CYVar($L1($L(unique, $ CYObject())))); + + cy::Syntax::Catch *rescue( + $ cy::Syntax::Catch(cye, $$->* + $ CYIf($ CYIdentical($M($ CYVariable(cye), $S("$cyk")), $ CYVariable(unique)), $$->* + $ CYReturn($M($ CYVariable(cye), $S("$cyv"))))->* + $ cy::Syntax::Throw($ CYVariable(cye)))); + + declare = declare->Replace(context); + rescue->Replace(context); statements = $$->* - $E($ CYAssign(unique, $ CYObject()))->* - $ cy::Syntax::Try(statements, $ cy::Syntax::Catch(cye->name_, $$->* - $ CYIf($ CYIdentical($M(cye, $S("$cyk")), unique), $$->* - $ CYReturn($M(cye, $S("$cyv"))))->* - $ cy::Syntax::Throw(cye) - ), NULL); + declare->* + $ cy::Syntax::Try(statements, rescue, NULL); } } @@ -372,9 +386,7 @@ void CYFunction::Replace_(CYContext &context, bool outer) { if (outer) Inject(context); - CYScope scope; - scope.parent_ = context.scope_; - context.scope_ = &scope; + CYScope scope(CYScopeFunction, context, code_.statements_); CYNonLocal *nonlocal(context.nonlocal_); CYNonLocal *nextlocal(context.nextlocal_); @@ -394,6 +406,7 @@ void CYFunction::Replace_(CYContext &context, bool outer) { if (parameters_ != NULL) parameters_ = parameters_->Replace(context, code_); + code_.Replace(context); if (localize) @@ -402,8 +415,7 @@ void CYFunction::Replace_(CYContext &context, bool outer) { context.nextlocal_ = nextlocal; context.nonlocal_ = nonlocal; - context.scope_ = scope.parent_; - scope.Scope(context, code_.statements_); + scope.Close(); } CYExpression *CYFunctionExpression::Replace(CYContext &context) { @@ -554,17 +566,13 @@ namespace { } void CYProgram::Replace(CYContext &context) { - CYScope scope; - scope.parent_ = context.scope_; - context.scope_ = &scope; + CYScope scope(CYScopeProgram, context, statements_); context.nextlocal_ = $ CYNonLocal(); - statements_ = statements_->ReplaceAll(context); context.NonLocal(statements_); - context.scope_ = scope.parent_; - scope.Scope(context, statements_); + scope.Close(); size_t offset(0); @@ -641,8 +649,25 @@ CYExpression *CYRubyProc::Replace(CYContext &context) { return function; } +CYScope::CYScope(CYScopeType type, CYContext &context, CYStatement *&statements) : + type_(type), + context_(context), + statements_(statements), + parent_(context.scope_) +{ + context_.scope_ = this; +} + +void CYScope::Close() { + context_.scope_ = parent_; + Scope(context_, statements_); +} + void CYScope::Declare(CYContext &context, CYIdentifier *identifier, CYIdentifierFlags flags) { - internal_.insert(CYIdentifierAddressFlagsMap::value_type(identifier, flags)); + if (type_ == CYScopeCatch && flags != CYIdentifierCatch) + parent_->Declare(context, identifier, flags); + else + internal_.insert(CYIdentifierAddressFlagsMap::value_type(identifier, flags)); } CYIdentifier *CYScope::Lookup(CYContext &context, CYIdentifier *identifier) {