]> git.saurik.com Git - cycript.git/commitdiff
Add optional parameter support.
authorJay Freeman (saurik) <saurik@saurik.com>
Thu, 1 Jul 2010 08:01:48 +0000 (08:01 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Thu, 1 Jul 2010 08:01:48 +0000 (08:01 +0000)
Cycript.yy.in
Output.cpp
Parser.hpp
Replace.cpp

index ecfbba104edee8c89bef2d29be9b3c8a3fff5d7f..103deb70d961c4b15f563395e8ebe974f2763b63 100644 (file)
@@ -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); }
+    ;
+/* }}} */
 
 %%
index d6c3a038aeda70a4d6a1c606e889524c84860f6a..8b77e0ef4c763c749a0782b6848da3323fe8c06b 100644 (file)
@@ -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();
index a994ead8c08a49c36c3c9ea49f1b0827ffac17c9..1218fe91de27c960c5dcbff465c053c52cdb7e9c 100644 (file)
@@ -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;
 };
 
index c06c2a514e91711346494fab13feb64c38c579b5..f0b09344e300eda52d0f6d5fce834f771ce6799a 100644 (file)
@@ -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;