Commit 65ae6e92 authored by dslomov@chromium.org's avatar dslomov@chromium.org

Parse 'super' keyword.

BUG=v8:3330
LOG=N
R=arv@chromium.org, marja@chromium.org

Review URL: https://codereview.chromium.org/480543002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23157 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d9fe1e71
...@@ -1097,6 +1097,7 @@ DONT_OPTIMIZE_NODE(TryCatchStatement) ...@@ -1097,6 +1097,7 @@ DONT_OPTIMIZE_NODE(TryCatchStatement)
DONT_OPTIMIZE_NODE(TryFinallyStatement) DONT_OPTIMIZE_NODE(TryFinallyStatement)
DONT_OPTIMIZE_NODE(DebuggerStatement) DONT_OPTIMIZE_NODE(DebuggerStatement)
DONT_OPTIMIZE_NODE(NativeFunctionLiteral) DONT_OPTIMIZE_NODE(NativeFunctionLiteral)
DONT_OPTIMIZE_NODE(SuperReference)
DONT_OPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(Yield) DONT_OPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(Yield)
......
...@@ -94,6 +94,7 @@ namespace internal { ...@@ -94,6 +94,7 @@ namespace internal {
V(BinaryOperation) \ V(BinaryOperation) \
V(CompareOperation) \ V(CompareOperation) \
V(ThisFunction) \ V(ThisFunction) \
V(SuperReference) \
V(CaseClause) V(CaseClause)
#define AST_NODE_LIST(V) \ #define AST_NODE_LIST(V) \
...@@ -1710,6 +1711,10 @@ class Property V8_FINAL : public Expression, public FeedbackSlotInterface { ...@@ -1710,6 +1711,10 @@ class Property V8_FINAL : public Expression, public FeedbackSlotInterface {
void mark_for_call() { is_for_call_ = true; } void mark_for_call() { is_for_call_ = true; }
bool IsForCall() { return is_for_call_; } bool IsForCall() { return is_for_call_; }
bool IsSuperAccess() {
return obj()->IsSuperReference();
}
TypeFeedbackId PropertyFeedbackId() { return reuse(id()); } TypeFeedbackId PropertyFeedbackId() { return reuse(id()); }
virtual int ComputeFeedbackSlotCount() { return FLAG_vector_ics ? 1 : 0; } virtual int ComputeFeedbackSlotCount() { return FLAG_vector_ics ? 1 : 0; }
...@@ -2554,6 +2559,25 @@ class ThisFunction V8_FINAL : public Expression { ...@@ -2554,6 +2559,25 @@ class ThisFunction V8_FINAL : public Expression {
explicit ThisFunction(Zone* zone, int pos): Expression(zone, pos) {} explicit ThisFunction(Zone* zone, int pos): Expression(zone, pos) {}
}; };
class SuperReference V8_FINAL : public Expression {
public:
DECLARE_NODE_TYPE(SuperReference)
VariableProxy* this_var() const { return this_var_; }
TypeFeedbackId HomeObjectFeedbackId() { return reuse(id()); }
protected:
explicit SuperReference(Zone* zone, VariableProxy* this_var, int pos)
: Expression(zone, pos), this_var_(this_var) {
DCHECK(this_var->is_this());
}
VariableProxy* this_var_;
};
#undef DECLARE_NODE_TYPE #undef DECLARE_NODE_TYPE
...@@ -3472,6 +3496,11 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { ...@@ -3472,6 +3496,11 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
VISIT_AND_RETURN(ThisFunction, fun) VISIT_AND_RETURN(ThisFunction, fun)
} }
SuperReference* NewSuperReference(VariableProxy* this_var, int pos) {
SuperReference* super = new (zone_) SuperReference(zone_, this_var, pos);
VISIT_AND_RETURN(SuperReference, super);
}
#undef VISIT_AND_RETURN #undef VISIT_AND_RETURN
private: private:
......
...@@ -1540,6 +1540,11 @@ void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) { ...@@ -1540,6 +1540,11 @@ void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
} }
void AstGraphBuilder::VisitSuperReference(SuperReference* expr) {
UNREACHABLE();
}
void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); } void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); }
......
...@@ -160,6 +160,7 @@ DEFINE_BOOL(harmony_numeric_literals, false, ...@@ -160,6 +160,7 @@ DEFINE_BOOL(harmony_numeric_literals, false,
DEFINE_BOOL(harmony_strings, false, "enable harmony string") DEFINE_BOOL(harmony_strings, false, "enable harmony string")
DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays") DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays")
DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions") DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions")
DEFINE_BOOL(harmony_classes, false, "enable harmony classes")
DEFINE_BOOL(harmony, false, "enable all harmony features (except proxies)") DEFINE_BOOL(harmony, false, "enable all harmony features (except proxies)")
DEFINE_IMPLICATION(harmony, harmony_scoping) DEFINE_IMPLICATION(harmony, harmony_scoping)
...@@ -171,6 +172,7 @@ DEFINE_IMPLICATION(harmony, harmony_numeric_literals) ...@@ -171,6 +172,7 @@ DEFINE_IMPLICATION(harmony, harmony_numeric_literals)
DEFINE_IMPLICATION(harmony, harmony_strings) DEFINE_IMPLICATION(harmony, harmony_strings)
DEFINE_IMPLICATION(harmony, harmony_arrays) DEFINE_IMPLICATION(harmony, harmony_arrays)
DEFINE_IMPLICATION(harmony, harmony_arrow_functions) DEFINE_IMPLICATION(harmony, harmony_arrow_functions)
DEFINE_IMPLICATION(harmony, harmony_classes)
DEFINE_IMPLICATION(harmony_modules, harmony_scoping) DEFINE_IMPLICATION(harmony_modules, harmony_scoping)
DEFINE_IMPLICATION(harmony, es_staging) DEFINE_IMPLICATION(harmony, es_staging)
......
...@@ -285,6 +285,9 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) { ...@@ -285,6 +285,9 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
} }
void BreakableStatementChecker::VisitSuperReference(SuperReference* expr) {}
#define __ ACCESS_MASM(masm()) #define __ ACCESS_MASM(masm())
bool FullCodeGenerator::MakeCode(CompilationInfo* info) { bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
...@@ -819,6 +822,12 @@ void FullCodeGenerator::SetStatementPosition(Statement* stmt) { ...@@ -819,6 +822,12 @@ void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
} }
void FullCodeGenerator::VisitSuperReference(SuperReference* super) {
DCHECK(FLAG_harmony_classes);
UNIMPLEMENTED();
}
void FullCodeGenerator::SetExpressionPosition(Expression* expr) { void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
if (!info_->is_debug()) { if (!info_->is_debug()) {
CodeGenerator::RecordPositions(masm_, expr->position()); CodeGenerator::RecordPositions(masm_, expr->position());
......
...@@ -11185,6 +11185,11 @@ void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { ...@@ -11185,6 +11185,11 @@ void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
} }
void HOptimizedGraphBuilder::VisitSuperReference(SuperReference* expr) {
UNREACHABLE();
}
void HOptimizedGraphBuilder::VisitDeclarations( void HOptimizedGraphBuilder::VisitDeclarations(
ZoneList<Declaration*>* declarations) { ZoneList<Declaration*>* declarations) {
DCHECK(globals_.is_empty()); DCHECK(globals_.is_empty());
......
...@@ -167,7 +167,8 @@ var kMessages = { ...@@ -167,7 +167,8 @@ var kMessages = {
symbol_to_number: ["Cannot convert a Symbol value to a number"], symbol_to_number: ["Cannot convert a Symbol value to a number"],
invalid_module_path: ["Module does not export '", "%0", "', or export is not itself a module"], invalid_module_path: ["Module does not export '", "%0", "', or export is not itself a module"],
module_type_error: ["Module '", "%0", "' used improperly"], module_type_error: ["Module '", "%0", "' used improperly"],
module_export_undefined: ["Export '", "%0", "' is not defined in module"] module_export_undefined: ["Export '", "%0", "' is not defined in module"],
unexpected_super: ["'super' keyword unexpected here"]
}; };
......
...@@ -1022,7 +1022,7 @@ template <class C> inline bool Is(Object* obj); ...@@ -1022,7 +1022,7 @@ template <class C> inline bool Is(Object* obj);
V(OrderedHashTable) V(OrderedHashTable)
#define ERROR_MESSAGES_LIST(V) \ #define ERROR_MESSAGES_LIST(V) \
V(kNoReason, "no reason") \ V(kNoReason, "no reason") \
\ \
V(k32BitValueInRegisterIsNotZeroExtended, \ V(k32BitValueInRegisterIsNotZeroExtended, \
...@@ -1089,24 +1089,17 @@ template <class C> inline bool Is(Object* obj); ...@@ -1089,24 +1089,17 @@ template <class C> inline bool Is(Object* obj);
V(kExpectedNonIdenticalObjects, "Expected non-identical objects") \ V(kExpectedNonIdenticalObjects, "Expected non-identical objects") \
V(kExpectedNonNullContext, "Expected non-null context") \ V(kExpectedNonNullContext, "Expected non-null context") \
V(kExpectedPositiveZero, "Expected +0.0") \ V(kExpectedPositiveZero, "Expected +0.0") \
V(kExpectedAllocationSiteInCell, \ V(kExpectedAllocationSiteInCell, "Expected AllocationSite in property cell")\
"Expected AllocationSite in property cell") \
V(kExpectedFixedArrayInFeedbackVector, \ V(kExpectedFixedArrayInFeedbackVector, \
"Expected fixed array in feedback vector") \ "Expected fixed array in feedback vector") \
V(kExpectedFixedArrayInRegisterA2, \ V(kExpectedFixedArrayInRegisterA2, "Expected fixed array in register a2") \
"Expected fixed array in register a2") \ V(kExpectedFixedArrayInRegisterEbx, "Expected fixed array in register ebx") \
V(kExpectedFixedArrayInRegisterEbx, \ V(kExpectedFixedArrayInRegisterR2, "Expected fixed array in register r2") \
"Expected fixed array in register ebx") \ V(kExpectedFixedArrayInRegisterRbx, "Expected fixed array in register rbx") \
V(kExpectedFixedArrayInRegisterR2, \
"Expected fixed array in register r2") \
V(kExpectedFixedArrayInRegisterRbx, \
"Expected fixed array in register rbx") \
V(kExpectedNewSpaceObject, "Expected new space object") \ V(kExpectedNewSpaceObject, "Expected new space object") \
V(kExpectedSmiOrHeapNumber, "Expected smi or HeapNumber") \ V(kExpectedSmiOrHeapNumber, "Expected smi or HeapNumber") \
V(kExpectedUndefinedOrCell, \ V(kExpectedUndefinedOrCell, "Expected undefined or cell in register") \
"Expected undefined or cell in register") \ V(kExpectingAlignmentForCopyBytes, "Expecting alignment for CopyBytes") \
V(kExpectingAlignmentForCopyBytes, \
"Expecting alignment for CopyBytes") \
V(kExportDeclaration, "Export declaration") \ V(kExportDeclaration, "Export declaration") \
V(kExternalStringExpectedButNotFound, \ V(kExternalStringExpectedButNotFound, \
"External string expected, but not found") \ "External string expected, but not found") \
...@@ -1179,8 +1172,7 @@ template <class C> inline bool Is(Object* obj); ...@@ -1179,8 +1172,7 @@ template <class C> inline bool Is(Object* obj);
V(kLhsHasBeenClobbered, "lhs has been clobbered") \ V(kLhsHasBeenClobbered, "lhs has been clobbered") \
V(kLiveBytesCountOverflowChunkSize, "Live Bytes Count overflow chunk size") \ V(kLiveBytesCountOverflowChunkSize, "Live Bytes Count overflow chunk size") \
V(kLiveEdit, "LiveEdit") \ V(kLiveEdit, "LiveEdit") \
V(kLookupVariableInCountOperation, \ V(kLookupVariableInCountOperation, "Lookup variable in count operation") \
"Lookup variable in count operation") \
V(kMapBecameDeprecated, "Map became deprecated") \ V(kMapBecameDeprecated, "Map became deprecated") \
V(kMapBecameUnstable, "Map became unstable") \ V(kMapBecameUnstable, "Map became unstable") \
V(kMapIsNoLongerInEax, "Map is no longer in eax") \ V(kMapIsNoLongerInEax, "Map is no longer in eax") \
...@@ -1191,25 +1183,23 @@ template <class C> inline bool Is(Object* obj); ...@@ -1191,25 +1183,23 @@ template <class C> inline bool Is(Object* obj);
V(kModuleVariable, "Module variable") \ V(kModuleVariable, "Module variable") \
V(kModuleUrl, "Module url") \ V(kModuleUrl, "Module url") \
V(kNativeFunctionLiteral, "Native function literal") \ V(kNativeFunctionLiteral, "Native function literal") \
V(kSuperReference, "Super reference") \
V(kNeedSmiLiteral, "Need a Smi literal here") \ V(kNeedSmiLiteral, "Need a Smi literal here") \
V(kNoCasesLeft, "No cases left") \ V(kNoCasesLeft, "No cases left") \
V(kNoEmptyArraysHereInEmitFastAsciiArrayJoin, \ V(kNoEmptyArraysHereInEmitFastAsciiArrayJoin, \
"No empty arrays here in EmitFastAsciiArrayJoin") \ "No empty arrays here in EmitFastAsciiArrayJoin") \
V(kNonInitializerAssignmentToConst, \ V(kNonInitializerAssignmentToConst, "Non-initializer assignment to const") \
"Non-initializer assignment to const") \
V(kNonSmiIndex, "Non-smi index") \ V(kNonSmiIndex, "Non-smi index") \
V(kNonSmiKeyInArrayLiteral, "Non-smi key in array literal") \ V(kNonSmiKeyInArrayLiteral, "Non-smi key in array literal") \
V(kNonSmiValue, "Non-smi value") \ V(kNonSmiValue, "Non-smi value") \
V(kNonObject, "Non-object value") \ V(kNonObject, "Non-object value") \
V(kNotEnoughVirtualRegistersForValues, \ V(kNotEnoughVirtualRegistersForValues, \
"Not enough virtual registers for values") \ "Not enough virtual registers for values") \
V(kNotEnoughSpillSlotsForOsr, \ V(kNotEnoughSpillSlotsForOsr, "Not enough spill slots for OSR") \
"Not enough spill slots for OSR") \
V(kNotEnoughVirtualRegistersRegalloc, \ V(kNotEnoughVirtualRegistersRegalloc, \
"Not enough virtual registers (regalloc)") \ "Not enough virtual registers (regalloc)") \
V(kObjectFoundInSmiOnlyArray, "Object found in smi-only array") \ V(kObjectFoundInSmiOnlyArray, "Object found in smi-only array") \
V(kObjectLiteralWithComplexProperty, \ V(kObjectLiteralWithComplexProperty, "Object literal with complex property")\
"Object literal with complex property") \
V(kOddballInStringTableIsNotUndefinedOrTheHole, \ V(kOddballInStringTableIsNotUndefinedOrTheHole, \
"Oddball in string table is not undefined or the hole") \ "Oddball in string table is not undefined or the hole") \
V(kOffsetOutOfRange, "Offset out of range") \ V(kOffsetOutOfRange, "Offset out of range") \
...@@ -1235,12 +1225,11 @@ template <class C> inline bool Is(Object* obj); ...@@ -1235,12 +1225,11 @@ template <class C> inline bool Is(Object* obj);
V(kReceivedInvalidReturnAddress, "Received invalid return address") \ V(kReceivedInvalidReturnAddress, "Received invalid return address") \
V(kReferenceToAVariableWhichRequiresDynamicLookup, \ V(kReferenceToAVariableWhichRequiresDynamicLookup, \
"Reference to a variable which requires dynamic lookup") \ "Reference to a variable which requires dynamic lookup") \
V(kReferenceToGlobalLexicalVariable, \ V(kReferenceToGlobalLexicalVariable, "Reference to global lexical variable")\
"Reference to global lexical variable") \
V(kReferenceToUninitializedVariable, "Reference to uninitialized variable") \ V(kReferenceToUninitializedVariable, "Reference to uninitialized variable") \
V(kRegisterDidNotMatchExpectedRoot, "Register did not match expected root") \ V(kRegisterDidNotMatchExpectedRoot, "Register did not match expected root") \
V(kRegisterWasClobbered, "Register was clobbered") \ V(kRegisterWasClobbered, "Register was clobbered") \
V(kRememberedSetPointerInNewSpace, "Remembered set pointer is in new space") \ V(kRememberedSetPointerInNewSpace, "Remembered set pointer is in new space")\
V(kReturnAddressNotFoundInFrame, "Return address not found in frame") \ V(kReturnAddressNotFoundInFrame, "Return address not found in frame") \
V(kRhsHasBeenClobbered, "Rhs has been clobbered") \ V(kRhsHasBeenClobbered, "Rhs has been clobbered") \
V(kScopedBlock, "ScopedBlock") \ V(kScopedBlock, "ScopedBlock") \
......
...@@ -619,6 +619,12 @@ Expression* ParserTraits::ThisExpression( ...@@ -619,6 +619,12 @@ Expression* ParserTraits::ThisExpression(
return factory->NewVariableProxy(scope->receiver(), pos); return factory->NewVariableProxy(scope->receiver(), pos);
} }
Expression* ParserTraits::SuperReference(
Scope* scope, AstNodeFactory<AstConstructionVisitor>* factory, int pos) {
return factory->NewSuperReference(
ThisExpression(scope, factory, pos)->AsVariableProxy(),
pos);
}
Literal* ParserTraits::ExpressionFromLiteral( Literal* ParserTraits::ExpressionFromLiteral(
Token::Value token, int pos, Token::Value token, int pos,
...@@ -731,6 +737,7 @@ Parser::Parser(CompilationInfo* info) ...@@ -731,6 +737,7 @@ Parser::Parser(CompilationInfo* info)
set_allow_generators(FLAG_harmony_generators); set_allow_generators(FLAG_harmony_generators);
set_allow_arrow_functions(FLAG_harmony_arrow_functions); set_allow_arrow_functions(FLAG_harmony_arrow_functions);
set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
set_allow_classes(FLAG_harmony_classes);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) { ++feature) {
use_counts_[feature] = 0; use_counts_[feature] = 0;
......
...@@ -549,6 +549,9 @@ class ParserTraits { ...@@ -549,6 +549,9 @@ class ParserTraits {
Expression* ThisExpression(Scope* scope, Expression* ThisExpression(Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory, AstNodeFactory<AstConstructionVisitor>* factory,
int pos = RelocInfo::kNoPosition); int pos = RelocInfo::kNoPosition);
Expression* SuperReference(Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory,
int pos = RelocInfo::kNoPosition);
Literal* ExpressionFromLiteral( Literal* ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner, Token::Value token, int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory); AstNodeFactory<AstConstructionVisitor>* factory);
......
...@@ -95,6 +95,7 @@ class ParserBase : public Traits { ...@@ -95,6 +95,7 @@ class ParserBase : public Traits {
bool allow_harmony_numeric_literals() const { bool allow_harmony_numeric_literals() const {
return scanner()->HarmonyNumericLiterals(); return scanner()->HarmonyNumericLiterals();
} }
bool allow_classes() const { return scanner()->HarmonyClasses(); }
// Setters that determine whether certain syntactical constructs are // Setters that determine whether certain syntactical constructs are
// allowed to be parsed by this instance of the parser. // allowed to be parsed by this instance of the parser.
...@@ -109,6 +110,9 @@ class ParserBase : public Traits { ...@@ -109,6 +110,9 @@ class ParserBase : public Traits {
void set_allow_harmony_numeric_literals(bool allow) { void set_allow_harmony_numeric_literals(bool allow) {
scanner()->SetHarmonyNumericLiterals(allow); scanner()->SetHarmonyNumericLiterals(allow);
} }
void set_allow_classes(bool allow) {
scanner()->SetHarmonyClasses(allow);
}
protected: protected:
friend class Traits::Type::Checkpoint; friend class Traits::Type::Checkpoint;
...@@ -677,6 +681,10 @@ class PreParserExpression { ...@@ -677,6 +681,10 @@ class PreParserExpression {
return PreParserExpression(kThisExpression); return PreParserExpression(kThisExpression);
} }
static PreParserExpression Super() {
return PreParserExpression(kSuperExpression);
}
static PreParserExpression ThisProperty() { static PreParserExpression ThisProperty() {
return PreParserExpression(kThisPropertyExpression); return PreParserExpression(kThisPropertyExpression);
} }
...@@ -798,7 +806,8 @@ class PreParserExpression { ...@@ -798,7 +806,8 @@ class PreParserExpression {
kThisExpression = (1 << 4), kThisExpression = (1 << 4),
kThisPropertyExpression = (2 << 4), kThisPropertyExpression = (2 << 4),
kPropertyExpression = (3 << 4), kPropertyExpression = (3 << 4),
kCallExpression = (4 << 4) kCallExpression = (4 << 4),
kSuperExpression = (5 << 4)
}; };
explicit PreParserExpression(int expression_code) : code_(expression_code) {} explicit PreParserExpression(int expression_code) : code_(expression_code) {}
...@@ -1248,6 +1257,11 @@ class PreParserTraits { ...@@ -1248,6 +1257,11 @@ class PreParserTraits {
return PreParserExpression::This(); return PreParserExpression::This();
} }
static PreParserExpression SuperReference(PreParserScope* scope,
PreParserFactory* factory) {
return PreParserExpression::Super();
}
static PreParserExpression ExpressionFromLiteral( static PreParserExpression ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner, Token::Value token, int pos, Scanner* scanner,
PreParserFactory* factory) { PreParserFactory* factory) {
...@@ -2383,7 +2397,12 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) { ...@@ -2383,7 +2397,12 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
if (peek() == Token::NEW) { if (peek() == Token::NEW) {
Consume(Token::NEW); Consume(Token::NEW);
int new_pos = position(); int new_pos = position();
ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK); ExpressionT result = this->EmptyExpression();
if (Check(Token::SUPER)) {
result = this->SuperReference(scope_, factory());
} else {
result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
}
if (peek() == Token::LPAREN) { if (peek() == Token::LPAREN) {
// NewExpression with arguments. // NewExpression with arguments.
typename Traits::Type::ExpressionList args = typename Traits::Type::ExpressionList args =
...@@ -2397,7 +2416,7 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) { ...@@ -2397,7 +2416,7 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
return factory()->NewCallNew(result, this->NewExpressionList(0, zone_), return factory()->NewCallNew(result, this->NewExpressionList(0, zone_),
new_pos); new_pos);
} }
// No 'new' keyword. // No 'new' or 'super' keyword.
return this->ParseMemberExpression(ok); return this->ParseMemberExpression(ok);
} }
...@@ -2438,6 +2457,19 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) { ...@@ -2438,6 +2457,19 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) {
function_type, function_type,
FunctionLiteral::NORMAL_ARITY, FunctionLiteral::NORMAL_ARITY,
CHECK_OK); CHECK_OK);
} else if (peek() == Token::SUPER) {
int beg_pos = position();
Consume(Token::SUPER);
Token::Value next = peek();
if (next == Token::PERIOD || next == Token::LBRACK ||
next == Token::LPAREN) {
result = this->SuperReference(scope_, factory());
} else {
ReportMessageAt(Scanner::Location(beg_pos, position()),
"unexpected_super");
*ok = false;
return this->EmptyExpression();
}
} else { } else {
result = ParsePrimaryExpression(CHECK_OK); result = ParsePrimaryExpression(CHECK_OK);
} }
......
...@@ -447,6 +447,11 @@ void PrettyPrinter::VisitThisFunction(ThisFunction* node) { ...@@ -447,6 +447,11 @@ void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
} }
void PrettyPrinter::VisitSuperReference(SuperReference* node) {
Print("<super-reference>");
}
const char* PrettyPrinter::Print(AstNode* node) { const char* PrettyPrinter::Print(AstNode* node) {
Init(); Init();
Visit(node); Visit(node);
...@@ -1145,6 +1150,11 @@ void AstPrinter::VisitThisFunction(ThisFunction* node) { ...@@ -1145,6 +1150,11 @@ void AstPrinter::VisitThisFunction(ThisFunction* node) {
IndentedScope indent(this, "THIS-FUNCTION"); IndentedScope indent(this, "THIS-FUNCTION");
} }
void AstPrinter::VisitSuperReference(SuperReference* node) {
IndentedScope indent(this, "SUPER-REFERENCE");
}
#endif // DEBUG #endif // DEBUG
} } // namespace v8::internal } } // namespace v8::internal
This diff is collapsed.
...@@ -438,6 +438,12 @@ class Scanner { ...@@ -438,6 +438,12 @@ class Scanner {
void SetHarmonyNumericLiterals(bool numeric_literals) { void SetHarmonyNumericLiterals(bool numeric_literals) {
harmony_numeric_literals_ = numeric_literals; harmony_numeric_literals_ = numeric_literals;
} }
bool HarmonyClasses() const {
return harmony_classes_;
}
void SetHarmonyClasses(bool classes) {
harmony_classes_ = classes;
}
// Returns true if there was a line terminator before the peek'ed token, // Returns true if there was a line terminator before the peek'ed token,
// possibly inside a multi-line comment. // possibly inside a multi-line comment.
...@@ -647,6 +653,8 @@ class Scanner { ...@@ -647,6 +653,8 @@ class Scanner {
bool harmony_modules_; bool harmony_modules_;
// Whether we scan 0o777 and 0b111 as numbers. // Whether we scan 0o777 and 0b111 as numbers.
bool harmony_numeric_literals_; bool harmony_numeric_literals_;
// Whether we scan 'super' as keyword.
bool harmony_classes_;
}; };
} } // namespace v8::internal } } // namespace v8::internal
......
...@@ -153,6 +153,7 @@ namespace internal { ...@@ -153,6 +153,7 @@ namespace internal {
K(IMPORT, "import", 0) \ K(IMPORT, "import", 0) \
K(LET, "let", 0) \ K(LET, "let", 0) \
K(YIELD, "yield", 0) \ K(YIELD, "yield", 0) \
K(SUPER, "super", 0) \
\ \
/* Illegal token - not able to scan. */ \ /* Illegal token - not able to scan. */ \
T(ILLEGAL, "ILLEGAL", 0) \ T(ILLEGAL, "ILLEGAL", 0) \
......
...@@ -723,6 +723,9 @@ void AstTyper::VisitThisFunction(ThisFunction* expr) { ...@@ -723,6 +723,9 @@ void AstTyper::VisitThisFunction(ThisFunction* expr) {
} }
void AstTyper::VisitSuperReference(SuperReference* expr) {}
void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
for (int i = 0; i < decls->length(); ++i) { for (int i = 0; i < decls->length(); ++i) {
Declaration* decl = decls->at(i); Declaration* decl = decls->at(i);
......
...@@ -72,6 +72,7 @@ TEST(ScanKeywords) { ...@@ -72,6 +72,7 @@ TEST(ScanKeywords) {
// The scanner should parse Harmony keywords for this test. // The scanner should parse Harmony keywords for this test.
scanner.SetHarmonyScoping(true); scanner.SetHarmonyScoping(true);
scanner.SetHarmonyModules(true); scanner.SetHarmonyModules(true);
scanner.SetHarmonyClasses(true);
scanner.Initialize(&stream); scanner.Initialize(&stream);
CHECK_EQ(key_token.token, scanner.Next()); CHECK_EQ(key_token.token, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next());
...@@ -1209,7 +1210,8 @@ enum ParserFlag { ...@@ -1209,7 +1210,8 @@ enum ParserFlag {
kAllowModules, kAllowModules,
kAllowGenerators, kAllowGenerators,
kAllowHarmonyNumericLiterals, kAllowHarmonyNumericLiterals,
kAllowArrowFunctions kAllowArrowFunctions,
kAllowClasses
}; };
...@@ -1230,6 +1232,7 @@ void SetParserFlags(i::ParserBase<Traits>* parser, ...@@ -1230,6 +1232,7 @@ void SetParserFlags(i::ParserBase<Traits>* parser,
parser->set_allow_harmony_numeric_literals( parser->set_allow_harmony_numeric_literals(
flags.Contains(kAllowHarmonyNumericLiterals)); flags.Contains(kAllowHarmonyNumericLiterals));
parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions)); parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
parser->set_allow_classes(flags.Contains(kAllowClasses));
} }
...@@ -1512,7 +1515,8 @@ void RunParserSyncTest(const char* context_data[][2], ...@@ -1512,7 +1515,8 @@ void RunParserSyncTest(const char* context_data[][2],
static const ParserFlag default_flags[] = { static const ParserFlag default_flags[] = {
kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowLazy, kAllowHarmonyScoping, kAllowModules,
kAllowGenerators, kAllowNativesSyntax, kAllowArrowFunctions}; kAllowGenerators, kAllowNativesSyntax, kAllowArrowFunctions,
kAllowClasses};
ParserFlag* generated_flags = NULL; ParserFlag* generated_flags = NULL;
if (flags == NULL) { if (flags == NULL) {
flags = default_flags; flags = default_flags;
...@@ -3343,3 +3347,47 @@ TEST(NoErrorsArrowFunctions) { ...@@ -3343,3 +3347,47 @@ TEST(NoErrorsArrowFunctions) {
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
always_flags, ARRAY_SIZE(always_flags)); always_flags, ARRAY_SIZE(always_flags));
} }
TEST(NoErrorsSuper) {
// Tests that parser and preparser accept 'super' keyword in right places.
const char* context_data[][2] = {{"", ";"},
{"k = ", ";"},
{"foo(", ");"},
{NULL, NULL}};
const char* statement_data[] = {
"super.x",
"super[27]",
"new super",
"new super()",
"new super(12, 45)",
"new new super",
"new new super()",
"new new super()()",
"z.super", // Ok, property lookup.
NULL};
static const ParserFlag always_flags[] = {kAllowClasses};
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
always_flags, ARRAY_SIZE(always_flags));
}
TEST(ErrorsSuper) {
// Tests that parser and preparser generate same errors for 'super'.
const char* context_data[][2] = {{"", ";"},
{"k = ", ";"},
{"foo(", ");"},
{NULL, NULL}};
const char* statement_data[] = {
"super = x",
"y = super",
"f(super)",
NULL};
static const ParserFlag always_flags[] = {kAllowClasses};
RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
always_flags, ARRAY_SIZE(always_flags));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment