From 4f3e597ca9a1d3e5ff9e7831c55f32500917d7d7 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 31 Dec 2015 13:38:55 -0800 Subject: [PATCH] Add syntax akin to Java's anonymous inner classes. --- Output.cpp | 7 ++++++- Parser.ypp.in | 34 ++++++++++++++++++++-------------- Replace.cpp | 18 +++++++++++++----- Syntax.hpp | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 83 insertions(+), 26 deletions(-) diff --git a/Output.cpp b/Output.cpp index c436b3c..e8ae4ae 100644 --- a/Output.cpp +++ b/Output.cpp @@ -452,6 +452,11 @@ void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const { Output(out, flags); } +void CYExtend::Output(CYOutput &out, CYFlags flags) const { + lhs_->Output(out, CYLeft(flags)); + out << ' ' << object_; +} + void CYExternal::Output(CYOutput &out, CYFlags flags) const { out << "extern" << abi_ << typed_; out.Terminate(); @@ -872,7 +877,7 @@ void CYReturn::Output(CYOutput &out, CYFlags flags) const { } void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const { - call_->Output(out, CYLeft(flags)); + lhs_->Output(out, CYLeft(flags)); out << ' '; proc_->Output(out, CYRight(flags)); } diff --git a/Parser.ypp.in b/Parser.ypp.in index c2927f2..ffa42cc 100644 --- a/Parser.ypp.in +++ b/Parser.ypp.in @@ -48,6 +48,7 @@ %union { CYBinding *binding_; } %union { CYBindings *bindings_; } %union { CYBoolean *boolean_; } +%union { CYBraced *braced_; } %union { CYClause *clause_; } %union { cy::Syntax::Catch *catch_; } %union { CYClassTail *classTail_; } @@ -71,7 +72,6 @@ %union { CYParenthetical *parenthetical_; } %union { CYProperty *property_; } %union { CYPropertyName *propertyName_; } -%union { CYRubyProc *rubyProc_; } %union { CYSpan *span_; } %union { CYStatement *statement_; } %union { CYString *string_; } @@ -503,6 +503,8 @@ type; }) %type BindingElement %type BitwiseORExpression %type BitwiseXORExpression +%type BracedExpression_ +%type BracedExpression %type BreakStatement %type BreakableStatement %type CallExpression_ @@ -623,9 +625,7 @@ type; }) %type RegularExpressionSlash %type RelationalExpression %type ReturnStatement -%type RubyBlockExpression_ -%type RubyBlockExpression -%type RubyProcExpression +%type BracedParameter %type RubyProcParameterList_ %type RubyProcParameterList %type RubyProcParameters @@ -1233,13 +1233,13 @@ AccessExpression ; LeftHandSideExpression - : RubyBlockExpression[pass] { $$ = $pass; } + : BracedExpression[pass] { $$ = $pass; } | IndirectExpression[pass] { $$ = $pass; } ; /* }}} */ /* 12.4 Postfix Expressions {{{ */ PostfixExpression - : RubyBlockExpression[pass] { $$ = $pass; } + : BracedExpression[pass] { $$ = $pass; } | AccessExpression[lhs] LexNewLineOrOpt "++" { $$ = CYNew CYPostIncrement($lhs); } | AccessExpression[lhs] LexNewLineOrOpt "--" { $$ = CYNew CYPostDecrement($lhs); } ; @@ -1622,7 +1622,7 @@ ForStatementInitializer ; ForInStatementInitializer - : LexLet LexOf RubyBlockExpression[pass] { $$ = $pass; } + : LexLet LexOf BracedExpression[pass] { $$ = $pass; } | LexLet LexOf IndirectExpression[pass] { $$ = $pass; } | LexLet LexOf Var_ LexBind ForBinding[binding] { $$ = CYNew CYForVariable($binding); } | ForDeclaration[pass] { $$ = $pass; } @@ -2665,6 +2665,12 @@ ArgumentList ; /* }}} */ +/* JavaScript FTW: Java "Anonymous Inner Classes" {{{ */ +BracedParameter + : "{" PropertyDefinitionListOpt[properties] "}" { $$ = CYNew CYExtend(NULL, $properties); } + ; +/* }}} */ + /* JavaScript FTW: Ruby Blocks {{{ */ RubyProcParameterList_ : "," RubyProcParameterList[parameters] { $$ = $parameters; } @@ -2686,22 +2692,22 @@ RubyProcParametersOpt | { $$ = NULL; } ; -RubyProcExpression - : "{" RubyProcParametersOpt[parameters] StatementListOpt[code] "}" { $$ = CYNew CYRubyProc($parameters, $code); } +BracedParameter + : ";{" RubyProcParametersOpt[parameters] StatementListOpt[code] "}" { $$ = CYNew CYRubyBlock(NULL, CYNew CYRubyProc($parameters, $code)); } ; PrimaryExpression : "{" RubyProcParameters[parameters] StatementListOpt[code] "}" { $$ = CYNew CYRubyProc($parameters, $code); } ; -RubyBlockExpression_ +BracedExpression_ : AccessExpression[pass] LexNewLineOrOpt { $$ = $pass; } - | RubyBlockExpression_[lhs] RubyProcExpression[rhs] LexNewLineOrOpt { $$ = CYNew CYRubyBlock($lhs, $rhs); } + | BracedExpression_[lhs] { if (!$lhs->IsNew()) CYMAP(OpenBrace_, OpenBrace); } BracedParameter[rhs] LexNewLineOrOpt { $rhs->SetLeft($lhs); $$ = $rhs; } ; -RubyBlockExpression - : RubyBlockExpression_[pass] "\n" { $$ = $pass; } - | RubyBlockExpression_[pass] { $$ = $pass; } +BracedExpression + : BracedExpression_[pass] "\n" { $$ = $pass; } + | BracedExpression_[pass] { $$ = $pass; } ; /* }}} */ /* JavaScript FTW: Ruby Scopes {{{ */ diff --git a/Replace.cpp b/Replace.cpp index ed486f7..7a99296 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -381,6 +381,10 @@ CYFunctionParameter *CYExpression::Parameter() const { return NULL; } +CYTarget *CYExtend::Replace(CYContext &context) { + return object_.Replace(context, lhs_); +} + CYStatement *CYExternal::Replace(CYContext &context) { return $E($ CYAssign($V(typed_->identifier_), $C1(typed_->Replace(context), $C2($V("dlsym"), $V("RTLD_DEFAULT"), $S(typed_->identifier_->Word()))))); } @@ -732,21 +736,25 @@ CYExpression *CYNumber::PropertyName(CYContext &context) { return String(context); } -CYTarget *CYObject::Replace(CYContext &context) { +CYTarget *CYObject::Replace(CYContext &context, CYTarget *seed) { CYBuilder builder; if (properties_ != NULL) - properties_ = properties_->ReplaceAll(context, builder, $ CYThis(), false); + properties_ = properties_->ReplaceAll(context, builder, $ CYThis(), seed != this); if (builder) { return $C1($M($ CYFunctionExpression(NULL, builder.bindings_->Parameter(context), builder.statements_ ->* $ CYReturn($ CYThis()) - ), $S("call")), this, builder.bindings_->Argument(context)); + ), $S("call")), seed, builder.bindings_->Argument(context)); } CYForEach (property, properties_) property->Replace(context); - return this; + return seed; +} + +CYTarget *CYObject::Replace(CYContext &context) { + return Replace(context, this); } CYTarget *CYParenthetical::Replace(CYContext &context) { @@ -895,7 +903,7 @@ CYStatement *CYReturn::Replace(CYContext &context) { } CYTarget *CYRubyBlock::Replace(CYContext &context) { - return call_->AddArgument(context, proc_->Replace(context)); + return lhs_->AddArgument(context, proc_->Replace(context)); } CYTarget *CYRubyBlock::AddArgument(CYContext &context, CYExpression *value) { diff --git a/Syntax.hpp b/Syntax.hpp index a3f03fa..4a93e03 100644 --- a/Syntax.hpp +++ b/Syntax.hpp @@ -535,6 +535,10 @@ struct CYTarget : return false; } + virtual bool IsNew() const { + return false; + } + virtual CYStatement *Initialize(CYContext &context, CYExpression *value); virtual CYTarget *Replace(CYContext &context) = 0; @@ -1416,6 +1420,8 @@ struct CYObject : { } + CYTarget *Replace(CYContext &context, CYTarget *seed); + virtual CYTarget *Replace(CYContext &context); void Output(CYOutput &out, CYFlags flags) const; }; @@ -1498,6 +1504,9 @@ struct New : return arguments_ == NULL ? 2 : 1; } + virtual bool IsNew() const { + return true; + } virtual CYTarget *Replace(CYContext &context); virtual void Output(CYOutput &out, CYFlags flags) const; @@ -1551,26 +1560,55 @@ struct CYEval : struct CYRubyProc; -struct CYRubyBlock : +struct CYBraced : CYTarget { - CYExpression *call_; - CYRubyProc *proc_; + CYTarget *lhs_; - CYRubyBlock(CYExpression *call, CYRubyProc *proc) : - call_(call), - proc_(proc) + CYBraced(CYTarget *lhs = NULL) : + lhs_(lhs) { } CYPrecedence(1) + void SetLeft(CYTarget *lhs) { + lhs_ = lhs; + } +}; + +struct CYRubyBlock : + CYBraced +{ + CYRubyProc *proc_; + + CYRubyBlock(CYTarget *lhs, CYRubyProc *proc) : + CYBraced(lhs), + proc_(proc) + { + } + virtual CYTarget *Replace(CYContext &context); virtual void Output(CYOutput &out, CYFlags flags) const; virtual CYTarget *AddArgument(CYContext &context, CYExpression *value); }; +struct CYExtend : + CYBraced +{ + CYObject object_; + + CYExtend(CYTarget *lhs, CYProperty *properties = NULL) : + CYBraced(lhs), + object_(properties) + { + } + + virtual CYTarget *Replace(CYContext &context); + virtual void Output(CYOutput &out, CYFlags flags) const; +}; + struct CYIf : CYStatement { -- 2.45.2