From: Jay Freeman (saurik) Date: Mon, 7 Dec 2015 08:49:07 +0000 (-0800) Subject: Implement ECMAScript 6 class syntax (sort of?...). X-Git-Tag: v0.9.590~240 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/c5b15840ab1bb70218506531f9a73fe2d112b007?ds=sidebyside;hp=1abe53bff9f3ea0bebf749a4b49271c4eff7ec12 Implement ECMAScript 6 class syntax (sort of?...). --- diff --git a/Driver.cpp b/Driver.cpp index df31a03..83b9462 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -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); diff --git a/Driver.hpp b/Driver.hpp index fbc96d9..8b53c5b 100644 --- a/Driver.hpp +++ b/Driver.hpp @@ -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 in_; std::stack return_; + std::stack super_; std::stack template_; std::stack yield_; + std::stack class_; + bool newline_; bool last_; bool next_; diff --git a/List.hpp b/List.hpp index 30390eb..4caa536 100644 --- a/List.hpp +++ b/List.hpp @@ -63,6 +63,50 @@ Type_ *&CYGetLast(Type_ *&list) { return *next; } +template +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_) diff --git a/ObjectiveC/Output.cpp b/ObjectiveC/Output.cpp index 360a54e..76838d8 100644 --- a/ObjectiveC/Output.cpp +++ b/ObjectiveC/Output.cpp @@ -26,45 +26,29 @@ #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_) diff --git a/ObjectiveC/Replace.cpp b/ObjectiveC/Replace.cpp index 74e9227..fb7f1f8 100644 --- a/ObjectiveC/Replace.cpp +++ b/ObjectiveC/Replace.cpp @@ -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 diff --git a/ObjectiveC/Syntax.hpp b/ObjectiveC/Syntax.hpp index 025612a..5f6c726 100644 --- a/ObjectiveC/Syntax.hpp +++ b/ObjectiveC/Syntax.hpp @@ -110,13 +110,13 @@ struct CYSelector : virtual void Output(CYOutput &out, CYFlags flags) const; }; -struct CYClassField : - CYNext +struct CYImplementationField : + CYNext { CYTypedIdentifier *typed_; - CYClassField(CYTypedIdentifier *typed, CYClassField *next = NULL) : - CYNext(next), + CYImplementationField(CYTypedIdentifier *typed, CYImplementationField *next = NULL) : + CYNext(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) { diff --git a/Output.cpp b/Output.cpp index 1496509..ce8e00c 100644 --- a/Output.cpp +++ b/Output.cpp @@ -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_) { diff --git a/Parser.ypp.in b/Parser.ypp.in index fe1c5f3..6028184 100644 --- a/Parser.ypp.in +++ b/Parser.ypp.in @@ -42,11 +42,13 @@ %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_; } @@ -84,10 +86,9 @@ @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 CatchParameter %type ClassDeclaration %type ClassExpression +%type ClassHeritage +%type ClassHeritageOpt +%type ClassTail %type Comprehension %type ComprehensionFor %type ComprehensionIf %type ComprehensionTail -%type ComputedPropertyName +%type ComputedPropertyName %type ConditionalExpression %type ContinueStatement %type ConciseBody @@ -466,7 +473,7 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY %type GeneratorBody %type GeneratorDeclaration %type GeneratorExpression -%type GeneratorMethod +%type GeneratorMethod %type HoistableDeclaration %type Identifier %type IdentifierType @@ -487,9 +494,9 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY %type LiteralPropertyName %type LogicalANDExpression %type LogicalORExpression -%type MemberAccess +%type MemberAccess %type MemberExpression -%type MethodDefinition +%type MethodDefinition %type ModulePath %type MultiplicativeExpression %type NewExpression @@ -522,6 +529,8 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY %type StatementListOpt %type StatementListItem %type StrictFormalParameters +%type SuperCall +%type SuperProperty %type SwitchStatement %type TemplateLiteral %type TemplateSpans @@ -558,16 +567,15 @@ _finline int yylex(cy::parser::semantic_type *semantic, CYLocation *location, CY @begin ObjectiveC %type BoxableExpression %type CategoryStatement -%type ClassFieldListOpt -%type ClassFields -%type ClassStatement %type ClassSuperOpt +%type ImplementationFieldListOpt +%type ImplementationFields %type ClassMessageDeclaration %type ClassMessageDeclarationListOpt -%type ClassName %type ClassProtocolListOpt %type ClassProtocols %type ClassProtocolsOpt +%type ImplementationStatement %type MessageExpression %type MessageParameter %type 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_ diff --git a/Replace.cpp b/Replace.cpp index 2ac6942..4d1a2be 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -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() + ->* $ 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() + ->* $ 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); } diff --git a/Replace.hpp b/Replace.hpp index 3fac91e..82eed60 100644 --- a/Replace.hpp +++ b/Replace.hpp @@ -110,8 +110,8 @@ #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...) \ diff --git a/Scanner.lpp.in b/Scanner.lpp.in index 6300e30..5563b06 100644 --- a/Scanner.lpp.in +++ b/Scanner.lpp.in @@ -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); diff --git a/Syntax.hpp b/Syntax.hpp index 82b1392..e3999e3 100644 --- a/Syntax.hpp +++ b/Syntax.hpp @@ -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 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, - CYThing -{ - CYPropertyName *name_; - CYExpression *value_; - - CYProperty(CYPropertyName *name, CYExpression *value, CYProperty *next = NULL) : - CYNext(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 declarations_; + CYList statements_; + + operator bool() const { + return statements_ != NULL; + } +}; + +struct CYProperty : + CYNext, + CYThing +{ + CYPropertyName *name_; + + CYProperty(CYPropertyName *name, CYProperty *next = NULL) : + CYNext(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 instance_; + CYList 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 {