From ab2aa221129d1936a866b25679e18445b6c20a77 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Fri, 2 Jul 2010 07:33:05 +0000 Subject: [PATCH] Added RubyProc/Blocks. --- Parser.hpp | 36 ++++++++++++++++++++++++++++++++---- Replace.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/Parser.hpp b/Parser.hpp index 49e0722..2d3a59f 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -357,16 +357,24 @@ struct CYProgram : virtual void Output(CYOutput &out) const; }; +struct CYNonLocal; + struct CYContext { apr_pool_t *pool_; CYOptions &options_; + CYScope *scope_; CYIdentifierUsageVector rename_; + CYNonLocal *nonlocal_; + unsigned unique_; + CYContext(apr_pool_t *pool, CYOptions &options) : pool_(pool), options_(options), - scope_(NULL) + scope_(NULL), + nonlocal_(NULL), + unique_(0) { } @@ -384,6 +392,24 @@ struct CYContext { else break; } } + + void NonLocal(CYStatement *&statements); + CYIdentifier *Unique(); +}; + +struct CYNonLocal { + CYIdentifier *identifier_; + + CYNonLocal() : + identifier_(NULL) + { + } + + CYIdentifier *Target(CYContext &context) { + if (identifier_ == NULL) + identifier_ = context.Unique(); + return identifier_; + } }; struct CYBlock : @@ -1261,7 +1287,7 @@ struct CYObject : { CYProperty *properties_; - CYObject(CYProperty *properties) : + CYObject(CYProperty *properties = NULL) : properties_(properties) { } @@ -1440,11 +1466,13 @@ struct CYFunction { CYIdentifier *name_; CYFunctionParameter *parameters_; CYBlock code_; + CYNonLocal *nonlocal_; CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *statements) : name_(name), parameters_(parameters), - code_(statements) + code_(statements), + nonlocal_(NULL) { } @@ -1623,7 +1651,7 @@ struct Throw : { CYExpression *value_; - Throw(CYExpression *value) : + Throw(CYExpression *value = NULL) : value_(value) { } diff --git a/Replace.cpp b/Replace.cpp index 1285e8f..2115772 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -172,6 +172,28 @@ CYExpression *CYCondition::Replace(CYContext &context) { return this; } +void CYContext::NonLocal(CYStatement *&statements) { + CYContext &context(*this); + + if (nonlocal_->identifier_ != NULL) { + CYVariable *cye($V("$cye")); + CYVariable *unique($ CYVariable(nonlocal_->identifier_)); + + 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); + } +} + +CYIdentifier *CYContext::Unique() { + CYContext &context(*this); + return $ CYIdentifier(apr_psprintf(pool_, "$cy%u", unique_++)); +} + CYStatement *CYContinue::Replace(CYContext &context) { return this; } @@ -354,6 +376,17 @@ void CYFunction::Replace_(CYContext &context, bool outer) { scope.parent_ = context.scope_; context.scope_ = &scope; + bool localize; + if (nonlocal_ != NULL) + localize = false; + else { + localize = true; + nonlocal_ = $ CYNonLocal(); + } + + CYNonLocal *nonlocal(context.nonlocal_); + context.nonlocal_ = nonlocal_; + if (!outer && name_ != NULL) Inject(context); @@ -361,6 +394,10 @@ void CYFunction::Replace_(CYContext &context, bool outer) { parameters_ = parameters_->Replace(context, code_); code_.Replace(context); + if (localize) + context.NonLocal(code_.statements_); + context.nonlocal_ = nonlocal; + context.scope_ = scope.parent_; scope.Scope(context, code_.statements_); } @@ -515,7 +552,11 @@ void CYProgram::Replace(CYContext &context) { CYScope scope; scope.parent_ = context.scope_; context.scope_ = &scope; + + context.nonlocal_ = $ CYNonLocal(); statements_ = statements_->ReplaceAll(context); + context.NonLocal(statements_); + context.scope_ = scope.parent_; scope.Scope(context, statements_); @@ -572,6 +613,13 @@ void CYProperty::Replace(CYContext &context) { $T() } CYStatement *CYReturn::Replace(CYContext &context) { + if (context.nonlocal_ != NULL) { + CYProperty *value(value_ == NULL ? NULL : $ CYProperty($S("$cyv"), value_)); + return $ cy::Syntax::Throw($ CYObject( + $ CYProperty($S("$cyk"), $ CYVariable(context.nonlocal_->Target(context)), value) + )); + } + context.Replace(value_); return this; } @@ -582,7 +630,9 @@ CYExpression *CYRubyBlock::Replace(CYContext &context) { } CYExpression *CYRubyProc::Replace(CYContext &context) { - return $ CYFunctionExpression(NULL, parameters_, code_); + CYFunctionExpression *function($ CYFunctionExpression(NULL, parameters_, code_)); + function->nonlocal_ = context.nonlocal_; + return function; } void CYScope::Declare(CYContext &context, CYIdentifier *identifier, CYIdentifierFlags flags) { -- 2.47.2