]> git.saurik.com Git - cycript.git/commitdiff
Implement ECMAScript 6 class syntax (sort of?...).
authorJay Freeman (saurik) <saurik@saurik.com>
Mon, 7 Dec 2015 08:49:07 +0000 (00:49 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Mon, 7 Dec 2015 08:49:07 +0000 (00:49 -0800)
12 files changed:
Driver.cpp
Driver.hpp
List.hpp
ObjectiveC/Output.cpp
ObjectiveC/Replace.cpp
ObjectiveC/Syntax.hpp
Output.cpp
Parser.ypp.in
Replace.cpp
Replace.hpp
Scanner.lpp.in
Syntax.hpp

index df31a036935f95f033f1617fa5c83f948854a3fb..83b9462f9199e65d1689a3bc18b99c0fb9c45b75 100644 (file)
@@ -41,6 +41,7 @@ CYDriver::CYDriver(CYPool &pool, std::istream &data, const std::string &filename
 {
     in_.push(false);
     return_.push(false);
+    super_.push(false);
     template_.push(false);
     yield_.push(false);
 
index fbc96d931a53a672fae24c799f7fa2397992c519..8b53c5b4379bf69696bdcb721df7e7ec7bed8e1f 100644 (file)
@@ -33,6 +33,7 @@
 #include "Pooling.hpp"
 #include "Standard.hpp"
 
+struct CYClassTail;
 struct CYExpression;
 struct CYScript;
 struct CYWord;
@@ -53,9 +54,12 @@ class _visible CYDriver {
 
     std::stack<bool> in_;
     std::stack<bool> return_;
+    std::stack<bool> super_;
     std::stack<bool> template_;
     std::stack<bool> yield_;
 
+    std::stack<CYClassTail *> class_;
+
     bool newline_;
     bool last_;
     bool next_;
index 30390eb0786795a40f065eabc2088ac85398d8cf..4caa5361e35db6eceb83f1232c23e078f3b7c7ab 100644 (file)
--- a/List.hpp
+++ b/List.hpp
@@ -63,6 +63,50 @@ Type_ *&CYGetLast(Type_ *&list) {
     return *next;
 }
 
+template <typename Type_>
+struct CYList {
+    Type_ *first_;
+    Type_ *last_;
+
+    CYList(Type_ *first = NULL) :
+        first_(first),
+        last_(CYGetLast(first))
+    {
+    }
+
+    operator Type_ *() const {
+        return first_;
+    }
+
+    Type_ *operator ->() const {
+        return first_;
+    }
+
+    CYList &operator ->*(Type_ *next) {
+        if (next != NULL)
+            if (first_ == NULL) {
+                first_ = next;
+                last_ = next;
+            } else for (;; last_ = last_->next_)
+                if (last_->next_ == NULL) {
+                    last_->next_ = next;
+                    last_ = next;
+                    break;
+                }
+        return *this;
+    }
+
+    CYList &operator ->*(CYList &next) {
+        if (*this == NULL)
+            *this = next;
+        else if (next != NULL) {
+            last_->next_ = next.first_;
+            last_ = next.last_;
+        }
+        return *this;
+    }
+};
+
 #define CYForEach(value, list) \
     for (__typeof__(*list) *value(list); value != NULL; value = value->next_)
 
index 360a54e16c6fa2fa1627d745f49f9eca226a42d7..76838d8815431189cd9922a5a80e80dd69986dbd 100644 (file)
 #include "ObjectiveC/Syntax.hpp"
 
 void CYCategory::Output(CYOutput &out, CYFlags flags) const {
-    out << "(function($cys,$cyp,$cyc,$cyn,$cyt){";
-    out << "$cyp=object_getClass($cys);";
-    out << "$cyc=$cys;";
-    if (messages_ != NULL)
-        messages_->Output(out, true);
-    out << "})(";
-    name_->ClassName(out, true);
-    out << ')';
-    out << ';';
-}
+    out << "@implementation" << ' ' << *name_ << ' ' << '(' << ')' << '\n';
+    ++out.indent_;
 
-void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
-    // XXX: I don't necc. need the ()s
-    out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
-    out << "$cyp=object_getClass($cys);";
-    out << "$cyc=objc_allocateClassPair($cys,";
-    name_->ClassName(out, false);
-    out << ",0);";
-    out << "$cym=object_getClass($cyc);";
-    if (fields_ != NULL)
-        fields_->Output(out);
-    if (messages_ != NULL)
-        messages_->Output(out, false);
-    if (protocols_ != NULL) {
-        out << '<';
-        out << *protocols_;
-        out << '>';
+    CYForEach (message, messages_) {
+        message->Output(out);
+        out << '\n';
     }
-    out << "objc_registerClassPair($cyc);";
-    out << "return $cyc;";
-    out << "}(";
-    if (super_ != NULL)
-        super_->Output(out, CYAssign::Precedence_, CYNoFlags);
-    else
-        out << "null";
-    out << "))";
+
+    --out.indent_;
+    out << "@end";
+}
+
+void CYImplementation::Output(CYOutput &out, CYFlags flags) const {
+    out << "@implementation" << ' ' << *name_ << '\n';
+    ++out.indent_;
+
+    // XXX: implement
+
+    --out.indent_;
+    out << "@end";
 }
 
-void CYClassField::Output(CYOutput &out) const {
+void CYImplementationField::Output(CYOutput &out) const {
 }
 
 void CYInstanceLiteral::Output(CYOutput &out, CYFlags flags) const {
@@ -72,7 +56,7 @@ void CYInstanceLiteral::Output(CYOutput &out, CYFlags flags) const {
     number_->Output(out, CYRight(flags));
 }
 
-void CYMessage::Output(CYOutput &out, bool replace) const {
+void CYMessage::Output(CYOutput &out) const {
     out << (instance_ ? '-' : '+');
 
     CYForEach (parameter, parameters_)
index 74e9227bcf78550c6fecdfb32d27a035b4b5b68b..fb7f1f8c50823ff2791b750476b88c9632f367dd 100644 (file)
@@ -43,22 +43,20 @@ static CYExpression *MessageType(CYContext &context, CYTypedIdentifier *type, CY
 CYStatement *CYCategory::Replace(CYContext &context) {
     CYVariable *cyc($V("$cyc")), *cys($V("$cys"));
 
-    return $E($C1($F(NULL, $P6($L("$cys"), $L("$cyp"), $L("$cyc"), $L("$cyn"), $L("$cyt"), $L("$cym")), $$->*
+    return $E($C1($F(NULL, $P6($L($I("$cys")), $L($I("$cyp")), $L($I("$cyc")), $L($I("$cyn")), $L($I("$cyt")), $L($I("$cym"))), $$->*
         $E($ CYAssign($V("$cyp"), $C1($V("object_getClass"), cys)))->*
         $E($ CYAssign(cyc, cys))->*
         $E($ CYAssign($V("$cym"), $C1($V("object_getClass"), cyc)))->*
         messages_->Replace(context, true)
-    ), name_->ClassName(context, true)));
+    ), $C1($V("objc_getClass"), $S(name_))));
 }
 
-CYStatement *CYClassStatement::Replace(CYContext &context) {
+CYStatement *CYImplementation::Replace(CYContext &context) {
     CYVariable *cyc($V("$cyc")), *cys($V("$cys"));
 
-    CYExpression *name(name_->ClassName(context, false));
-
-    return $E($C1($F(NULL, $P6($L("$cys"), $L("$cyp"), $L("$cyc"), $L("$cyn"), $L("$cyt"), $L("$cym")), $$->*
+    return $E($C1($F(NULL, $P6($L($I("$cys")), $L($I("$cyp")), $L($I("$cyc")), $L($I("$cyn")), $L($I("$cyt")), $L($I("$cym"))), $$->*
         $E($ CYAssign($V("$cyp"), $C1($V("object_getClass"), cys)))->*
-        $E($ CYAssign(cyc, $C3($V("objc_allocateClassPair"), cys, name, $D(0))))->*
+        $E($ CYAssign(cyc, $C3($V("objc_allocateClassPair"), cys, $S(name_), $D(0))))->*
         $E($ CYAssign($V("$cym"), $C1($V("object_getClass"), cyc)))->*
         protocols_->Replace(context)->*
         fields_->Replace(context)->*
@@ -68,7 +66,7 @@ CYStatement *CYClassStatement::Replace(CYContext &context) {
     ), super_ == NULL ? $ CYNull() : super_));
 }
 
-CYStatement *CYClassField::Replace(CYContext &context) const { $T(NULL)
+CYStatement *CYImplementationField::Replace(CYContext &context) const { $T(NULL)
     CYVariable *cyn($V("$cyn"));
     CYVariable *cyt($V("$cyt"));
 
@@ -99,8 +97,8 @@ CYStatement *CYMessage::Replace(CYContext &context, bool replace) const { $T(NUL
         $E($C4($V(replace ? "class_replaceMethod" : "class_addMethod"),
             $V(instance_ ? "$cyc" : "$cym"),
             cyn,
-            $N2($V("Functor"), $F(NULL, $P2($L("self"), $L("_cmd"), parameters_->Parameters(context)), $$->*
-                $ CYVar($L1($L("$cyr", $N2($V("objc_super"), self, _class))))->*
+            $N2($V("Functor"), $F(NULL, $P2($L($I("self")), $L($I("_cmd")), parameters_->Parameters(context)), $$->*
+                $ CYVar($L1($L($I("$cyr"), $N2($V("objc_super"), self, _class))))->*
                 $ CYReturn($C1($M($F(NULL, NULL, code_.code_), $S("call")), self))
             ), cyt),
             cyt
index 025612aba1ab98218928bcf0715e6107ebf72fdc..5f6c726d9286b7d9b2b1cfce1829cc73910fec7d 100644 (file)
@@ -110,13 +110,13 @@ struct CYSelector :
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
-struct CYClassField :
-    CYNext<CYClassField>
+struct CYImplementationField :
+    CYNext<CYImplementationField>
 {
     CYTypedIdentifier *typed_;
 
-    CYClassField(CYTypedIdentifier *typed, CYClassField *next = NULL) :
-        CYNext<CYClassField>(next),
+    CYImplementationField(CYTypedIdentifier *typed, CYImplementationField *next = NULL) :
+        CYNext<CYImplementationField>(next),
         typed_(typed)
     {
     }
@@ -160,7 +160,7 @@ struct CYMessage :
     }
 
     CYStatement *Replace(CYContext &context, bool replace) const;
-    void Output(CYOutput &out, bool replace) const;
+    void Output(CYOutput &out) const;
 
     CYExpression *TypeSignature(CYContext &context) const;
 };
@@ -181,16 +181,16 @@ struct CYProtocol :
     void Output(CYOutput &out) const;
 };
 
-struct CYClassStatement :
+struct CYImplementation :
     CYStatement
 {
-    CYClassName *name_;
+    CYIdentifier *name_;
     CYExpression *super_;
     CYProtocol *protocols_;
-    CYClassField *fields_;
+    CYImplementationField *fields_;
     CYMessage *messages_;
 
-    CYClassStatement(CYClassName *name, CYExpression *super, CYProtocol *protocols, CYClassField *fields, CYMessage *messages) :
+    CYImplementation(CYIdentifier *name, CYExpression *super, CYProtocol *protocols, CYImplementationField *fields, CYMessage *messages) :
         name_(name),
         super_(super),
         protocols_(protocols),
@@ -208,10 +208,10 @@ struct CYClassStatement :
 struct CYCategory :
     CYStatement
 {
-    CYClassName *name_;
+    CYIdentifier *name_;
     CYMessage *messages_;
 
-    CYCategory(CYClassName *name, CYMessage *messages) :
+    CYCategory(CYIdentifier *name, CYMessage *messages) :
         name_(name),
         messages_(messages)
     {
index 1496509a7b4ee3ea38b8ea1935e18044b06e214b..ce8e00c28924aa2b37eb4d1811155014b3a5aa48 100644 (file)
@@ -184,6 +184,41 @@ void Catch::Output(CYOutput &out) const {
 
 } }
 
+void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
+    bool protect((flags & CYNoClass) != 0);
+    if (protect)
+        out << '(';
+    out << "class";
+    if (name_ != NULL)
+        out << ' ' << *name_;
+    out << *tail_;;
+    if (protect)
+        out << ')';
+}
+
+void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
+    out << "class" << ' ' << *name_  << *tail_;
+}
+
+void CYClassTail::Output(CYOutput &out) const {
+    if (extends_ == NULL)
+        out << ' ';
+    else {
+        out << '\n';
+        ++out.indent_;
+        out << "extends" << ' ';
+        extends_->Output(out, CYAssign::Precedence_ - 1, CYNoFlags);
+        out << '\n';
+        --out.indent_;
+    }
+
+    out << '{' << '\n';
+    ++out.indent_;
+
+    --out.indent_;
+    out << '}';
+}
+
 void CYCompound::Output(CYOutput &out, CYFlags flags) const {
     if (next_ == NULL)
         expression_->Output(out, flags);
@@ -194,6 +229,12 @@ void CYCompound::Output(CYOutput &out, CYFlags flags) const {
     }
 }
 
+void CYComputed::PropertyName(CYOutput &out) const {
+    out << '[';
+    expression_->Output(out, CYAssign::Precedence_, CYNoFlags);
+    out << ']';
+}
+
 void CYCondition::Output(CYOutput &out, CYFlags flags) const {
     test_->Output(out, Precedence() - 1, CYLeft(flags));
     out << ' ' << '?' << ' ';
@@ -313,14 +354,10 @@ void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
 }
 
 void CYExpress::Output(CYOutput &out, CYFlags flags) const {
-    expression_->Output(out, flags | CYNoBF);
+    expression_->Output(out, flags | CYNoBFC);
     out << ';';
 }
 
-void CYExpression::ClassName(CYOutput &out, bool object) const {
-    Output(out, CYAssign::Precedence_, CYNoFlags);
-}
-
 void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
     Output(out, flags | CYNoRightHand);
 }
@@ -396,30 +433,31 @@ void CYForInComprehension::Output(CYOutput &out) const {
     out << ' ' << "in" << ' ' << *set_ << ')';
 }
 
-void CYFunction::Output(CYOutput &out, CYFlags flags) const {
-    // XXX: one could imagine using + here to save a byte
-    bool protect((flags & CYNoFunction) != 0);
-    if (protect)
-        out << '(';
-    out << "function";
-    if (name_ != NULL)
-        out << ' ' << *name_;
+void CYFunction::Output(CYOutput &out) const {
     out << '(' << parameters_ << ')' << ' ';
     out << '{' << '\n';
     ++out.indent_;
     out << code_;
     --out.indent_;
     out << '\t' << '}';
-    if (protect)
-        out << ')';
 }
 
 void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
-    CYFunction::Output(out, flags);
+    // XXX: one could imagine using + here to save a byte
+    bool protect((flags & CYNoFunction) != 0);
+    if (protect)
+        out << '(';
+    out << "function";
+    if (name_ != NULL)
+        out << ' ' << *name_;
+    CYFunction::Output(out);
+    if (protect)
+        out << ')';
 }
 
 void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
-    CYFunction::Output(out, flags);
+    out << "function" << ' ' << *name_;
+    CYFunction::Output(out);
 }
 
 void CYFunctionParameter::Output(CYOutput &out) const {
@@ -664,14 +702,37 @@ void CYScript::Output(CYOutput &out) const {
 }
 
 void CYProperty::Output(CYOutput &out) const {
+    if (next_ != NULL || out.pretty_)
+        out << ',';
+    out << '\n' <<  next_;
+}
+
+void CYPropertyGetter::Output(CYOutput &out) const {
+    out << "get" << ' ';
+    name_->PropertyName(out);
+    CYFunction::Output(out);
+    CYProperty::Output(out);
+}
+
+void CYPropertyMethod::Output(CYOutput &out) const {
+    name_->PropertyName(out);
+    CYFunction::Output(out);
+    CYProperty::Output(out);
+}
+
+void CYPropertySetter::Output(CYOutput &out) const {
+    out << "set" << ' ';
+    name_->PropertyName(out);
+    CYFunction::Output(out);
+    CYProperty::Output(out);
+}
+
+void CYPropertyValue::Output(CYOutput &out) const {
     out << '\t';
     name_->PropertyName(out);
     out << ':' << ' ';
     value_->Output(out, CYAssign::Precedence_, CYNoFlags);
-    if (next_ != NULL)
-        out << ',' << '\n' << *next_;
-    else
-        out << '\n';
+    CYProperty::Output(out);
 }
 
 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
@@ -781,6 +842,18 @@ const char *CYString::Word() const {
     return value;
 }
 
+void CYSuperAccess::Output(CYOutput &out, CYFlags flags) const {
+    out << "super";
+    if (const char *word = property_->Word())
+        out << '.' << word;
+    else
+        out << '[' << *property_ << ']';
+}
+
+void CYSuperCall::Output(CYOutput &out, CYFlags flags) const {
+    out << "super" << '(' << arguments_ << ')';
+}
+
 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
     out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{' << '\n';
     ++out.indent_;
@@ -863,14 +936,6 @@ void CYWith::Output(CYOutput &out, CYFlags flags) const {
     code_->Single(out, CYRight(flags), CYCompactShort);
 }
 
-void CYWord::ClassName(CYOutput &out, bool object) const {
-    if (object)
-        out << "objc_getClass(";
-    out << '"' << Word() << '"';
-    if (object)
-        out << ')';
-}
-
 void CYWord::Output(CYOutput &out) const {
     out << Word();
     if (out.options_.verbose_) {
index fe1c5f353ded4ab64d8c1e09f2749aa5c92a9686..6028184ecc46b3b00df36b9e72028c36abe94719 100644 (file)
 
 %union { bool bool_; }
 
+%union { CYMember *access_; }
 %union { CYArgument *argument_; }
 %union { CYAssignment *assignment_; }
 %union { CYBoolean *boolean_; }
 %union { CYClause *clause_; }
 %union { cy::Syntax::Catch *catch_; }
+%union { CYClassTail *classTail_; }
 %union { CYComprehension *comprehension_; }
 %union { CYDeclaration *declaration_; }
 %union { CYDeclarations *declarations_; }
@@ -61,7 +63,7 @@
 %union { CYIdentifier *identifier_; }
 %union { CYInfix *infix_; }
 %union { CYLiteral *literal_; }
-%union { CYMember *member_; }
+%union { CYMethod *method_; }
 %union { CYModule *module_; }
 %union { CYNull *null_; }
 %union { CYNumber *number_; }
 @end
 
 @begin ObjectiveC
-%union { CYClassName *className_; }
-%union { CYClassField *classField_; }
 %union { CYMessage *message_; }
 %union { CYMessageParameter *messageParameter_; }
+%union { CYImplementationField *implementationField_; }
 %union { CYProtocol *protocol_; }
 %union { CYSelectorPart *selector_; }
 @end
@@ -321,6 +322,7 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY
 %token _return_ "return"
 %token _return__ "!return"
 %token _super_ "super"
+%token _super__ "!super"
 %token _switch_ "switch"
 %token _this_ "this"
 %token _throw_ "throw"
@@ -336,6 +338,7 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY
 %token _boolean_ "boolean"
 %token _byte_ "byte"
 %token _char_ "char"
+%token _constructor_ "constructor"
 %token _double_ "double"
 %token _final_ "final"
 %token _float_ "float"
@@ -351,6 +354,7 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY
 %token _package_ "package"
 %token _private_ "private"
 %token _protected_ "protected"
+%token _prototype_ "prototype"
 %token _public_ "public"
 %token _set_ "set"
 %token _short_ "short"
@@ -428,11 +432,14 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY
 %type <identifier_> CatchParameter
 %type <statement_> ClassDeclaration
 %type <expression_> ClassExpression
+%type <classTail_> ClassHeritage
+%type <classTail_> ClassHeritageOpt
+%type <classTail_> ClassTail
 %type <expression_> Comprehension
 %type <comprehension_> ComprehensionFor
 %type <comprehension_> ComprehensionIf
 %type <comprehension_> ComprehensionTail
-%type <expression_> ComputedPropertyName
+%type <propertyName_> ComputedPropertyName
 %type <expression_> ConditionalExpression
 %type <statement_> ContinueStatement
 %type <statement_> ConciseBody
@@ -466,7 +473,7 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY
 %type <statement_> GeneratorBody
 %type <statement_> GeneratorDeclaration
 %type <expression_> GeneratorExpression
-%type <property_> GeneratorMethod
+%type <method_> GeneratorMethod
 %type <statement_> HoistableDeclaration
 %type <identifier_> Identifier
 %type <identifier_> IdentifierType
@@ -487,9 +494,9 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY
 %type <propertyName_> LiteralPropertyName
 %type <expression_> LogicalANDExpression
 %type <expression_> LogicalORExpression
-%type <member_> MemberAccess
+%type <access_> MemberAccess
 %type <expression_> MemberExpression
-%type <property_> MethodDefinition
+%type <method_> MethodDefinition
 %type <module_> ModulePath
 %type <expression_> MultiplicativeExpression
 %type <expression_> NewExpression
@@ -522,6 +529,8 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY
 %type <statement_> StatementListOpt
 %type <statement_> StatementListItem
 %type <functionParameter_> StrictFormalParameters
+%type <expression_> SuperCall
+%type <expression_> SuperProperty
 %type <statement_> SwitchStatement
 %type <expression_> TemplateLiteral
 %type <span_> TemplateSpans
@@ -558,16 +567,15 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY
 @begin ObjectiveC
 %type <expression_> BoxableExpression
 %type <statement_> CategoryStatement
-%type <classField_> ClassFieldListOpt
-%type <classField_> ClassFields
-%type <statement_> ClassStatement
 %type <expression_> ClassSuperOpt
+%type <implementationField_> ImplementationFieldListOpt
+%type <implementationField_> ImplementationFields
 %type <message_> ClassMessageDeclaration
 %type <message_> ClassMessageDeclarationListOpt
-%type <className_> ClassName
 %type <protocol_> ClassProtocolListOpt
 %type <protocol_> ClassProtocols
 %type <protocol_> ClassProtocolsOpt
+%type <statement_> ImplementationStatement
 %type <expression_> MessageExpression
 %type <messageParameter_> MessageParameter
 %type <messageParameter_> MessageParameters
@@ -633,6 +641,10 @@ LexPopIn: { driver.in_.pop(); };
 LexPushReturnOn: { driver.return_.push(true); };
 LexPopReturn: { driver.return_.pop(); };
 
+LexPushSuperOn: { driver.super_.push(true); };
+LexPushSuperOff: { driver.super_.push(false); };
+LexPopSuper: { driver.super_.pop(); };
+
 LexPushYieldOn: { driver.yield_.push(true); };
 LexPushYieldOff: { driver.yield_.push(false); };
 LexPopYield: { driver.yield_.pop(); };
@@ -718,6 +730,7 @@ Word
     | "return" { $$ = CYNew CYWord("return"); }
     | "!return" { $$ = CYNew CYWord("return"); }
     | "super" { $$ = CYNew CYWord("super"); }
+    | "!super" { $$ = CYNew CYWord("super"); }
     | "switch" { $$ = CYNew CYWord("switch"); }
     | "this" { $$ = CYNew CYWord("this"); }
     | "throw" { $$ = CYNew CYWord("throw"); }
@@ -803,10 +816,13 @@ IdentifierType
     | "await" { $$ = CYNew CYIdentifier("await"); }
     | "boolean" { $$ = CYNew CYIdentifier("boolean"); }
     | "byte" { $$ = CYNew CYIdentifier("byte"); }
+    | "constructor" { $$ = CYNew CYIdentifier("constructor"); }
     | "double" { $$ = CYNew CYIdentifier("double"); }
     | "each" { $$ = CYNew CYIdentifier("each"); }
     | "final" { $$ = CYNew CYIdentifier("final"); }
     | "float" { $$ = CYNew CYIdentifier("float"); }
+    | "from" { $$ = CYNew CYIdentifier("from"); }
+    | "get" { $$ = CYNew CYIdentifier("get"); }
     | "goto" { $$ = CYNew CYIdentifier("goto"); }
     | "implements" { $$ = CYNew CYIdentifier("implements"); }
     | "interface" { $$ = CYNew CYIdentifier("interface"); }
@@ -815,11 +831,13 @@ IdentifierType
     | "package" { $$ = CYNew CYIdentifier("package"); }
     | "private" { $$ = CYNew CYIdentifier("private"); }
     | "protected" { $$ = CYNew CYIdentifier("protected"); }
+    | "prototype" { $$ = CYNew CYIdentifier("prototype"); }
     | "public" { $$ = CYNew CYIdentifier("public"); }
-    | "static" { $$ = CYNew CYIdentifier("static"); }
+    | "set" { $$ = CYNew CYIdentifier("set"); }
     | "synchronized" { $$ = CYNew CYIdentifier("synchronized"); }
     | "throws" { $$ = CYNew CYIdentifier("throws"); }
     | "transient" { $$ = CYNew CYIdentifier("transient"); }
+    | "undefined" { $$ = CYNew CYIdentifier("undefined"); }
 @begin ObjectiveC
     | "bool" { $$ = CYNew CYIdentifier("bool"); }
     | "BOOL" { $$ = CYNew CYIdentifier("BOOL"); }
@@ -831,13 +849,10 @@ IdentifierType
 Identifier
     : IdentifierType
     | "char" { $$ = CYNew CYIdentifier("char"); }
-    | "from" { $$ = CYNew CYIdentifier("from"); }
-    | "get" { $$ = CYNew CYIdentifier("get"); }
     | "int" { $$ = CYNew CYIdentifier("int"); }
     | "long" { $$ = CYNew CYIdentifier("long"); }
-    | "set" { $$ = CYNew CYIdentifier("set"); }
     | "short" { $$ = CYNew CYIdentifier("short"); }
-    | "undefined" { $$ = CYNew CYIdentifier("undefined"); }
+    | "static" { $$ = CYNew CYIdentifier("static"); }
     | "volatile" { $$ = CYNew CYIdentifier("volatile"); }
 @begin C
     | "extern" { $$ = CYNew CYIdentifier("extern"); }
@@ -920,15 +935,15 @@ PropertyDefinitionListOpt
     ;
 
 PropertyDefinition
-    : IdentifierReference { $$ = CYNew CYProperty($1->name_, $1); }
+    : IdentifierReference { $$ = CYNew CYPropertyValue($1->name_, $1); }
     | CoverInitializedName { CYNOT(@$); }
-    | PropertyName ":" AssignmentExpression { $$ = CYNew CYProperty($1, $3); }
+    | PropertyName ":" AssignmentExpression { $$ = CYNew CYPropertyValue($1, $3); }
     | MethodDefinition { $$ = $1; }
     ;
 
 PropertyName
     : LiteralPropertyName { $$ = $1; }
-    | ComputedPropertyName { CYNOT(@$); /* $$ = $1; */ }
+    | ComputedPropertyName { $$ = $1; }
     ;
 
 LiteralPropertyName
@@ -938,7 +953,7 @@ LiteralPropertyName
     ;
 
 ComputedPropertyName
-    : "[" AssignmentExpression "]" { $$ = $2; }
+    : "[" AssignmentExpression "]" { $$ = CYNew CYComputed($2); }
     ;
 
 CoverInitializedName
@@ -977,14 +992,14 @@ MemberAccess
 MemberExpression
     : LexSetRegExp PrimaryExpression { $$ = $2; }
     | MemberExpression { driver.context_ = $1; } MemberAccess { $3->SetLeft($1); $$ = $3; }
-    | SuperProperty { CYNOT(@$); }
+    | SuperProperty { $$ = $1; }
     | MetaProperty { CYNOT(@$); }
     | LexSetRegExp "new" MemberExpression Arguments { $$ = CYNew cy::Syntax::New($3, $4); }
     ;
 
 SuperProperty
-    : LexSetRegExp "super" "[" Expression "]"
-    | LexSetRegExp "super" "." IdentifierName
+    : LexSetRegExp "!super" "[" Expression "]" { $$ = CYNew CYSuperAccess($4); }
+    | LexSetRegExp "!super" "." IdentifierName { $$ = CYNew CYSuperAccess(CYNew CYString($4)); }
     ;
 
 MetaProperty
@@ -1007,12 +1022,12 @@ CallExpression_
 
 CallExpression
     : CallExpression_ Arguments { $$ = CYNew CYCall($1, $2); }
-    | SuperCall { CYNOT(@$); }
+    | SuperCall { $$ = $1; }
     | CallExpression { driver.context_ = $1; } MemberAccess { $3->SetLeft($1); $$ = $3; }
     ;
 
 SuperCall
-    : LexSetRegExp "super" Arguments
+    : LexSetRegExp "!super" Arguments { $$ = CYNew CYSuperCall($3); }
     ;
 
 Arguments
@@ -1497,11 +1512,11 @@ DebuggerStatement
 
 /* 14.1 Function Definitions {{{ */
 FunctionDeclaration
-    : ";function" BindingIdentifier "(" FormalParameters ")" BRACE FunctionBody "}" { $$ = CYNew CYFunctionStatement($2, $4, $7); }
+    : ";function" BindingIdentifier "(" FormalParameters ")" BRACE LexPushSuperOff FunctionBody "}" LexPopSuper { $$ = CYNew CYFunctionStatement($2, $4, $8); }
     ;
 
 FunctionExpression
-    : "function" BindingIdentifierOpt "(" LexPushInOff FormalParameters ")" LexPopIn BRACE LexPushInOff FunctionBody "}" LexPopIn { $$ = CYNew CYFunctionExpression($2, $5, $10); }
+    : "function" BindingIdentifierOpt "(" LexPushInOff FormalParameters ")" LexPopIn BRACE LexPushSuperOff LexPushInOff FunctionBody "}" LexPopIn LexPopSuper { $$ = CYNew CYFunctionExpression($2, $5, $11); }
     ;
 
 StrictFormalParameters
@@ -1556,10 +1571,10 @@ ConciseBody
 /* }}} */
 /* 14.3 Method Definitions {{{ */
 MethodDefinition
-    : PropertyName "(" StrictFormalParameters ")" BRACE FunctionBody "}" { CYNOT(@$); /* $$ = CYNew CYFunctionMethod($1, $3, $6); */ }
+    : PropertyName "(" StrictFormalParameters ")" BRACE FunctionBody "}" { $$ = CYNew CYPropertyMethod($1, $3, $6); }
     | GeneratorMethod { $$ = $1; }
-    | "get" PropertyName "(" ")" BRACE FunctionBody "}" { CYNOT(@$); /* $$ = CYNew CYMethodGet($2, $6); */ }
-    | "set" PropertyName "(" PropertySetParameterList ")" BRACE FunctionBody "}" { CYNOT(@$); /* $$ = CYNew CYMethodSet($2, $4); */ }
+    | "get" PropertyName "(" ")" BRACE FunctionBody "}" { $$ = CYNew CYPropertyGetter($2, $6); }
+    | "set" PropertyName "(" PropertySetParameterList ")" BRACE FunctionBody "}" { $$ = CYNew CYPropertySetter($2, CYNew CYFunctionParameter($4), $7); }
     ;
 
 PropertySetParameterList
@@ -1595,24 +1610,24 @@ YieldExpression
 /* }}} */
 /* 14.5 Class Definitions {{{ */
 ClassDeclaration
-    : ";class" BindingIdentifier ClassTail { CYNOT(@$); }
+    : ";class" BindingIdentifier ClassTail { $$ = CYNew CYClassStatement($2, $3); }
     ;
 
 ClassExpression
-    : "class" BindingIdentifierOpt ClassTail { CYNOT(@$); }
+    : "class" BindingIdentifierOpt ClassTail { $$ = CYNew CYClassExpression($2, $3); }
     ;
 
 ClassTail
-    : ClassHeritageOpt BRACE ClassBodyOpt "}"
+    : ClassHeritageOpt { driver.class_.push($1); } BRACE LexPushSuperOn ClassBodyOpt "}" LexPopSuper { driver.class_.pop(); $$ = $1; }
     ;
 
 ClassHeritage
-    : "extends" LeftHandSideExpression
+    : "extends" LeftHandSideExpression { $$ = CYNew CYClassTail($2); }
     ;
 
 ClassHeritageOpt
-    : ClassHeritage
-    |
+    : ClassHeritage { $$ = $1; }
+    | { $$ = CYNew CYClassTail(NULL); }
     ;
 
 ClassBody
@@ -1634,8 +1649,8 @@ ClassElementListOpt
     ;
 
 ClassElement
-    : MethodDefinition
-    | "static" MethodDefinition
+    : MethodDefinition { if (CYFunctionExpression *constructor = $1->Constructor()) driver.class_.top()->constructor_ = constructor; else driver.class_.top()->instance_->*$1; }
+    | "static" MethodDefinition { driver.class_.top()->static_->*$2; }
     | ";"
     ;
 /* }}} */
@@ -1853,13 +1868,13 @@ ClassSuperOpt
     | { $$ = NULL; }
     ;
 
-ClassFieldListOpt
-    : TypedIdentifier ";" ClassFieldListOpt { $$ = CYNew CYClassField($1, $3); }
+ImplementationFieldListOpt
+    : TypedIdentifier ";" ImplementationFieldListOpt { $$ = CYNew CYImplementationField($1, $3); }
     | LexSetRegExp { $$ = NULL; }
     ;
 
-ClassFields
-    : BRACE ClassFieldListOpt "}" { $$ = $2; }
+ImplementationFields
+    : BRACE ImplementationFieldListOpt "}" { $$ = $2; }
     ;
 
 MessageScope
@@ -1891,7 +1906,7 @@ MessageParameters
     ;
 
 ClassMessageDeclaration
-    : MessageScope TypeOpt MessageParameters BRACE FunctionBody "}" { $$ = CYNew CYMessage($1, $2, $3, $5); }
+    : MessageScope TypeOpt MessageParameters BRACE LexPushSuperOn FunctionBody "}" LexPopSuper { $$ = CYNew CYMessage($1, $2, $3, $6); }
     ;
 
 ClassMessageDeclarationListOpt
@@ -1899,11 +1914,6 @@ ClassMessageDeclarationListOpt
     | { $$ = NULL; }
     ;
 
-ClassName
-    : Identifier { $$ = $1; }
-    | "(" AssignmentExpression ")" { $$ = $2; }
-    ;
-
 // XXX: this should be AssignmentExpressionNoRight
 ClassProtocols
     : ShiftExpression ClassProtocolsOpt { $$ = CYNew CYProtocol($1, $2); }
@@ -1919,8 +1929,8 @@ ClassProtocolListOpt
     | { $$ = NULL; }
     ;
 
-ClassStatement
-    : "@implementation" ClassName ClassSuperOpt ClassProtocolListOpt ClassFields ClassMessageDeclarationListOpt "@end" { $$ = CYNew CYClassStatement($2, $3, $4, $5, $6); }
+ImplementationStatement
+    : "@implementation" Identifier ClassSuperOpt ClassProtocolListOpt ImplementationFields ClassMessageDeclarationListOpt "@end" { $$ = CYNew CYImplementation($2, $3, $4, $5, $6); }
     ;
 
 CategoryName
@@ -1928,11 +1938,11 @@ CategoryName
     ;
 
 CategoryStatement
-    : "@implementation" ClassName CategoryName ClassMessageDeclarationListOpt "@end" { $$ = CYNew CYCategory($2, $4); }
+    : "@implementation" Identifier CategoryName ClassMessageDeclarationListOpt "@end" { $$ = CYNew CYCategory($2, $4); }
     ;
 
 Statement__
-    : ClassStatement { $$ = $1; }
+    : ImplementationStatement { $$ = $1; }
     | CategoryStatement { $$ = $1; }
     ;
 /* }}} */
@@ -1963,7 +1973,7 @@ SelectorList
 
 MessageExpression
     : "[" LexPushInOff AssignmentExpression { driver.contexts_.push_back($3); } SelectorList "]" LexPopIn { driver.contexts_.pop_back(); } { $$ = CYNew CYSendDirect($3, $5); }
-    | "[" LexPushInOff LexSetRegExp "super" { driver.context_ = NULL; } SelectorList "]" LexPopIn { $$ = CYNew CYSendSuper($6); }
+    | "[" LexPushInOff LexSetRegExp "!super" { driver.context_ = NULL; } SelectorList "]" LexPopIn { $$ = CYNew CYSendSuper($6); }
     ;
 
 SelectorExpression_
index 2ac69422c4904914191a99c809d1f1d600f8596d..4d1a2be5d2cf7c5611a0b51249bb1a38e85f28bc 100644 (file)
@@ -29,6 +29,11 @@ CYFunctionExpression *CYNonLocalize(CYContext &context, CYFunctionExpression *fu
     return function;
 }
 
+CYFunctionExpression *CYSuperize(CYContext &context, CYFunctionExpression *function) {
+    function->super_ = context.super_;
+    return function;
+}
+
 static void CYImplicitReturn(CYStatement *&code) {
     if (CYStatement *&last = CYGetLast(code))
         last = last->Return();
@@ -88,7 +93,7 @@ CYExpression *CYArray::Replace(CYContext &context) {
 CYExpression *CYArrayComprehension::Replace(CYContext &context) {
     CYVariable *cyv($V("$cyv"));
 
-    return $C0($F(NULL, $P1($L("$cyv"), comprehensions_->Parameters(context)), $$->*
+    return $C0($F(NULL, $P1($L($I("$cyv")), comprehensions_->Parameters(context)), $$->*
         $E($ CYAssign(cyv, $ CYArray()))->*
         comprehensions_->Replace(context, $E($C1($M(cyv, $S("push")), expression_)))->*
         $ CYReturn(cyv)
@@ -146,6 +151,45 @@ void Catch::Replace(CYContext &context) { $T()
 
 } }
 
+CYExpression *CYClassExpression::Replace(CYContext &context) {
+    CYBuilder builder;
+
+    CYIdentifier *super(context.Unique());
+
+    CYIdentifier *old(context.super_);
+    context.super_ = super;
+
+    CYIdentifier *constructor(context.Unique());
+    CYForEach (member, tail_->static_)
+        member->Replace(context, builder, $V(constructor), true);
+
+    CYIdentifier *prototype(context.Unique());
+    CYForEach (member, tail_->instance_)
+        member->Replace(context, builder, $V(prototype), true);
+
+    if (tail_->constructor_ == NULL)
+        tail_->constructor_ = $ CYFunctionExpression(NULL, NULL, NULL);
+    tail_->constructor_ = CYSuperize(context, tail_->constructor_);
+
+    context.super_ = old;
+
+    return $C1($ CYFunctionExpression(NULL, $P($L(super)), $$
+        ->* $ CYVar($L1($L(constructor, tail_->constructor_)))
+        ->* $ CYVar($L1($L(prototype, $ CYFunctionExpression(NULL, NULL, NULL))))
+        ->* $E($ CYAssign($M($V(prototype), $S("prototype")), $M($V(super), $S("prototype"))))
+        ->* $E($ CYAssign($V(prototype), $N($V(prototype))))
+        ->* $E($ CYAssign($M($V(prototype), $S("constructor")), $V(constructor)))
+        ->* $ CYVar(builder.declarations_)
+        ->* builder.statements_
+        ->* $E($ CYAssign($M($V(constructor), $S("prototype")), $V(prototype)))
+        ->* $ CYReturn($V(constructor))
+    ), tail_->extends_ ?: $V($I("Object")));
+}
+
+CYStatement *CYClassStatement::Replace(CYContext &context) {
+    return $ CYVar($L1($L(name_, $ CYClassExpression(name_, tail_))));
+}
+
 void CYClause::Replace(CYContext &context) { $T()
     context.Replace(case_);
     context.ReplaceAll(code_);
@@ -192,6 +236,10 @@ CYStatement *CYComprehension::Replace(CYContext &context, CYStatement *statement
     return next_ == NULL ? statement : next_->Replace(context, statement);
 }
 
+CYExpression *CYComputed::PropertyName(CYContext &context) {
+    return expression_;
+}
+
 CYExpression *CYCondition::Replace(CYContext &context) {
     context.Replace(test_);
     context.Replace(true_);
@@ -207,7 +255,7 @@ void CYContext::NonLocal(CYStatement *&statements) {
         CYIdentifier *unique(nextlocal_->identifier_->Replace(context));
 
         CYStatement *declare(
-            $ CYVar($L1($ CYDeclaration(unique, $ CYObject()))));
+            $ CYVar($L1($L(unique, $ CYObject()))));
 
         cy::Syntax::Catch *rescue(
             $ cy::Syntax::Catch(cye, $$->*
@@ -265,10 +313,6 @@ void CYDeclarations::Replace(CYContext &context) { $T()
     next_->Replace(context);
 }
 
-CYProperty *CYDeclarations::Property(CYContext &context) { $T(NULL)
-    return $ CYProperty(declaration_->identifier_, declaration_->initialiser_, next_->Property(context));
-}
-
 CYFunctionParameter *CYDeclarations::Parameter(CYContext &context) { $T(NULL)
     return $ CYFunctionParameter($ CYDeclaration(declaration_->identifier_), next_->Parameter(context));
 }
@@ -330,10 +374,6 @@ CYExpression *CYExpression::AddArgument(CYContext &context, CYExpression *value)
     return $C1(this, value);
 }
 
-CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
-    return this;
-}
-
 CYStatement *CYExpression::ForEachIn(CYContext &context, CYExpression *value) {
     return $E($ CYAssign(this, value));
 }
@@ -427,7 +467,7 @@ CYFunctionParameter *CYForOfComprehension::Parameter(CYContext &context) const {
 CYStatement *CYForOfComprehension::Replace(CYContext &context, CYStatement *statement) const {
     CYIdentifier *cys($I("$cys"));
 
-    return $E($C0($F(NULL, $P1($L("$cys")), $$->*
+    return $E($C0($F(NULL, $P1($L($I("$cys"))), $$->*
         $E($ CYAssign($V(cys), set_))->*
         $ CYForIn(declaration_->Variable(context), $V(cys), $ CYBlock($$->*
             $E($ CYAssign(declaration_->Variable(context), $M($V(cys), declaration_->Variable(context))))->*
@@ -436,19 +476,14 @@ CYStatement *CYForOfComprehension::Replace(CYContext &context, CYStatement *stat
     )));
 }
 
-void CYFunction::Inject(CYContext &context) {
-    context.Replace(name_);
-    context.scope_->Declare(context, name_, CYIdentifierOther);
-}
-
-void CYFunction::Replace_(CYContext &context, bool outer) {
-    if (outer)
-        Inject(context);
-
+void CYFunction::Replace(CYContext &context) {
     CYThisScope *_this(context.this_);
     context.this_ = &this_;
     context.this_ = CYGetLast(context.this_);
 
+    CYIdentifier *super(context.super_);
+    context.super_ = super_;
+
     CYNonLocal *nonlocal(context.nonlocal_);
     CYNonLocal *nextlocal(context.nextlocal_);
 
@@ -464,19 +499,20 @@ void CYFunction::Replace_(CYContext &context, bool outer) {
 
     CYScope scope(!localize, context);
 
-    if (!outer && name_ != NULL)
-        Inject(context);
-
     parameters_->Replace(context, code_);
+
     context.ReplaceAll(code_);
 
     if (implicit_)
         CYImplicitReturn(code_);
 
-    if (CYIdentifier *identifier = this_.identifier_)
-        code_ = $$->*
-            $ CYVar($L1($ CYDeclaration(identifier, $ CYThis())))->*
-            code_;
+    if (CYIdentifier *identifier = this_.identifier_) {
+        context.scope_->Declare(context, identifier, CYIdentifierVariable);
+        code_ = $$
+            ->*$E($ CYAssign($V(identifier), $ CYThis()))
+            ->*code_
+        ;
+    }
 
     if (localize)
         context.NonLocal(code_);
@@ -484,13 +520,18 @@ void CYFunction::Replace_(CYContext &context, bool outer) {
     context.nextlocal_ = nextlocal;
     context.nonlocal_ = nonlocal;
 
+    context.super_ = super;
     context.this_ = _this;
 
     scope.Close(context, code_);
 }
 
 CYExpression *CYFunctionExpression::Replace(CYContext &context) {
-    Replace_(context, false);
+    CYScope scope(false, context);
+    if (name_ != NULL)
+        context.scope_->Declare(context, name_, CYIdentifierOther);
+    CYFunction::Replace(context);
+    scope.Close(context, code_);
     return this;
 }
 
@@ -510,7 +551,8 @@ void CYFunctionParameter::Replace(CYContext &context, CYStatement *&statements)
 }
 
 CYStatement *CYFunctionStatement::Replace(CYContext &context) {
-    Replace_(context, true);
+    context.scope_->Declare(context, name_, CYIdentifierOther);
+    CYFunction::Replace(context);
     return this;
 }
 
@@ -543,7 +585,7 @@ CYStatement *CYIfComprehension::Replace(CYContext &context, CYStatement *stateme
 }
 
 CYStatement *CYImport::Replace(CYContext &context) {
-    return $ CYVar($L1($L(module_->part_->Word(), $C1($V("require"), module_->Replace(context, "/")))));
+    return $ CYVar($L1($L($I(module_->part_->Word()), $C1($V("require"), module_->Replace(context, "/")))));
 }
 
 CYExpression *CYIndirect::Replace(CYContext &context) {
@@ -573,6 +615,14 @@ CYStatement *CYLetStatement::Replace(CYContext &context) {
     return $E($ CYCall(CYNonLocalize(context, $ CYFunctionExpression(NULL, declarations_->Parameter(context), code_)), declarations_->Argument(context)));
 }
 
+CYFunctionExpression *CYMethod::Constructor() {
+    return NULL;
+}
+
+void CYMethod::Replace(CYContext &context) {
+    CYFunction::Replace(context);
+}
+
 CYString *CYModule::Replace(CYContext &context, const char *separator) const {
     if (next_ == NULL)
         return $ CYString(part_);
@@ -622,8 +672,24 @@ CYString *CYNumber::String(CYContext &context) {
     return $S($pool.sprintf(24, "%.17g", Value()));
 }
 
+CYExpression *CYNumber::PropertyName(CYContext &context) {
+    return String(context);
+}
+
 CYExpression *CYObject::Replace(CYContext &context) {
-    properties_->Replace(context);
+    CYBuilder builder;
+    if (properties_ != NULL)
+        properties_ = properties_->ReplaceAll(context, builder, $ CYThis(), false);
+
+    if (builder) {
+        return $C1($M($ CYFunctionExpression(NULL, builder.declarations_->Parameter(context),
+            builder.statements_->*
+                $ CYReturn($ CYThis())
+        ), $S("call")), this, builder.declarations_->Argument(context));
+    }
+
+    CYForEach (property, properties_)
+        property->Replace(context);
     return this;
 }
 
@@ -641,6 +707,74 @@ CYExpression *CYPrefix::Replace(CYContext &context) {
     return this;
 }
 
+CYProperty *CYProperty::ReplaceAll(CYContext &context, CYBuilder &builder, CYExpression *self, bool update) {
+    update |= name_->Computed();
+    if (update)
+        Replace(context, builder, self, true);
+    if (next_ != NULL)
+        next_ = next_->ReplaceAll(context, builder, self, update);
+    return update ? next_ : this;
+}
+
+void CYProperty::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, bool computed) {
+    CYExpression *name(name_->PropertyName(context));
+    if (computed) {
+        CYIdentifier *unique(context.Unique());
+        builder.declarations_->*$L1($L(unique, name));
+        name = $V(unique);
+    }
+
+    Replace(context, builder, self, name);
+}
+
+void CYPropertyGetter::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name) {
+    CYIdentifier *unique(context.Unique());
+    builder.declarations_
+        ->* $L1($L(unique, CYSuperize(context, $ CYFunctionExpression(NULL, parameters_, code_))));
+    builder.statements_
+        ->* $E($C3($M($V("Object"), $S("defineProperty")), self, name, $ CYObject(CYList<CYProperty>()
+            ->* $ CYPropertyValue($S("configurable"), $ CYTrue())
+            ->* $ CYPropertyValue($S("enumerable"), $ CYTrue())
+            ->* $ CYPropertyValue($S("get"), $V(unique))
+        )));
+}
+
+CYFunctionExpression *CYPropertyMethod::Constructor() {
+    return name_->Constructor() ? $ CYFunctionExpression(NULL, parameters_, code_) : NULL;
+}
+
+void CYPropertyMethod::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name) {
+    CYIdentifier *unique(context.Unique());
+    builder.declarations_
+        ->* $L1($L(unique, CYSuperize(context, $ CYFunctionExpression(NULL, parameters_, code_))));
+    builder.statements_
+        ->* $E($ CYAssign($M(self, name), $V(unique)));
+}
+
+void CYPropertySetter::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name) {
+    CYIdentifier *unique(context.Unique());
+    builder.declarations_
+        ->* $L1($L(unique, CYSuperize(context, $ CYFunctionExpression(NULL, parameters_, code_))));
+    builder.statements_
+        ->* $E($C3($M($V("Object"), $S("defineProperty")), self, name, $ CYObject(CYList<CYProperty>()
+            ->* $ CYPropertyValue($S("configurable"), $ CYTrue())
+            ->* $ CYPropertyValue($S("enumerable"), $ CYTrue())
+            ->* $ CYPropertyValue($S("set"), $V(unique))
+        )));
+}
+
+void CYPropertyValue::Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name) {
+    CYIdentifier *unique(context.Unique());
+    builder.declarations_
+        ->* $L1($L(unique, value_));
+    builder.statements_
+        ->* $E($ CYAssign($M(self, name), $V(unique)));
+}
+
+void CYPropertyValue::Replace(CYContext &context) {
+    context.Replace(value_);
+}
+
 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
@@ -715,18 +849,11 @@ void CYScript::Replace(CYContext &context) {
     }
 }
 
-void CYProperty::Replace(CYContext &context) { $T()
-    context.Replace(value_);
-    next_->Replace(context);
-    if (value_ == NULL)
-        value_ = $U;
-}
-
 CYStatement *CYReturn::Replace(CYContext &context) {
     if (context.nonlocal_ != NULL) {
-        CYProperty *value(value_ == NULL ? NULL : $ CYProperty($S("$cyv"), value_));
+        CYProperty *value(value_ == NULL ? NULL : $ CYPropertyValue($S("$cyv"), value_));
         return $ cy::Syntax::Throw($ CYObject(
-            $ CYProperty($S("$cyk"), $V(context.nonlocal_->Target(context)), value)
+            $ CYPropertyValue($S("$cyk"), $V(context.nonlocal_->Target(context)), value)
         ));
     }
 
@@ -885,10 +1012,22 @@ CYNumber *CYString::Number(CYContext &context) {
     return NULL;
 }
 
+CYExpression *CYString::PropertyName(CYContext &context) {
+    return this;
+}
+
 CYString *CYString::String(CYContext &context) {
     return this;
 }
 
+CYExpression *CYSuperAccess::Replace(CYContext &context) {
+    return $C1($M($M($M($V(context.super_), $S("prototype")), property_), $S("bind")), $ CYThis());
+}
+
+CYExpression *CYSuperCall::Replace(CYContext &context) {
+    return $C($C1($M($V(context.super_), $S("bind")), $ CYThis()), arguments_);
+}
+
 CYStatement *CYSwitch::Replace(CYContext &context) {
     context.Replace(value_);
     clauses_->Replace(context);
@@ -1057,10 +1196,6 @@ CYStatement *CYWith::Replace(CYContext &context) {
     return this;
 }
 
-CYExpression *CYWord::ClassName(CYContext &context, bool object) {
-    CYString *name($S(this));
-    if (object)
-        return $C1($V("objc_getClass"), name);
-    else
-        return name;
+CYExpression *CYWord::PropertyName(CYContext &context) {
+    return $S(this);
 }
index 3fac91e325e5e3fe89bc285362630b5ce42d81ef..82eed60589d79a42caf7e7fbaf254215bdd19fb4 100644 (file)
 #define $N5(func, args...) \
     $N(func, $C5_(args))
 
-#define $L(arg0, args...) \
-    $ CYDeclaration($I(arg0), ##args)
+#define $L(args...) \
+    $ CYDeclaration(args)
 #define $L1(arg0) \
     $ CYDeclarations(arg0)
 #define $L2(arg0, args...) \
index 6300e305b031c89d2183d7df72a48273e0d308a6..5563b067ed0725b3cf22587f7d28e7cf667e085e 100644 (file)
@@ -453,6 +453,7 @@ XMLName {XMLNameStart}{XMLNamePart}*
 "char"            L /*FII*/ F(tk::_char_, hi::Type);
 "class"           L /*FFK*/ F(tk::_class_, hi::Meta);
 "const"           L /*FFK*/ F(tk::_const_, hi::Meta);
+"constructor"     L /*III*/ F(tk::_constructor_, hi::Special);
 "continue"        L /*KKK*/ F(tk::_continue_, hi::Control);
 "debugger"        L /*FKK*/ F(tk::_debugger_, hi::Meta);
 "default"         L /*KKK*/ F(tk::_default_, hi::Control);
@@ -487,12 +488,13 @@ XMLName {XMLNameStart}{XMLNamePart}*
 "package"         L /*FSS*/ F(tk::_package_, hi::Meta);
 "private"         L /*FSS*/ F(tk::_private_, hi::Meta);
 "protected"       L /*FSS*/ F(tk::_protected_, hi::Meta);
+"prototype"       L /*III*/ F(tk::_prototype_, hi::Special);
 "public"          L /*FSS*/ F(tk::_public_, hi::Meta);
 "return"          L /*KKK*/ F(yyextra->return_.top() ? tk::_return__ : tk::_return_, hi::Control);
 "set"             L /*III*/ F(tk::_set_, hi::Meta);
 "short"           L /*FII*/ F(tk::_short_, hi::Type);
 "static"          L /*FS?*/ F(tk::_static_, hi::Meta);
-"super"           L /*FFK*/ F(tk::_super_, hi::Constant);
+"super"           L /*FFK*/ F(yyextra->super_.top() ? tk::_super__ : tk::_super_, hi::Constant);
 "switch"          L /*KKK*/ F(tk::_switch_, hi::Control);
 "synchronized"    L /*FII*/ F(tk::_synchronized_, hi::Meta);
 "this"            L /*KKK*/ F(tk::_this_, hi::Constant);
index 82b1392dd6bad5b45efa82802f497220d98cacf0..e3999e3c63e2037e3a272edefd3a622fa7037390 100644 (file)
@@ -108,13 +108,22 @@ struct CYOutput {
     }
 };
 
+struct CYExpression;
+struct CYAssignment;
+
 struct CYPropertyName {
+    virtual bool Computed() const {
+        return false;
+    }
+
+    virtual bool Constructor() const {
+        return false;
+    }
+
+    virtual CYExpression *PropertyName(CYContext &context) = 0;
     virtual void PropertyName(CYOutput &out) const = 0;
 };
 
-struct CYExpression;
-struct CYAssignment;
-
 enum CYNeeded {
     CYNever     = -1,
     CYSometimes =  0,
@@ -125,12 +134,13 @@ enum CYFlags {
     CYNoFlags =      0,
     CYNoBrace =      (1 << 0),
     CYNoFunction =   (1 << 1),
-    CYNoIn =         (1 << 2),
-    CYNoCall =       (1 << 3),
-    CYNoRightHand =  (1 << 4),
-    CYNoDangle =     (1 << 5),
-    CYNoInteger =    (1 << 6),
-    CYNoBF =         (CYNoBrace | CYNoFunction),
+    CYNoClass =      (1 << 2),
+    CYNoIn =         (1 << 3),
+    CYNoCall =       (1 << 4),
+    CYNoRightHand =  (1 << 5),
+    CYNoDangle =     (1 << 6),
+    CYNoInteger =    (1 << 7),
+    CYNoBFC =        (CYNoBrace | CYNoFunction | CYNoClass),
 };
 
 _finline CYFlags operator ~(CYFlags rhs) {
@@ -154,7 +164,7 @@ _finline CYFlags CYLeft(CYFlags flags) {
 }
 
 _finline CYFlags CYRight(CYFlags flags) {
-    return flags & ~CYNoBF;
+    return flags & ~CYNoBFC;
 }
 
 _finline CYFlags CYCenter(CYFlags flags) {
@@ -189,44 +199,11 @@ struct CYStatement :
     virtual void Output(CYOutput &out, CYFlags flags) const = 0;
 };
 
-struct CYStatements {
-    CYStatement *first_;
-    CYStatement *last_;
-
-    CYStatements() :
-        first_(NULL),
-        last_(NULL)
-    {
-    }
-
-    operator CYStatement *() const {
-        return first_;
-    }
-
-    CYStatements &operator ->*(CYStatement *next) {
-        if (next != NULL)
-            if (first_ == NULL) {
-                first_ = next;
-                last_ = next;
-            } else for (;; last_ = last_->next_)
-                if (last_->next_ == NULL) {
-                    last_->next_ = next;
-                    last_ = next;
-                    break;
-                }
-        return *this;
-    }
-};
-
-struct CYClassName {
-    virtual CYExpression *ClassName(CYContext &context, bool object) = 0;
-    virtual void ClassName(CYOutput &out, bool object) const = 0;
-};
+typedef CYList<CYStatement> CYStatements;
 
 struct CYWord :
     CYThing,
-    CYPropertyName,
-    CYClassName
+    CYPropertyName
 {
     const char *word_;
 
@@ -239,11 +216,14 @@ struct CYWord :
         word_ = value;
     }
 
+    virtual bool Constructor() const {
+        return strcmp(word_, "constructor") == 0;
+    }
+
     virtual const char *Word() const;
     virtual void Output(CYOutput &out) const;
 
-    virtual CYExpression *ClassName(CYContext &context, bool object);
-    virtual void ClassName(CYOutput &out, bool object) const;
+    virtual CYExpression *PropertyName(CYContext &context);
     virtual void PropertyName(CYOutput &out) const;
 };
 
@@ -362,6 +342,7 @@ struct CYContext {
 
     CYScope *scope_;
     CYThisScope *this_;
+    CYIdentifier *super_;
 
     CYIdentifierUsageVector rename_;
 
@@ -373,6 +354,7 @@ struct CYContext {
         options_(options),
         scope_(NULL),
         this_(NULL),
+        super_(NULL),
         nonlocal_(NULL),
         nextlocal_(NULL),
         unique_(0)
@@ -485,7 +467,6 @@ struct CYString;
 struct CYExpression :
     CYForInitializer,
     CYForInInitializer,
-    CYClassName,
     CYThing
 {
     virtual int Precedence() const = 0;
@@ -503,9 +484,6 @@ struct CYExpression :
     virtual void Output(CYOutput &out, CYFlags flags) const = 0;
     void Output(CYOutput &out, int precedence, CYFlags flags) const;
 
-    virtual CYExpression *ClassName(CYContext &context, bool object);
-    virtual void ClassName(CYOutput &out, bool object) const;
-
     virtual CYExpression *Replace(CYContext &context) = 0;
     virtual CYAssignment *Assignment(CYContext &context);
 
@@ -780,6 +758,8 @@ struct CYString :
 
     CYString *Concat(CYContext &out, CYString *rhs) const;
     virtual void Output(CYOutput &out, CYFlags flags) const;
+
+    virtual CYExpression *PropertyName(CYContext &context);
     virtual void PropertyName(CYOutput &out) const;
 };
 
@@ -839,6 +819,26 @@ struct CYNumber :
     virtual CYString *String(CYContext &context);
 
     virtual void Output(CYOutput &out, CYFlags flags) const;
+
+    virtual CYExpression *PropertyName(CYContext &context);
+    virtual void PropertyName(CYOutput &out) const;
+};
+
+struct CYComputed :
+    CYPropertyName
+{
+    CYExpression *expression_;
+
+    CYComputed(CYExpression *expression) :
+        expression_(expression)
+    {
+    }
+
+    virtual bool Computed() const {
+        return true;
+    }
+
+    virtual CYExpression *PropertyName(CYContext &context);
     virtual void PropertyName(CYOutput &out) const;
 };
 
@@ -1116,24 +1116,6 @@ struct CYArray :
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
-struct CYProperty :
-    CYNext<CYProperty>,
-    CYThing
-{
-    CYPropertyName *name_;
-    CYExpression *value_;
-
-    CYProperty(CYPropertyName *name, CYExpression *value, CYProperty *next = NULL) :
-        CYNext<CYProperty>(next),
-        name_(name),
-        value_(value)
-    {
-    }
-
-    void Replace(CYContext &context);
-    virtual void Output(CYOutput &out) const;
-};
-
 struct CYDeclaration :
     CYForInInitializer
 {
@@ -1172,7 +1154,6 @@ struct CYDeclarations :
     void Replace(CYContext &context);
 
     CYExpression *Expression(CYContext &context);
-    CYProperty *Property(CYContext &context);
     CYArgument *Argument(CYContext &context);
     CYFunctionParameter *Parameter(CYContext &context);
 
@@ -1228,6 +1209,52 @@ struct CYLetStatement :
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
+struct CYBuilder {
+    CYList<CYDeclarations> declarations_;
+    CYList<CYStatement> statements_;
+
+    operator bool() const {
+        return statements_ != NULL;
+    }
+};
+
+struct CYProperty :
+    CYNext<CYProperty>,
+    CYThing
+{
+    CYPropertyName *name_;
+
+    CYProperty(CYPropertyName *name, CYProperty *next = NULL) :
+        CYNext<CYProperty>(next),
+        name_(name)
+    {
+    }
+
+    CYProperty *ReplaceAll(CYContext &context, CYBuilder &builder, CYExpression *self, bool update);
+    void Replace(CYContext &context, CYBuilder &builder, CYExpression *self, bool computed);
+
+    virtual void Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name) = 0;
+
+    virtual void Replace(CYContext &context) = 0;
+    virtual void Output(CYOutput &out) const;
+};
+
+struct CYPropertyValue :
+    CYProperty
+{
+    CYExpression *value_;
+
+    CYPropertyValue(CYPropertyName *name, CYExpression *value, CYProperty *next = NULL) :
+        CYProperty(name, next),
+        value_(value)
+    {
+    }
+
+    virtual void Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name);
+    virtual void Replace(CYContext &context);
+    virtual void Output(CYOutput &out) const;
+};
+
 struct CYFor :
     CYStatement
 {
@@ -1360,7 +1387,7 @@ struct New :
     CYExpression *constructor_;
     CYArgument *arguments_;
 
-    New(CYExpression *constructor, CYArgument *arguments) :
+    New(CYExpression *constructor, CYArgument *arguments = NULL) :
         constructor_(constructor),
         arguments_(arguments)
     {
@@ -1483,34 +1510,36 @@ struct CYWhile :
 };
 
 struct CYFunction {
-    CYIdentifier *name_;
     CYFunctionParameter *parameters_;
     CYStatement *code_;
 
     CYNonLocal *nonlocal_;
     bool implicit_;
     CYThisScope this_;
+    CYIdentifier *super_;
 
-    CYFunction(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *code) :
-        name_(name),
+    CYFunction(CYFunctionParameter *parameters, CYStatement *code) :
         parameters_(parameters),
         code_(code),
         nonlocal_(NULL),
-        implicit_(false)
+        implicit_(false),
+        super_(NULL)
     {
     }
 
-    void Inject(CYContext &context);
-    virtual void Replace_(CYContext &context, bool outer);
-    virtual void Output(CYOutput &out, CYFlags flags) const;
+    void Replace(CYContext &context);
+    void Output(CYOutput &out) const;
 };
 
 struct CYFunctionExpression :
     CYFunction,
     CYExpression
 {
+    CYIdentifier *name_;
+
     CYFunctionExpression(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *code) :
-        CYFunction(name, parameters, code)
+        CYFunction(parameters, code),
+        name_(name)
     {
     }
 
@@ -1526,7 +1555,7 @@ struct CYFatArrow :
     CYExpression
 {
     CYFatArrow(CYFunctionParameter *parameters, CYStatement *code) :
-        CYFunction(NULL, parameters, code)
+        CYFunction(parameters, code)
     {
     }
 
@@ -1542,10 +1571,13 @@ struct CYRubyProc :
     CYExpression
 {
     CYRubyProc(CYFunctionParameter *parameters, CYStatement *code) :
-        CYFunction(NULL, parameters, code)
+        CYFunction(parameters, code)
     {
     }
 
+    CYPrecedence(0)
+    CYRightHand(false)
+
     virtual CYExpression *Replace(CYContext &context);
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
@@ -1554,8 +1586,11 @@ struct CYFunctionStatement :
     CYFunction,
     CYStatement
 {
+    CYIdentifier *name_;
+
     CYFunctionStatement(CYIdentifier *name, CYFunctionParameter *parameters, CYStatement *code) :
-        CYFunction(name, parameters, code)
+        CYFunction(parameters, code),
+        name_(name)
     {
     }
 
@@ -1565,6 +1600,151 @@ struct CYFunctionStatement :
     virtual void Output(CYOutput &out, CYFlags flags) const;
 };
 
+struct CYPropertyMethod;
+
+struct CYMethod :
+    CYFunction,
+    CYProperty
+{
+    CYMethod(CYPropertyName *name, CYFunctionParameter *parameters, CYStatement *code, CYProperty *next = NULL) :
+        CYFunction(parameters, code),
+        CYProperty(name, next)
+    {
+    }
+
+    virtual CYFunctionExpression *Constructor();
+
+    using CYProperty::Replace;
+    virtual void Replace(CYContext &context);
+};
+
+struct CYPropertyGetter :
+    CYMethod
+{
+    CYPropertyGetter(CYPropertyName *name, CYStatement *code, CYProperty *next = NULL) :
+        CYMethod(name, NULL, code, next)
+    {
+    }
+
+    virtual void Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name);
+    virtual void Output(CYOutput &out) const;
+};
+
+struct CYPropertySetter :
+    CYMethod
+{
+    CYPropertySetter(CYPropertyName *name, CYFunctionParameter *parameters, CYStatement *code, CYProperty *next = NULL) :
+        CYMethod(name, parameters, code, next)
+    {
+    }
+
+    virtual void Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name);
+    virtual void Output(CYOutput &out) const;
+};
+
+struct CYPropertyMethod :
+    CYMethod
+{
+    CYPropertyMethod(CYPropertyName *name, CYFunctionParameter *parameters, CYStatement *code, CYProperty *next = NULL) :
+        CYMethod(name, parameters, code, next)
+    {
+    }
+
+    virtual CYFunctionExpression *Constructor();
+
+    virtual void Replace(CYContext &context, CYBuilder &builder, CYExpression *self, CYExpression *name);
+    virtual void Output(CYOutput &out) const;
+};
+
+struct CYClassTail :
+    CYThing
+{
+    CYExpression *extends_;
+
+    CYFunctionExpression *constructor_;
+    CYList<CYProperty> instance_;
+    CYList<CYProperty> static_;
+
+    CYClassTail(CYExpression *extends) :
+        extends_(extends),
+        constructor_(NULL)
+    {
+    }
+
+    void Output(CYOutput &out) const;
+};
+
+struct CYClassExpression :
+    CYExpression
+{
+    CYIdentifier *name_;
+    CYClassTail *tail_;
+
+    CYClassExpression(CYIdentifier *name, CYClassTail *tail) :
+        name_(name),
+        tail_(tail)
+    {
+    }
+
+    CYPrecedence(0)
+    CYRightHand(false)
+
+    virtual CYExpression *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
+struct CYClassStatement :
+    CYStatement
+{
+    CYIdentifier *name_;
+    CYClassTail *tail_;
+
+    CYClassStatement(CYIdentifier *name, CYClassTail *tail) :
+        name_(name),
+        tail_(tail)
+    {
+    }
+
+    CYCompact(Long)
+
+    virtual CYStatement *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
+struct CYSuperCall :
+    CYExpression
+{
+    CYArgument *arguments_;
+
+    CYSuperCall(CYArgument *arguments) :
+        arguments_(arguments)
+    {
+    }
+
+    CYPrecedence(2)
+    CYRightHand(false)
+
+    virtual CYExpression *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
+struct CYSuperAccess :
+    CYExpression
+{
+    CYExpression *property_;
+
+    CYSuperAccess(CYExpression *property) :
+        property_(property)
+    {
+    }
+
+    CYPrecedence(1)
+    CYRightHand(false)
+
+    virtual CYExpression *Replace(CYContext &context);
+    virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
 struct CYExpress :
     CYStatement
 {