Commit 7efd2eb1 authored by arv@chromium.org's avatar arv@chromium.org

Class syntax parsing

This implements parsing for ClassExpression and ClassDeclaration.
The runtime is not yet implemented and the value is currently
hard coded to undefined.

BUG=v8:3330
LOG=Y
R=dslomov@chromium.org, marja@chromium.org, rossberg@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23988 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7062b8fb
...@@ -235,32 +235,33 @@ class AstValue : public ZoneObject { ...@@ -235,32 +235,33 @@ class AstValue : public ZoneObject {
// For generating string constants. // For generating string constants.
#define STRING_CONSTANTS(F) \ #define STRING_CONSTANTS(F) \
F(anonymous_function, "(anonymous function)") \ F(anonymous_function, "(anonymous function)") \
F(arguments, "arguments") \ F(arguments, "arguments") \
F(done, "done") \ F(constructor, "constructor") \
F(dot, ".") \ F(done, "done") \
F(dot_for, ".for") \ F(dot, ".") \
F(dot_generator, ".generator") \ F(dot_for, ".for") \
F(dot_generator_object, ".generator_object") \ F(dot_generator, ".generator") \
F(dot_iterator, ".iterator") \ F(dot_generator_object, ".generator_object") \
F(dot_module, ".module") \ F(dot_iterator, ".iterator") \
F(dot_result, ".result") \ F(dot_module, ".module") \
F(empty, "") \ F(dot_result, ".result") \
F(eval, "eval") \ F(empty, "") \
F(eval, "eval") \
F(initialize_const_global, "initializeConstGlobal") \ F(initialize_const_global, "initializeConstGlobal") \
F(initialize_var_global, "initializeVarGlobal") \ F(initialize_var_global, "initializeVarGlobal") \
F(make_reference_error, "MakeReferenceError") \ F(make_reference_error, "MakeReferenceError") \
F(make_syntax_error, "MakeSyntaxError") \ F(make_syntax_error, "MakeSyntaxError") \
F(make_type_error, "MakeTypeError") \ F(make_type_error, "MakeTypeError") \
F(module, "module") \ F(module, "module") \
F(native, "native") \ F(native, "native") \
F(next, "next") \ F(next, "next") \
F(proto, "__proto__") \ F(proto, "__proto__") \
F(prototype, "prototype") \ F(prototype, "prototype") \
F(this, "this") \ F(this, "this") \
F(use_asm, "use asm") \ F(use_asm, "use asm") \
F(use_strict, "use strict") \ F(use_strict, "use strict") \
F(value, "value") F(value, "value")
......
...@@ -173,10 +173,12 @@ void FunctionLiteral::InitializeSharedInfo( ...@@ -173,10 +173,12 @@ void FunctionLiteral::InitializeSharedInfo(
ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone, ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone,
AstValueFactory* ast_value_factory, AstValueFactory* ast_value_factory,
Literal* key, Expression* value) { Literal* key, Expression* value,
bool is_static) {
emit_store_ = true; emit_store_ = true;
key_ = key; key_ = key;
value_ = value; value_ = value;
is_static_ = is_static;
if (key->raw_value()->EqualsString(ast_value_factory->proto_string())) { if (key->raw_value()->EqualsString(ast_value_factory->proto_string())) {
kind_ = PROTOTYPE; kind_ = PROTOTYPE;
} else if (value_->AsMaterializedLiteral() != NULL) { } else if (value_->AsMaterializedLiteral() != NULL) {
...@@ -189,11 +191,13 @@ ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone, ...@@ -189,11 +191,13 @@ ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone,
} }
ObjectLiteralProperty::ObjectLiteralProperty( ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone, bool is_getter,
Zone* zone, bool is_getter, FunctionLiteral* value) { FunctionLiteral* value,
bool is_static) {
emit_store_ = true; emit_store_ = true;
value_ = value; value_ = value;
kind_ = is_getter ? GETTER : SETTER; kind_ = is_getter ? GETTER : SETTER;
is_static_ = is_static;
} }
...@@ -1090,6 +1094,7 @@ DONT_OPTIMIZE_NODE(ModuleUrl) ...@@ -1090,6 +1094,7 @@ DONT_OPTIMIZE_NODE(ModuleUrl)
DONT_OPTIMIZE_NODE(ModuleStatement) DONT_OPTIMIZE_NODE(ModuleStatement)
DONT_OPTIMIZE_NODE(WithStatement) DONT_OPTIMIZE_NODE(WithStatement)
DONT_OPTIMIZE_NODE(DebuggerStatement) DONT_OPTIMIZE_NODE(DebuggerStatement)
DONT_OPTIMIZE_NODE(ClassLiteral)
DONT_OPTIMIZE_NODE(NativeFunctionLiteral) DONT_OPTIMIZE_NODE(NativeFunctionLiteral)
DONT_OPTIMIZE_NODE(SuperReference) DONT_OPTIMIZE_NODE(SuperReference)
......
...@@ -40,12 +40,12 @@ namespace internal { ...@@ -40,12 +40,12 @@ namespace internal {
// Nodes of the abstract syntax tree. Only concrete classes are // Nodes of the abstract syntax tree. Only concrete classes are
// enumerated here. // enumerated here.
#define DECLARATION_NODE_LIST(V) \ #define DECLARATION_NODE_LIST(V) \
V(VariableDeclaration) \ V(VariableDeclaration) \
V(FunctionDeclaration) \ V(FunctionDeclaration) \
V(ModuleDeclaration) \ V(ModuleDeclaration) \
V(ImportDeclaration) \ V(ImportDeclaration) \
V(ExportDeclaration) \ V(ExportDeclaration)
#define MODULE_NODE_LIST(V) \ #define MODULE_NODE_LIST(V) \
V(ModuleLiteral) \ V(ModuleLiteral) \
...@@ -73,28 +73,29 @@ namespace internal { ...@@ -73,28 +73,29 @@ namespace internal {
V(TryFinallyStatement) \ V(TryFinallyStatement) \
V(DebuggerStatement) V(DebuggerStatement)
#define EXPRESSION_NODE_LIST(V) \ #define EXPRESSION_NODE_LIST(V) \
V(FunctionLiteral) \ V(FunctionLiteral) \
V(NativeFunctionLiteral) \ V(ClassLiteral) \
V(Conditional) \ V(NativeFunctionLiteral) \
V(VariableProxy) \ V(Conditional) \
V(Literal) \ V(VariableProxy) \
V(RegExpLiteral) \ V(Literal) \
V(ObjectLiteral) \ V(RegExpLiteral) \
V(ArrayLiteral) \ V(ObjectLiteral) \
V(Assignment) \ V(ArrayLiteral) \
V(Yield) \ V(Assignment) \
V(Throw) \ V(Yield) \
V(Property) \ V(Throw) \
V(Call) \ V(Property) \
V(CallNew) \ V(Call) \
V(CallRuntime) \ V(CallNew) \
V(UnaryOperation) \ V(CallRuntime) \
V(CountOperation) \ V(UnaryOperation) \
V(BinaryOperation) \ V(CountOperation) \
V(CompareOperation) \ V(BinaryOperation) \
V(ThisFunction) \ V(CompareOperation) \
V(SuperReference) \ V(ThisFunction) \
V(SuperReference) \
V(CaseClause) V(CaseClause)
#define AST_NODE_LIST(V) \ #define AST_NODE_LIST(V) \
...@@ -1459,7 +1460,7 @@ class ObjectLiteralProperty FINAL : public ZoneObject { ...@@ -1459,7 +1460,7 @@ class ObjectLiteralProperty FINAL : public ZoneObject {
}; };
ObjectLiteralProperty(Zone* zone, AstValueFactory* ast_value_factory, ObjectLiteralProperty(Zone* zone, AstValueFactory* ast_value_factory,
Literal* key, Expression* value); Literal* key, Expression* value, bool is_static);
Literal* key() { return key_; } Literal* key() { return key_; }
Expression* value() { return value_; } Expression* value() { return value_; }
...@@ -1478,7 +1479,8 @@ class ObjectLiteralProperty FINAL : public ZoneObject { ...@@ -1478,7 +1479,8 @@ class ObjectLiteralProperty FINAL : public ZoneObject {
protected: protected:
template<class> friend class AstNodeFactory; template<class> friend class AstNodeFactory;
ObjectLiteralProperty(Zone* zone, bool is_getter, FunctionLiteral* value); ObjectLiteralProperty(Zone* zone, bool is_getter, FunctionLiteral* value,
bool is_static);
void set_key(Literal* key) { key_ = key; } void set_key(Literal* key) { key_ = key; }
private: private:
...@@ -1486,6 +1488,7 @@ class ObjectLiteralProperty FINAL : public ZoneObject { ...@@ -1486,6 +1488,7 @@ class ObjectLiteralProperty FINAL : public ZoneObject {
Expression* value_; Expression* value_;
Kind kind_; Kind kind_;
bool emit_store_; bool emit_store_;
bool is_static_;
Handle<Map> receiver_type_; Handle<Map> receiver_type_;
}; };
...@@ -2498,6 +2501,40 @@ class FunctionLiteral FINAL : public Expression { ...@@ -2498,6 +2501,40 @@ class FunctionLiteral FINAL : public Expression {
}; };
class ClassLiteral FINAL : public Expression {
public:
typedef ObjectLiteralProperty Property;
DECLARE_NODE_TYPE(ClassLiteral)
Handle<String> name() const { return raw_name_->string(); }
const AstRawString* raw_name() const { return raw_name_; }
Expression* extends() const { return extends_; }
FunctionLiteral* constructor() const { return constructor_; }
ZoneList<Property*>* properties() const { return properties_; }
protected:
ClassLiteral(Zone* zone, const AstRawString* name, Expression* extends,
FunctionLiteral* constructor, ZoneList<Property*>* properties,
AstValueFactory* ast_value_factory, int position, IdGen* id_gen)
: Expression(zone, position, id_gen),
raw_name_(name),
raw_inferred_name_(ast_value_factory->empty_string()),
extends_(extends),
constructor_(constructor),
properties_(properties) {}
private:
const AstRawString* raw_name_;
Handle<String> name_;
const AstString* raw_inferred_name_;
Handle<String> inferred_name_;
Expression* extends_;
FunctionLiteral* constructor_;
ZoneList<Property*>* properties_;
};
class NativeFunctionLiteral FINAL : public Expression { class NativeFunctionLiteral FINAL : public Expression {
public: public:
DECLARE_NODE_TYPE(NativeFunctionLiteral) DECLARE_NODE_TYPE(NativeFunctionLiteral)
...@@ -3300,16 +3337,17 @@ class AstNodeFactory FINAL BASE_EMBEDDED { ...@@ -3300,16 +3337,17 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
} }
ObjectLiteral::Property* NewObjectLiteralProperty(Literal* key, ObjectLiteral::Property* NewObjectLiteralProperty(Literal* key,
Expression* value) { Expression* value,
return new (zone_) bool is_static) {
ObjectLiteral::Property(zone_, ast_value_factory_, key, value); return new (zone_) ObjectLiteral::Property(zone_, ast_value_factory_, key,
value, is_static);
} }
ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter, ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter,
FunctionLiteral* value, FunctionLiteral* value,
int pos) { int pos, bool is_static) {
ObjectLiteral::Property* prop = ObjectLiteral::Property* prop =
new(zone_) ObjectLiteral::Property(zone_, is_getter, value); new (zone_) ObjectLiteral::Property(zone_, is_getter, value, is_static);
prop->set_key(NewStringLiteral(value->raw_name(), pos)); prop->set_key(NewStringLiteral(value->raw_name(), pos));
return prop; // Not an AST node, will not be visited. return prop; // Not an AST node, will not be visited.
} }
...@@ -3465,6 +3503,17 @@ class AstNodeFactory FINAL BASE_EMBEDDED { ...@@ -3465,6 +3503,17 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
return lit; return lit;
} }
ClassLiteral* NewClassLiteral(const AstRawString* name, Expression* extends,
FunctionLiteral* constructor,
ZoneList<ObjectLiteral::Property*>* properties,
AstValueFactory* ast_value_factory,
int position) {
ClassLiteral* lit =
new (zone_) ClassLiteral(zone_, name, extends, constructor, properties,
ast_value_factory, position, id_gen_);
VISIT_AND_RETURN(ClassLiteral, lit)
}
NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name, NativeFunctionLiteral* NewNativeFunctionLiteral(const AstRawString* name,
v8::Extension* extension, v8::Extension* extension,
int pos) { int pos) {
......
...@@ -812,6 +812,12 @@ void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -812,6 +812,12 @@ void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
} }
void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
// TODO(arv): Implement.
UNREACHABLE();
}
void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -175,6 +175,8 @@ DEFINE_IMPLICATION(harmony, harmony_arrow_functions) ...@@ -175,6 +175,8 @@ DEFINE_IMPLICATION(harmony, harmony_arrow_functions)
DEFINE_IMPLICATION(harmony, harmony_classes) DEFINE_IMPLICATION(harmony, harmony_classes)
DEFINE_IMPLICATION(harmony, harmony_object_literals) DEFINE_IMPLICATION(harmony, harmony_object_literals)
DEFINE_IMPLICATION(harmony_modules, harmony_scoping) DEFINE_IMPLICATION(harmony_modules, harmony_scoping)
DEFINE_IMPLICATION(harmony_classes, harmony_scoping)
DEFINE_IMPLICATION(harmony_classes, harmony_object_literals)
DEFINE_IMPLICATION(harmony, es_staging) DEFINE_IMPLICATION(harmony, es_staging)
......
...@@ -33,18 +33,22 @@ void BreakableStatementChecker::VisitVariableDeclaration( ...@@ -33,18 +33,22 @@ void BreakableStatementChecker::VisitVariableDeclaration(
VariableDeclaration* decl) { VariableDeclaration* decl) {
} }
void BreakableStatementChecker::VisitFunctionDeclaration( void BreakableStatementChecker::VisitFunctionDeclaration(
FunctionDeclaration* decl) { FunctionDeclaration* decl) {
} }
void BreakableStatementChecker::VisitModuleDeclaration( void BreakableStatementChecker::VisitModuleDeclaration(
ModuleDeclaration* decl) { ModuleDeclaration* decl) {
} }
void BreakableStatementChecker::VisitImportDeclaration( void BreakableStatementChecker::VisitImportDeclaration(
ImportDeclaration* decl) { ImportDeclaration* decl) {
} }
void BreakableStatementChecker::VisitExportDeclaration( void BreakableStatementChecker::VisitExportDeclaration(
ExportDeclaration* decl) { ExportDeclaration* decl) {
} }
...@@ -178,6 +182,13 @@ void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -178,6 +182,13 @@ void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
} }
void BreakableStatementChecker::VisitClassLiteral(ClassLiteral* expr) {
if (expr->extends() != NULL) {
Visit(expr->extends());
}
}
void BreakableStatementChecker::VisitNativeFunctionLiteral( void BreakableStatementChecker::VisitNativeFunctionLiteral(
NativeFunctionLiteral* expr) { NativeFunctionLiteral* expr) {
} }
...@@ -1531,6 +1542,16 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -1531,6 +1542,16 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
} }
void FullCodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
// TODO(arv): Implement
Comment cmnt(masm_, "[ ClassLiteral");
if (expr->extends() != NULL) {
VisitForEffect(expr->extends());
}
context()->Plug(isolate()->factory()->undefined_value());
}
void FullCodeGenerator::VisitNativeFunctionLiteral( void FullCodeGenerator::VisitNativeFunctionLiteral(
NativeFunctionLiteral* expr) { NativeFunctionLiteral* expr) {
Comment cmnt(masm_, "[ NativeFunctionLiteral"); Comment cmnt(masm_, "[ NativeFunctionLiteral");
......
...@@ -5248,6 +5248,14 @@ void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -5248,6 +5248,14 @@ void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
} }
void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
DCHECK(!HasStackOverflow());
DCHECK(current_block() != NULL);
DCHECK(current_block()->HasPredecessor());
return Bailout(kClassLiteral);
}
void HOptimizedGraphBuilder::VisitNativeFunctionLiteral( void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
NativeFunctionLiteral* expr) { NativeFunctionLiteral* expr) {
DCHECK(!HasStackOverflow()); DCHECK(!HasStackOverflow());
......
...@@ -8,6 +8,7 @@ var kMessages = { ...@@ -8,6 +8,7 @@ var kMessages = {
// Error // Error
cyclic_proto: ["Cyclic __proto__ value"], cyclic_proto: ["Cyclic __proto__ value"],
code_gen_from_strings: ["%0"], code_gen_from_strings: ["%0"],
constructor_special_method: ["Class constructor may not be an accessor"],
generator_running: ["Generator is already running"], generator_running: ["Generator is already running"],
generator_finished: ["Generator has already finished"], generator_finished: ["Generator has already finished"],
// TypeError // TypeError
...@@ -139,6 +140,7 @@ var kMessages = { ...@@ -139,6 +140,7 @@ var kMessages = {
array_indexof_not_defined: ["Array.getIndexOf: Argument undefined"], array_indexof_not_defined: ["Array.getIndexOf: Argument undefined"],
object_not_extensible: ["Can't add property ", "%0", ", object is not extensible"], object_not_extensible: ["Can't add property ", "%0", ", object is not extensible"],
illegal_access: ["Illegal access"], illegal_access: ["Illegal access"],
static_prototype: ["Classes may not have static property named prototype"],
strict_mode_with: ["Strict mode code may not include a with statement"], strict_mode_with: ["Strict mode code may not include a with statement"],
strict_eval_arguments: ["Unexpected eval or arguments in strict mode"], strict_eval_arguments: ["Unexpected eval or arguments in strict mode"],
too_many_arguments: ["Too many arguments in function call (only 65535 allowed)"], too_many_arguments: ["Too many arguments in function call (only 65535 allowed)"],
......
...@@ -1016,6 +1016,7 @@ template <class C> inline bool Is(Object* obj); ...@@ -1016,6 +1016,7 @@ template <class C> inline bool Is(Object* obj);
"Call to a JavaScript runtime function") \ "Call to a JavaScript runtime function") \
V(kCannotTranslatePositionInChangedArea, \ V(kCannotTranslatePositionInChangedArea, \
"Cannot translate position in changed area") \ "Cannot translate position in changed area") \
V(kClassLiteral, "Class literal") \
V(kCodeGenerationFailed, "Code generation failed") \ V(kCodeGenerationFailed, "Code generation failed") \
V(kCodeObjectNotProperlyPatched, "Code object not properly patched") \ V(kCodeObjectNotProperlyPatched, "Code object not properly patched") \
V(kCompoundAssignmentToLookupSlot, "Compound assignment to lookup slot") \ V(kCompoundAssignmentToLookupSlot, "Compound assignment to lookup slot") \
......
...@@ -366,6 +366,16 @@ bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const { ...@@ -366,6 +366,16 @@ bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
} }
bool ParserTraits::IsPrototype(const AstRawString* identifier) const {
return identifier == parser_->ast_value_factory()->prototype_string();
}
bool ParserTraits::IsConstructor(const AstRawString* identifier) const {
return identifier == parser_->ast_value_factory()->constructor_string();
}
bool ParserTraits::IsThisProperty(Expression* expression) { bool ParserTraits::IsThisProperty(Expression* expression) {
DCHECK(expression != NULL); DCHECK(expression != NULL);
Property* property = expression->AsProperty(); Property* property = expression->AsProperty();
...@@ -1136,6 +1146,8 @@ Statement* Parser::ParseModuleElement(ZoneList<const AstRawString*>* labels, ...@@ -1136,6 +1146,8 @@ Statement* Parser::ParseModuleElement(ZoneList<const AstRawString*>* labels,
switch (peek()) { switch (peek()) {
case Token::FUNCTION: case Token::FUNCTION:
return ParseFunctionDeclaration(NULL, ok); return ParseFunctionDeclaration(NULL, ok);
case Token::CLASS:
return ParseClassDeclaration(NULL, ok);
case Token::IMPORT: case Token::IMPORT:
return ParseImportDeclaration(ok); return ParseImportDeclaration(ok);
case Token::EXPORT: case Token::EXPORT:
...@@ -1475,6 +1487,10 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { ...@@ -1475,6 +1487,10 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
result = ParseFunctionDeclaration(&names, CHECK_OK); result = ParseFunctionDeclaration(&names, CHECK_OK);
break; break;
case Token::CLASS:
result = ParseClassDeclaration(&names, CHECK_OK);
break;
case Token::VAR: case Token::VAR:
case Token::LET: case Token::LET:
case Token::CONST: case Token::CONST:
...@@ -1537,10 +1553,13 @@ Statement* Parser::ParseBlockElement(ZoneList<const AstRawString*>* labels, ...@@ -1537,10 +1553,13 @@ Statement* Parser::ParseBlockElement(ZoneList<const AstRawString*>* labels,
// LetDeclaration // LetDeclaration
// ConstDeclaration // ConstDeclaration
// GeneratorDeclaration // GeneratorDeclaration
// ClassDeclaration
switch (peek()) { switch (peek()) {
case Token::FUNCTION: case Token::FUNCTION:
return ParseFunctionDeclaration(NULL, ok); return ParseFunctionDeclaration(NULL, ok);
case Token::CLASS:
return ParseClassDeclaration(NULL, ok);
case Token::CONST: case Token::CONST:
return ParseVariableStatement(kModuleElement, NULL, ok); return ParseVariableStatement(kModuleElement, NULL, ok);
case Token::LET: case Token::LET:
...@@ -1652,6 +1671,9 @@ Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, ...@@ -1652,6 +1671,9 @@ Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
return ParseFunctionDeclaration(NULL, ok); return ParseFunctionDeclaration(NULL, ok);
} }
case Token::CLASS:
return ParseClassDeclaration(NULL, ok);
case Token::DEBUGGER: case Token::DEBUGGER:
return ParseDebuggerStatement(ok); return ParseDebuggerStatement(ok);
...@@ -1920,6 +1942,47 @@ Statement* Parser::ParseFunctionDeclaration( ...@@ -1920,6 +1942,47 @@ Statement* Parser::ParseFunctionDeclaration(
} }
Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
bool* ok) {
// ClassDeclaration ::
// 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
//
// A ClassDeclaration
//
// class C { ... }
//
// has the same semantics as:
//
// let C = class C { ... };
//
// so rewrite it as such.
Expect(Token::CLASS, CHECK_OK);
int pos = position();
bool is_strict_reserved = false;
const AstRawString* name =
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
ClassLiteral* value = ParseClassLiteral(name, scanner()->location(),
is_strict_reserved, pos, CHECK_OK);
Block* block = factory()->NewBlock(NULL, 1, true, pos);
VariableMode mode = LET;
VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
Declaration* declaration =
factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
Declare(declaration, true, CHECK_OK);
Token::Value init_op = Token::INIT_LET;
Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos);
block->AddStatement(
factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
zone());
if (names) names->Add(name, zone());
return block;
}
Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
if (allow_harmony_scoping() && strict_mode() == STRICT) { if (allow_harmony_scoping() && strict_mode() == STRICT) {
return ParseScopedBlock(labels, ok); return ParseScopedBlock(labels, ok);
......
...@@ -363,6 +363,7 @@ class ParserTraits { ...@@ -363,6 +363,7 @@ class ParserTraits {
typedef v8::internal::Expression* Expression; typedef v8::internal::Expression* Expression;
typedef Yield* YieldExpression; typedef Yield* YieldExpression;
typedef v8::internal::FunctionLiteral* FunctionLiteral; typedef v8::internal::FunctionLiteral* FunctionLiteral;
typedef v8::internal::ClassLiteral* ClassLiteral;
typedef v8::internal::Literal* Literal; typedef v8::internal::Literal* Literal;
typedef ObjectLiteral::Property* ObjectLiteralProperty; typedef ObjectLiteral::Property* ObjectLiteralProperty;
typedef ZoneList<v8::internal::Expression*>* ExpressionList; typedef ZoneList<v8::internal::Expression*>* ExpressionList;
...@@ -401,6 +402,10 @@ class ParserTraits { ...@@ -401,6 +402,10 @@ class ParserTraits {
static bool IsIdentifier(Expression* expression); static bool IsIdentifier(Expression* expression);
bool IsPrototype(const AstRawString* identifier) const;
bool IsConstructor(const AstRawString* identifier) const;
static const AstRawString* AsIdentifier(Expression* expression) { static const AstRawString* AsIdentifier(Expression* expression) {
DCHECK(IsIdentifier(expression)); DCHECK(IsIdentifier(expression));
return expression->AsVariableProxy()->raw_name(); return expression->AsVariableProxy()->raw_name();
...@@ -518,6 +523,8 @@ class ParserTraits { ...@@ -518,6 +523,8 @@ class ParserTraits {
return NULL; return NULL;
} }
static ObjectLiteralProperty* EmptyObjectLiteralProperty() { return NULL; } static ObjectLiteralProperty* EmptyObjectLiteralProperty() { return NULL; }
static FunctionLiteral* EmptyFunctionLiteral() { return NULL; }
static ClassLiteral* EmptyClassLiteral() { return NULL; }
// Used in error return values. // Used in error return values.
static ZoneList<Expression*>* NullExpressionList() { static ZoneList<Expression*>* NullExpressionList() {
...@@ -705,6 +712,8 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -705,6 +712,8 @@ class Parser : public ParserBase<ParserTraits> {
Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok); Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names, Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
bool* ok); bool* ok);
Statement* ParseClassDeclaration(ZoneList<const AstRawString*>* names,
bool* ok);
Statement* ParseNativeDeclaration(bool* ok); Statement* ParseNativeDeclaration(bool* ok);
Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok); Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok);
Block* ParseVariableStatement(VariableDeclarationContext var_context, Block* ParseVariableStatement(VariableDeclarationContext var_context,
......
...@@ -78,6 +78,12 @@ PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) { ...@@ -78,6 +78,12 @@ PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
if (scanner->UnescapedLiteralMatches("arguments", 9)) { if (scanner->UnescapedLiteralMatches("arguments", 9)) {
return PreParserIdentifier::Arguments(); return PreParserIdentifier::Arguments();
} }
if (scanner->UnescapedLiteralMatches("prototype", 9)) {
return PreParserIdentifier::Prototype();
}
if (scanner->UnescapedLiteralMatches("constructor", 11)) {
return PreParserIdentifier::Constructor();
}
return PreParserIdentifier::Default(); return PreParserIdentifier::Default();
} }
...@@ -178,6 +184,8 @@ PreParser::Statement PreParser::ParseSourceElement(bool* ok) { ...@@ -178,6 +184,8 @@ PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
switch (peek()) { switch (peek()) {
case Token::FUNCTION: case Token::FUNCTION:
return ParseFunctionDeclaration(ok); return ParseFunctionDeclaration(ok);
case Token::CLASS:
return ParseClassDeclaration(ok);
case Token::CONST: case Token::CONST:
return ParseVariableStatement(kSourceElement, ok); return ParseVariableStatement(kSourceElement, ok);
case Token::LET: case Token::LET:
...@@ -305,6 +313,9 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) { ...@@ -305,6 +313,9 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) {
} }
} }
case Token::CLASS:
return ParseClassDeclaration(CHECK_OK);
case Token::DEBUGGER: case Token::DEBUGGER:
return ParseDebuggerStatement(ok); return ParseDebuggerStatement(ok);
...@@ -345,6 +356,18 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { ...@@ -345,6 +356,18 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
} }
PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
Expect(Token::CLASS, CHECK_OK);
int pos = position();
bool is_strict_reserved = false;
Identifier name =
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
CHECK_OK);
return Statement::Default();
}
PreParser::Statement PreParser::ParseBlock(bool* ok) { PreParser::Statement PreParser::ParseBlock(bool* ok) {
// Block :: // Block ::
// '{' Statement* '}' // '{' Statement* '}'
......
This diff is collapsed.
...@@ -289,6 +289,21 @@ void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) { ...@@ -289,6 +289,21 @@ void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
} }
void PrettyPrinter::VisitClassLiteral(ClassLiteral* node) {
Print("(class ");
PrintLiteral(node->name(), false);
if (node->extends()) {
Print(" extends ");
Visit(node->extends());
}
Print(" { ");
for (int i = 0; i < node->properties()->length(); i++) {
PrintObjectLiteralProperty(node->properties()->at(i));
}
Print(" })");
}
void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { void PrettyPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
Print("("); Print("(");
PrintLiteral(node->name(), false); PrintLiteral(node->name(), false);
...@@ -323,16 +338,22 @@ void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) { ...@@ -323,16 +338,22 @@ void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
Print("{ "); Print("{ ");
for (int i = 0; i < node->properties()->length(); i++) { for (int i = 0; i < node->properties()->length(); i++) {
if (i != 0) Print(","); if (i != 0) Print(",");
ObjectLiteral::Property* property = node->properties()->at(i); PrintObjectLiteralProperty(node->properties()->at(i));
Print(" ");
Visit(property->key());
Print(": ");
Visit(property->value());
} }
Print(" }"); Print(" }");
} }
void PrettyPrinter::PrintObjectLiteralProperty(
ObjectLiteralProperty* property) {
// TODO(arv): Better printing of methods etc.
Print(" ");
Visit(property->key());
Print(": ");
Visit(property->value());
}
void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) { void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
Print("[ "); Print("[ ");
for (int i = 0; i < node->values()->length(); i++) { for (int i = 0; i < node->values()->length(); i++) {
...@@ -969,6 +990,12 @@ void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) { ...@@ -969,6 +990,12 @@ void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
} }
void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
IndentedScope indent(this, "CLASS LITERAL");
PrintLiteralIndented("NAME", node->name(), false);
}
void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) {
IndentedScope indent(this, "NATIVE FUNC LITERAL"); IndentedScope indent(this, "NATIVE FUNC LITERAL");
PrintLiteralIndented("NAME", node->name(), false); PrintLiteralIndented("NAME", node->name(), false);
......
...@@ -52,6 +52,7 @@ class PrettyPrinter: public AstVisitor { ...@@ -52,6 +52,7 @@ class PrettyPrinter: public AstVisitor {
void PrintDeclarations(ZoneList<Declaration*>* declarations); void PrintDeclarations(ZoneList<Declaration*>* declarations);
void PrintFunctionLiteral(FunctionLiteral* function); void PrintFunctionLiteral(FunctionLiteral* function);
void PrintCaseClause(CaseClause* clause); void PrintCaseClause(CaseClause* clause);
void PrintObjectLiteralProperty(ObjectLiteralProperty* property);
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
}; };
......
This diff is collapsed.
...@@ -653,7 +653,7 @@ class Scanner { ...@@ -653,7 +653,7 @@ 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. // Whether we scan 'class', 'extends', 'static' and 'super' as keywords.
bool harmony_classes_; bool harmony_classes_;
}; };
......
...@@ -148,10 +148,13 @@ namespace internal { ...@@ -148,10 +148,13 @@ namespace internal {
/* Future reserved words (ECMA-262, section 7.6.1.2). */ \ /* Future reserved words (ECMA-262, section 7.6.1.2). */ \
T(FUTURE_RESERVED_WORD, NULL, 0) \ T(FUTURE_RESERVED_WORD, NULL, 0) \
T(FUTURE_STRICT_RESERVED_WORD, NULL, 0) \ T(FUTURE_STRICT_RESERVED_WORD, NULL, 0) \
K(CLASS, "class", 0) \
K(CONST, "const", 0) \ K(CONST, "const", 0) \
K(EXPORT, "export", 0) \ K(EXPORT, "export", 0) \
K(EXTENDS, "extends", 0) \
K(IMPORT, "import", 0) \ K(IMPORT, "import", 0) \
K(LET, "let", 0) \ K(LET, "let", 0) \
K(STATIC, "static", 0) \
K(YIELD, "yield", 0) \ K(YIELD, "yield", 0) \
K(SUPER, "super", 0) \ K(SUPER, "super", 0) \
\ \
......
...@@ -352,6 +352,9 @@ void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -352,6 +352,9 @@ void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
} }
void AstTyper::VisitClassLiteral(ClassLiteral* expr) {}
void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
} }
......
This diff is collapsed.
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