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