From 4e11a430b3f7d66b06eaf76035834b55ec4f976b Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 1 Jul 2010 08:01:48 +0000 Subject: [PATCH] Add optional parameter support. --- Cycript.yy.in | 7 +++++++ Output.cpp | 6 ++++++ Parser.hpp | 17 ++++++++++++++++- Replace.cpp | 20 +++++++++++++++++--- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Cycript.yy.in b/Cycript.yy.in index ecfbba1..103deb7 100644 --- a/Cycript.yy.in +++ b/Cycript.yy.in @@ -1843,6 +1843,7 @@ PropertyNameAndValueList_ : "," { $$ = NULL; } ; /* }}} */ + /* JavaScript 1.7: Array Comprehensions {{{ */ IfComprehension : "if" "(" Expression ")" { $$ = new(driver.pool_) CYIfComprehension($3); } @@ -1881,10 +1882,16 @@ Statement_ : LetStatement ; *//* }}} */ + /* JavaScript FTW: Function Statements {{{ */ Statement : LexSetRegExp FunctionDeclaration { driver.Warning(yylloc, "warning, FunctionDeclaration is a SourceElement, not a Statement"); } { $$ = $2; } ; /* }}} */ +/* JavaScript FTW: Optional Arguments {{{ */ +FormalParameterList + : Identifier "=" AssignmentExpression FormalParameterList_ { $$ = new(driver.pool_) CYOptionalFunctionParameter($1, $3, $4); } + ; +/* }}} */ %% diff --git a/Output.cpp b/Output.cpp index d6c3a03..8b77e0e 100644 --- a/Output.cpp +++ b/Output.cpp @@ -560,6 +560,12 @@ void CYObject::Output(CYOutput &out, CYFlags flags) const { out << ')'; } +void CYOptionalFunctionParameter::Output(CYOutput &out) const { + out << *name_ << '=' << *initializer_; + if (next_ != NULL) + out << ',' << ' ' << *next_; +} + void CYPostfix::Output(CYOutput &out, CYFlags flags) const { lhs_->Output(out, Precedence(), CYLeft(flags)); out << Operator(); diff --git a/Parser.hpp b/Parser.hpp index a994ead..1218fe9 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -616,7 +616,22 @@ struct CYFunctionParameter : { } - void Replace(CYContext &context); + virtual CYFunctionParameter *Replace(CYContext &context, CYBlock &code); + virtual void Output(CYOutput &out) const; +}; + +struct CYOptionalFunctionParameter : + CYFunctionParameter +{ + CYExpression *initializer_; + + CYOptionalFunctionParameter(CYIdentifier *name, CYExpression *initializer, CYFunctionParameter *next = NULL) : + CYFunctionParameter(name, next), + initializer_(initializer) + { + } + + virtual CYFunctionParameter *Replace(CYContext &context, CYBlock &code); virtual void Output(CYOutput &out) const; }; diff --git a/Replace.cpp b/Replace.cpp index c06c2a5..f0b0934 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -345,7 +345,7 @@ void CYFunction::Replace_(CYContext &context, bool outer) { if (!outer && name_ != NULL) Inject(context); - parameters_->Replace(context); + parameters_ = parameters_->Replace(context, code_); code_.Replace(context); context.scope_ = scope.parent_; @@ -357,10 +357,12 @@ CYExpression *CYFunctionExpression::Replace(CYContext &context) { return this; } -void CYFunctionParameter::Replace(CYContext &context) { $T() +CYFunctionParameter *CYFunctionParameter::Replace(CYContext &context, CYBlock &code) { name_ = name_->Replace(context); context.scope_->Declare(context, name_, CYIdentifierArgument); - next_->Replace(context); + if (next_ != NULL) + next_ = next_->Replace(context, code); + return this; } CYStatement *CYFunctionStatement::Replace(CYContext &context) { @@ -448,6 +450,18 @@ CYExpression *CYObject::Replace(CYContext &context) { return this; } +CYFunctionParameter *CYOptionalFunctionParameter::Replace(CYContext &context, CYBlock &code) { + CYFunctionParameter *parameter($ CYFunctionParameter(name_, next_)); + parameter = parameter->Replace(context, code); + + CYVariable *name($ CYVariable(name_)); + code.AddPrev($ CYIf($ CYIdentical($ CYTypeOf(name), $S("undefined")), $$->* + $E($ CYAssign(name, initializer_)) + )); + + return parameter; +} + CYExpression *CYPostfix::Replace(CYContext &context) { context.Replace(lhs_); return this; -- 2.45.2