Refactor scope and function state tracking in (Pre)Parser.
Notes: - PreParser::Scope was a weird combination of Parser::FunctionState and Scope. Split it into two (PreParser::FunctionState and PreParser::Scope). This is necessary for unifying the Parser and the PreParser. - Scopes take care of language mode and tracking "with". - FunctionStates take care of counting material literal indexes, properties etc. and tracking generators. - PreParser::Scope::InsideWith was a hack to make a FunctionState-like object take care of tracking "with". It's now the responsibility fo PreParser::Scope and Scope. - PreParser::ScopeType is unnecessarly, there is already a ScopeType enum in v8globals.h. - Renamed scope stack variables so that they're consistent in Parser and PreParser. - Parser::FunctionState and Parser::BlockState had an unnecessary dependency to the Parser; they only need a couple of things from Parser. Broke the dependency. R=ulan@chromium.org BUG=v8:3126 LOG=N Review URL: https://codereview.chromium.org/148293011 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19319 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
96a1886637
commit
10ae9eb247
252
src/parser.cc
252
src/parser.cc
@ -464,48 +464,52 @@ class TargetScope BASE_EMBEDDED {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// FunctionState and BlockState together implement the parser's scope stack.
|
// FunctionState and BlockState together implement the parser's scope stack.
|
||||||
// The parser's current scope is in top_scope_. The BlockState and
|
// The parser's current scope is in scope_. The BlockState and
|
||||||
// FunctionState constructors push on the scope stack and the destructors
|
// FunctionState constructors push on the scope stack and the destructors
|
||||||
// pop. They are also used to hold the parser's per-function and per-block
|
// pop. They are also used to hold the parser's per-function and per-block
|
||||||
// state.
|
// state.
|
||||||
|
|
||||||
class Parser::BlockState BASE_EMBEDDED {
|
class Parser::BlockState BASE_EMBEDDED {
|
||||||
public:
|
public:
|
||||||
BlockState(Parser* parser, Scope* scope)
|
BlockState(Scope** scope_stack, Scope* scope)
|
||||||
: parser_(parser),
|
: scope_stack_(scope_stack),
|
||||||
outer_scope_(parser->top_scope_) {
|
outer_scope_(*scope_stack) {
|
||||||
parser->top_scope_ = scope;
|
*scope_stack = scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
~BlockState() { parser_->top_scope_ = outer_scope_; }
|
~BlockState() { *scope_stack_ = outer_scope_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Parser* parser_;
|
Scope** scope_stack_;
|
||||||
Scope* outer_scope_;
|
Scope* outer_scope_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Parser::FunctionState::FunctionState(Parser* parser, Scope* scope)
|
Parser::FunctionState::FunctionState(FunctionState** function_state_stack,
|
||||||
|
Scope** scope_stack, Scope* scope,
|
||||||
|
Zone* zone)
|
||||||
: next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
|
: next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
|
||||||
next_handler_index_(0),
|
next_handler_index_(0),
|
||||||
expected_property_count_(0),
|
expected_property_count_(0),
|
||||||
generator_object_variable_(NULL),
|
generator_object_variable_(NULL),
|
||||||
parser_(parser),
|
function_state_stack_(function_state_stack),
|
||||||
outer_function_state_(parser->current_function_state_),
|
outer_function_state_(*function_state_stack),
|
||||||
outer_scope_(parser->top_scope_),
|
scope_stack_(scope_stack),
|
||||||
saved_ast_node_id_(parser->zone()->isolate()->ast_node_id()),
|
outer_scope_(*scope_stack),
|
||||||
factory_(parser->zone()) {
|
isolate_(zone->isolate()),
|
||||||
parser->top_scope_ = scope;
|
saved_ast_node_id_(isolate_->ast_node_id()),
|
||||||
parser->current_function_state_ = this;
|
factory_(zone) {
|
||||||
parser->zone()->isolate()->set_ast_node_id(BailoutId::FirstUsable().ToInt());
|
*scope_stack_ = scope;
|
||||||
|
*function_state_stack = this;
|
||||||
|
isolate_->set_ast_node_id(BailoutId::FirstUsable().ToInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Parser::FunctionState::~FunctionState() {
|
Parser::FunctionState::~FunctionState() {
|
||||||
parser_->top_scope_ = outer_scope_;
|
*scope_stack_ = outer_scope_;
|
||||||
parser_->current_function_state_ = outer_function_state_;
|
*function_state_stack_ = outer_function_state_;
|
||||||
if (outer_function_state_ != NULL) {
|
if (outer_function_state_ != NULL) {
|
||||||
parser_->isolate()->set_ast_node_id(saved_ast_node_id_);
|
isolate_->set_ast_node_id(saved_ast_node_id_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,12 +538,12 @@ Parser::FunctionState::~FunctionState() {
|
|||||||
// Implementation of Parser
|
// Implementation of Parser
|
||||||
|
|
||||||
bool ParserTraits::is_classic_mode() const {
|
bool ParserTraits::is_classic_mode() const {
|
||||||
return parser_->top_scope_->is_classic_mode();
|
return parser_->scope_->is_classic_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ParserTraits::is_generator() const {
|
bool ParserTraits::is_generator() const {
|
||||||
return parser_->current_function_state_->is_generator();
|
return parser_->function_state_->is_generator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -552,7 +556,7 @@ bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const {
|
|||||||
|
|
||||||
|
|
||||||
int ParserTraits::NextMaterializedLiteralIndex() {
|
int ParserTraits::NextMaterializedLiteralIndex() {
|
||||||
return parser_->current_function_state_->NextMaterializedLiteralIndex();
|
return parser_->function_state_->NextMaterializedLiteralIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -636,9 +640,9 @@ Parser::Parser(CompilationInfo* info)
|
|||||||
script_(info->script()),
|
script_(info->script()),
|
||||||
scanner_(isolate_->unicode_cache()),
|
scanner_(isolate_->unicode_cache()),
|
||||||
reusable_preparser_(NULL),
|
reusable_preparser_(NULL),
|
||||||
top_scope_(NULL),
|
scope_(NULL),
|
||||||
original_scope_(NULL),
|
original_scope_(NULL),
|
||||||
current_function_state_(NULL),
|
function_state_(NULL),
|
||||||
target_stack_(NULL),
|
target_stack_(NULL),
|
||||||
extension_(info->extension()),
|
extension_(info->extension()),
|
||||||
pre_parse_data_(NULL),
|
pre_parse_data_(NULL),
|
||||||
@ -705,14 +709,14 @@ FunctionLiteral* Parser::ParseProgram() {
|
|||||||
|
|
||||||
FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
||||||
Handle<String> source) {
|
Handle<String> source) {
|
||||||
ASSERT(top_scope_ == NULL);
|
ASSERT(scope_ == NULL);
|
||||||
ASSERT(target_stack_ == NULL);
|
ASSERT(target_stack_ == NULL);
|
||||||
if (pre_parse_data_ != NULL) pre_parse_data_->Initialize();
|
if (pre_parse_data_ != NULL) pre_parse_data_->Initialize();
|
||||||
|
|
||||||
Handle<String> no_name = isolate()->factory()->empty_string();
|
Handle<String> no_name = isolate()->factory()->empty_string();
|
||||||
|
|
||||||
FunctionLiteral* result = NULL;
|
FunctionLiteral* result = NULL;
|
||||||
{ Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
|
{ Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
|
||||||
info->SetGlobalScope(scope);
|
info->SetGlobalScope(scope);
|
||||||
if (!info->context().is_null()) {
|
if (!info->context().is_null()) {
|
||||||
scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
|
scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
|
||||||
@ -738,19 +742,19 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
|||||||
ParsingModeScope parsing_mode(this, mode);
|
ParsingModeScope parsing_mode(this, mode);
|
||||||
|
|
||||||
// Enters 'scope'.
|
// Enters 'scope'.
|
||||||
FunctionState function_state(this, scope);
|
FunctionState function_state(&function_state_, &scope_, scope, zone());
|
||||||
|
|
||||||
top_scope_->SetLanguageMode(info->language_mode());
|
scope_->SetLanguageMode(info->language_mode());
|
||||||
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
|
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
int beg_pos = scanner().location().beg_pos;
|
int beg_pos = scanner().location().beg_pos;
|
||||||
ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
|
ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
|
||||||
if (ok && !top_scope_->is_classic_mode()) {
|
if (ok && !scope_->is_classic_mode()) {
|
||||||
CheckOctalLiteral(beg_pos, scanner().location().end_pos, &ok);
|
CheckOctalLiteral(beg_pos, scanner().location().end_pos, &ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok && is_extended_mode()) {
|
if (ok && is_extended_mode()) {
|
||||||
CheckConflictingVarDeclarations(top_scope_, &ok);
|
CheckConflictingVarDeclarations(scope_, &ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
|
if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
|
||||||
@ -766,7 +770,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
|||||||
if (ok) {
|
if (ok) {
|
||||||
result = factory()->NewFunctionLiteral(
|
result = factory()->NewFunctionLiteral(
|
||||||
no_name,
|
no_name,
|
||||||
top_scope_,
|
scope_,
|
||||||
body,
|
body,
|
||||||
function_state.materialized_literal_count(),
|
function_state.materialized_literal_count(),
|
||||||
function_state.expected_property_count(),
|
function_state.expected_property_count(),
|
||||||
@ -832,7 +836,7 @@ FunctionLiteral* Parser::ParseLazy() {
|
|||||||
FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
|
FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
|
||||||
Handle<SharedFunctionInfo> shared_info = info()->shared_info();
|
Handle<SharedFunctionInfo> shared_info = info()->shared_info();
|
||||||
scanner_.Initialize(source);
|
scanner_.Initialize(source);
|
||||||
ASSERT(top_scope_ == NULL);
|
ASSERT(scope_ == NULL);
|
||||||
ASSERT(target_stack_ == NULL);
|
ASSERT(target_stack_ == NULL);
|
||||||
|
|
||||||
Handle<String> name(String::cast(shared_info->name()));
|
Handle<String> name(String::cast(shared_info->name()));
|
||||||
@ -846,14 +850,14 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// Parse the function literal.
|
// Parse the function literal.
|
||||||
Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
|
Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
|
||||||
info()->SetGlobalScope(scope);
|
info()->SetGlobalScope(scope);
|
||||||
if (!info()->closure().is_null()) {
|
if (!info()->closure().is_null()) {
|
||||||
scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
|
scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
|
||||||
zone());
|
zone());
|
||||||
}
|
}
|
||||||
original_scope_ = scope;
|
original_scope_ = scope;
|
||||||
FunctionState function_state(this, scope);
|
FunctionState function_state(&function_state_, &scope_, scope, zone());
|
||||||
ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
|
ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
|
||||||
ASSERT(scope->language_mode() != EXTENDED_MODE ||
|
ASSERT(scope->language_mode() != EXTENDED_MODE ||
|
||||||
info()->is_extended_mode());
|
info()->is_extended_mode());
|
||||||
@ -934,7 +938,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
|
|||||||
Handle<String> directive = Handle<String>::cast(literal->value());
|
Handle<String> directive = Handle<String>::cast(literal->value());
|
||||||
|
|
||||||
// Check "use strict" directive (ES5 14.1).
|
// Check "use strict" directive (ES5 14.1).
|
||||||
if (top_scope_->is_classic_mode() &&
|
if (scope_->is_classic_mode() &&
|
||||||
directive->Equals(isolate()->heap()->use_strict_string()) &&
|
directive->Equals(isolate()->heap()->use_strict_string()) &&
|
||||||
token_loc.end_pos - token_loc.beg_pos ==
|
token_loc.end_pos - token_loc.beg_pos ==
|
||||||
isolate()->heap()->use_strict_string()->length() + 2) {
|
isolate()->heap()->use_strict_string()->length() + 2) {
|
||||||
@ -943,16 +947,16 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
|
|||||||
// add this scope in DoParseProgram(), but that requires adaptations
|
// add this scope in DoParseProgram(), but that requires adaptations
|
||||||
// all over the code base, so we go with a quick-fix for now.
|
// all over the code base, so we go with a quick-fix for now.
|
||||||
// In the same manner, we have to patch the parsing mode.
|
// In the same manner, we have to patch the parsing mode.
|
||||||
if (is_eval && !top_scope_->is_eval_scope()) {
|
if (is_eval && !scope_->is_eval_scope()) {
|
||||||
ASSERT(top_scope_->is_global_scope());
|
ASSERT(scope_->is_global_scope());
|
||||||
Scope* scope = NewScope(top_scope_, EVAL_SCOPE);
|
Scope* scope = NewScope(scope_, EVAL_SCOPE);
|
||||||
scope->set_start_position(top_scope_->start_position());
|
scope->set_start_position(scope_->start_position());
|
||||||
scope->set_end_position(top_scope_->end_position());
|
scope->set_end_position(scope_->end_position());
|
||||||
top_scope_ = scope;
|
scope_ = scope;
|
||||||
mode_ = PARSE_EAGERLY;
|
mode_ = PARSE_EAGERLY;
|
||||||
}
|
}
|
||||||
// TODO(ES6): Fix entering extended mode, once it is specified.
|
// TODO(ES6): Fix entering extended mode, once it is specified.
|
||||||
top_scope_->SetLanguageMode(allow_harmony_scoping()
|
scope_->SetLanguageMode(allow_harmony_scoping()
|
||||||
? EXTENDED_MODE : STRICT_MODE);
|
? EXTENDED_MODE : STRICT_MODE);
|
||||||
// "use strict" is the only directive for now.
|
// "use strict" is the only directive for now.
|
||||||
directive_prologue = false;
|
directive_prologue = false;
|
||||||
@ -1033,7 +1037,7 @@ Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
|
|||||||
Module* module = ParseModule(CHECK_OK);
|
Module* module = ParseModule(CHECK_OK);
|
||||||
VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
|
VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
|
||||||
Declaration* declaration =
|
Declaration* declaration =
|
||||||
factory()->NewModuleDeclaration(proxy, module, top_scope_, pos);
|
factory()->NewModuleDeclaration(proxy, module, scope_, pos);
|
||||||
Declare(declaration, true, CHECK_OK);
|
Declare(declaration, true, CHECK_OK);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -1091,14 +1095,14 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (FLAG_print_interface_details) PrintF("# Literal ");
|
if (FLAG_print_interface_details) PrintF("# Literal ");
|
||||||
#endif
|
#endif
|
||||||
Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
|
Scope* scope = NewScope(scope_, MODULE_SCOPE);
|
||||||
|
|
||||||
Expect(Token::LBRACE, CHECK_OK);
|
Expect(Token::LBRACE, CHECK_OK);
|
||||||
scope->set_start_position(scanner().location().beg_pos);
|
scope->set_start_position(scanner().location().beg_pos);
|
||||||
scope->SetLanguageMode(EXTENDED_MODE);
|
scope->SetLanguageMode(EXTENDED_MODE);
|
||||||
|
|
||||||
{
|
{
|
||||||
BlockState block_state(this, scope);
|
BlockState block_state(&scope_, scope);
|
||||||
TargetCollector collector(zone());
|
TargetCollector collector(zone());
|
||||||
Target target(&this->target_stack_, &collector);
|
Target target(&this->target_stack_, &collector);
|
||||||
Target target_body(&this->target_stack_, body);
|
Target target_body(&this->target_stack_, body);
|
||||||
@ -1182,7 +1186,7 @@ Module* Parser::ParseModuleVariable(bool* ok) {
|
|||||||
if (FLAG_print_interface_details)
|
if (FLAG_print_interface_details)
|
||||||
PrintF("# Module variable %s ", name->ToAsciiArray());
|
PrintF("# Module variable %s ", name->ToAsciiArray());
|
||||||
#endif
|
#endif
|
||||||
VariableProxy* proxy = top_scope_->NewUnresolved(
|
VariableProxy* proxy = scope_->NewUnresolved(
|
||||||
factory(), name, Interface::NewModule(zone()),
|
factory(), name, Interface::NewModule(zone()),
|
||||||
scanner().location().beg_pos);
|
scanner().location().beg_pos);
|
||||||
|
|
||||||
@ -1206,7 +1210,7 @@ Module* Parser::ParseModuleUrl(bool* ok) {
|
|||||||
|
|
||||||
// Create an empty literal as long as the feature isn't finished.
|
// Create an empty literal as long as the feature isn't finished.
|
||||||
USE(symbol);
|
USE(symbol);
|
||||||
Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
|
Scope* scope = NewScope(scope_, MODULE_SCOPE);
|
||||||
Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
|
Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
|
||||||
body->set_scope(scope);
|
body->set_scope(scope);
|
||||||
Interface* interface = scope->interface();
|
Interface* interface = scope->interface();
|
||||||
@ -1278,7 +1282,7 @@ Block* Parser::ParseImportDeclaration(bool* ok) {
|
|||||||
}
|
}
|
||||||
VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
|
VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
|
||||||
Declaration* declaration =
|
Declaration* declaration =
|
||||||
factory()->NewImportDeclaration(proxy, module, top_scope_, pos);
|
factory()->NewImportDeclaration(proxy, module, scope_, pos);
|
||||||
Declare(declaration, true, CHECK_OK);
|
Declare(declaration, true, CHECK_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1338,7 +1342,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract declared names into export declarations and interface.
|
// Extract declared names into export declarations and interface.
|
||||||
Interface* interface = top_scope_->interface();
|
Interface* interface = scope_->interface();
|
||||||
for (int i = 0; i < names.length(); ++i) {
|
for (int i = 0; i < names.length(); ++i) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (FLAG_print_interface_details)
|
if (FLAG_print_interface_details)
|
||||||
@ -1353,8 +1357,8 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
|||||||
// TODO(rossberg): Rethink whether we actually need to store export
|
// TODO(rossberg): Rethink whether we actually need to store export
|
||||||
// declarations (for compilation?).
|
// declarations (for compilation?).
|
||||||
// ExportDeclaration* declaration =
|
// ExportDeclaration* declaration =
|
||||||
// factory()->NewExportDeclaration(proxy, top_scope_, position);
|
// factory()->NewExportDeclaration(proxy, scope_, position);
|
||||||
// top_scope_->AddDeclaration(declaration);
|
// scope_->AddDeclaration(declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(result != NULL);
|
ASSERT(result != NULL);
|
||||||
@ -1480,7 +1484,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
// In Harmony mode, this case also handles the extension:
|
// In Harmony mode, this case also handles the extension:
|
||||||
// Statement:
|
// Statement:
|
||||||
// GeneratorDeclaration
|
// GeneratorDeclaration
|
||||||
if (!top_scope_->is_classic_mode()) {
|
if (!scope_->is_classic_mode()) {
|
||||||
ReportMessageAt(scanner().peek_location(), "strict_function");
|
ReportMessageAt(scanner().peek_location(), "strict_function");
|
||||||
*ok = false;
|
*ok = false;
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1700,7 +1704,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
|||||||
// other functions are set up when entering the surrounding scope.
|
// other functions are set up when entering the surrounding scope.
|
||||||
VariableProxy* proxy = NewUnresolved(name, VAR, Interface::NewValue());
|
VariableProxy* proxy = NewUnresolved(name, VAR, Interface::NewValue());
|
||||||
Declaration* declaration =
|
Declaration* declaration =
|
||||||
factory()->NewVariableDeclaration(proxy, VAR, top_scope_, pos);
|
factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
|
||||||
Declare(declaration, true, CHECK_OK);
|
Declare(declaration, true, CHECK_OK);
|
||||||
NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
|
NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
|
||||||
name, extension_, RelocInfo::kNoPosition);
|
name, extension_, RelocInfo::kNoPosition);
|
||||||
@ -1736,10 +1740,10 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
|
|||||||
// In extended mode, a function behaves as a lexical binding, except in the
|
// In extended mode, a function behaves as a lexical binding, except in the
|
||||||
// global scope.
|
// global scope.
|
||||||
VariableMode mode =
|
VariableMode mode =
|
||||||
is_extended_mode() && !top_scope_->is_global_scope() ? LET : VAR;
|
is_extended_mode() && !scope_->is_global_scope() ? LET : VAR;
|
||||||
VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
|
VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
|
||||||
Declaration* declaration =
|
Declaration* declaration =
|
||||||
factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_, pos);
|
factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
|
||||||
Declare(declaration, true, CHECK_OK);
|
Declare(declaration, true, CHECK_OK);
|
||||||
if (names) names->Add(name, zone());
|
if (names) names->Add(name, zone());
|
||||||
return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
|
return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
|
||||||
@ -1747,7 +1751,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
|
|||||||
|
|
||||||
|
|
||||||
Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
|
Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
|
||||||
if (top_scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
|
if (scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
|
||||||
|
|
||||||
// Block ::
|
// Block ::
|
||||||
// '{' Statement* '}'
|
// '{' Statement* '}'
|
||||||
@ -1780,12 +1784,12 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
|
|||||||
// Construct block expecting 16 statements.
|
// Construct block expecting 16 statements.
|
||||||
Block* body =
|
Block* body =
|
||||||
factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
|
factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
|
||||||
Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
|
Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
|
||||||
|
|
||||||
// Parse the statements and collect escaping labels.
|
// Parse the statements and collect escaping labels.
|
||||||
Expect(Token::LBRACE, CHECK_OK);
|
Expect(Token::LBRACE, CHECK_OK);
|
||||||
block_scope->set_start_position(scanner().location().beg_pos);
|
block_scope->set_start_position(scanner().location().beg_pos);
|
||||||
{ BlockState block_state(this, block_scope);
|
{ BlockState block_state(&scope_, block_scope);
|
||||||
TargetCollector collector(zone());
|
TargetCollector collector(zone());
|
||||||
Target target(&this->target_stack_, &collector);
|
Target target(&this->target_stack_, &collector);
|
||||||
Target target_body(&this->target_stack_, body);
|
Target target_body(&this->target_stack_, body);
|
||||||
@ -1867,7 +1871,7 @@ Block* Parser::ParseVariableDeclarations(
|
|||||||
// existing pages. Therefore we keep allowing const with the old
|
// existing pages. Therefore we keep allowing const with the old
|
||||||
// non-harmony semantics in classic mode.
|
// non-harmony semantics in classic mode.
|
||||||
Consume(Token::CONST);
|
Consume(Token::CONST);
|
||||||
switch (top_scope_->language_mode()) {
|
switch (scope_->language_mode()) {
|
||||||
case CLASSIC_MODE:
|
case CLASSIC_MODE:
|
||||||
mode = CONST;
|
mode = CONST;
|
||||||
init_op = Token::INIT_CONST;
|
init_op = Token::INIT_CONST;
|
||||||
@ -1960,7 +1964,7 @@ Block* Parser::ParseVariableDeclarations(
|
|||||||
is_const ? Interface::NewConst() : Interface::NewValue();
|
is_const ? Interface::NewConst() : Interface::NewValue();
|
||||||
VariableProxy* proxy = NewUnresolved(name, mode, interface);
|
VariableProxy* proxy = NewUnresolved(name, mode, interface);
|
||||||
Declaration* declaration =
|
Declaration* declaration =
|
||||||
factory()->NewVariableDeclaration(proxy, mode, top_scope_, pos);
|
factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
|
||||||
Declare(declaration, mode != VAR, CHECK_OK);
|
Declare(declaration, mode != VAR, CHECK_OK);
|
||||||
nvars++;
|
nvars++;
|
||||||
if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
|
if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
|
||||||
@ -1979,7 +1983,7 @@ Block* Parser::ParseVariableDeclarations(
|
|||||||
//
|
//
|
||||||
// var v; v = x;
|
// var v; v = x;
|
||||||
//
|
//
|
||||||
// In particular, we need to re-lookup 'v' (in top_scope_, not
|
// In particular, we need to re-lookup 'v' (in scope_, not
|
||||||
// declaration_scope) as it may be a different 'v' than the 'v' in the
|
// declaration_scope) as it may be a different 'v' than the 'v' in the
|
||||||
// declaration (e.g., if we are inside a 'with' statement or 'catch'
|
// declaration (e.g., if we are inside a 'with' statement or 'catch'
|
||||||
// block).
|
// block).
|
||||||
@ -1997,7 +2001,7 @@ Block* Parser::ParseVariableDeclarations(
|
|||||||
// one - there is no re-lookup (see the last parameter of the
|
// one - there is no re-lookup (see the last parameter of the
|
||||||
// Declare() call above).
|
// Declare() call above).
|
||||||
|
|
||||||
Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
|
Scope* initialization_scope = is_const ? declaration_scope : scope_;
|
||||||
Expression* value = NULL;
|
Expression* value = NULL;
|
||||||
int pos = -1;
|
int pos = -1;
|
||||||
// Harmony consts have non-optional initializers.
|
// Harmony consts have non-optional initializers.
|
||||||
@ -2188,7 +2192,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
|
|||||||
// Remove the "ghost" variable that turned out to be a label
|
// Remove the "ghost" variable that turned out to be a label
|
||||||
// from the top scope. This way, we don't try to resolve it
|
// from the top scope. This way, we don't try to resolve it
|
||||||
// during the scope processing.
|
// during the scope processing.
|
||||||
top_scope_->RemoveUnresolved(var);
|
scope_->RemoveUnresolved(var);
|
||||||
Expect(Token::COLON, CHECK_OK);
|
Expect(Token::COLON, CHECK_OK);
|
||||||
return ParseStatement(labels, ok);
|
return ParseStatement(labels, ok);
|
||||||
}
|
}
|
||||||
@ -2338,7 +2342,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
|||||||
ExpectSemicolon(CHECK_OK);
|
ExpectSemicolon(CHECK_OK);
|
||||||
if (is_generator()) {
|
if (is_generator()) {
|
||||||
Expression* generator = factory()->NewVariableProxy(
|
Expression* generator = factory()->NewVariableProxy(
|
||||||
current_function_state_->generator_object_variable());
|
function_state_->generator_object_variable());
|
||||||
Expression* yield = factory()->NewYield(
|
Expression* yield = factory()->NewYield(
|
||||||
generator, return_value, Yield::FINAL, pos);
|
generator, return_value, Yield::FINAL, pos);
|
||||||
result = factory()->NewExpressionStatement(yield, pos);
|
result = factory()->NewExpressionStatement(yield, pos);
|
||||||
@ -2351,7 +2355,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
|||||||
// function. See ECMA-262, section 12.9, page 67.
|
// function. See ECMA-262, section 12.9, page 67.
|
||||||
//
|
//
|
||||||
// To be consistent with KJS we report the syntax error at runtime.
|
// To be consistent with KJS we report the syntax error at runtime.
|
||||||
Scope* declaration_scope = top_scope_->DeclarationScope();
|
Scope* declaration_scope = scope_->DeclarationScope();
|
||||||
if (declaration_scope->is_global_scope() ||
|
if (declaration_scope->is_global_scope() ||
|
||||||
declaration_scope->is_eval_scope()) {
|
declaration_scope->is_eval_scope()) {
|
||||||
Handle<String> message = isolate()->factory()->illegal_return_string();
|
Handle<String> message = isolate()->factory()->illegal_return_string();
|
||||||
@ -2370,7 +2374,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
Expect(Token::WITH, CHECK_OK);
|
Expect(Token::WITH, CHECK_OK);
|
||||||
int pos = position();
|
int pos = position();
|
||||||
|
|
||||||
if (!top_scope_->is_classic_mode()) {
|
if (!scope_->is_classic_mode()) {
|
||||||
ReportMessage("strict_mode_with", Vector<const char*>::empty());
|
ReportMessage("strict_mode_with", Vector<const char*>::empty());
|
||||||
*ok = false;
|
*ok = false;
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2380,10 +2384,10 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
Expression* expr = ParseExpression(true, CHECK_OK);
|
Expression* expr = ParseExpression(true, CHECK_OK);
|
||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
|
|
||||||
top_scope_->DeclarationScope()->RecordWithStatement();
|
scope_->DeclarationScope()->RecordWithStatement();
|
||||||
Scope* with_scope = NewScope(top_scope_, WITH_SCOPE);
|
Scope* with_scope = NewScope(scope_, WITH_SCOPE);
|
||||||
Statement* stmt;
|
Statement* stmt;
|
||||||
{ BlockState block_state(this, with_scope);
|
{ BlockState block_state(&scope_, with_scope);
|
||||||
with_scope->set_start_position(scanner().peek_location().beg_pos);
|
with_scope->set_start_position(scanner().peek_location().beg_pos);
|
||||||
stmt = ParseStatement(labels, CHECK_OK);
|
stmt = ParseStatement(labels, CHECK_OK);
|
||||||
with_scope->set_end_position(scanner().location().end_pos);
|
with_scope->set_end_position(scanner().location().end_pos);
|
||||||
@ -2515,7 +2519,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
|||||||
Consume(Token::CATCH);
|
Consume(Token::CATCH);
|
||||||
|
|
||||||
Expect(Token::LPAREN, CHECK_OK);
|
Expect(Token::LPAREN, CHECK_OK);
|
||||||
catch_scope = NewScope(top_scope_, CATCH_SCOPE);
|
catch_scope = NewScope(scope_, CATCH_SCOPE);
|
||||||
catch_scope->set_start_position(scanner().location().beg_pos);
|
catch_scope->set_start_position(scanner().location().beg_pos);
|
||||||
name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
||||||
|
|
||||||
@ -2526,7 +2530,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
|||||||
catch_variable =
|
catch_variable =
|
||||||
catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
|
catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
|
||||||
|
|
||||||
BlockState block_state(this, catch_scope);
|
BlockState block_state(&scope_, catch_scope);
|
||||||
catch_block = ParseBlock(NULL, CHECK_OK);
|
catch_block = ParseBlock(NULL, CHECK_OK);
|
||||||
|
|
||||||
catch_scope->set_end_position(scanner().location().end_pos);
|
catch_scope->set_end_position(scanner().location().end_pos);
|
||||||
@ -2548,7 +2552,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
|||||||
if (catch_block != NULL && finally_block != NULL) {
|
if (catch_block != NULL && finally_block != NULL) {
|
||||||
// If we have both, create an inner try/catch.
|
// If we have both, create an inner try/catch.
|
||||||
ASSERT(catch_scope != NULL && catch_variable != NULL);
|
ASSERT(catch_scope != NULL && catch_variable != NULL);
|
||||||
int index = current_function_state_->NextHandlerIndex();
|
int index = function_state_->NextHandlerIndex();
|
||||||
TryCatchStatement* statement = factory()->NewTryCatchStatement(
|
TryCatchStatement* statement = factory()->NewTryCatchStatement(
|
||||||
index, try_block, catch_scope, catch_variable, catch_block,
|
index, try_block, catch_scope, catch_variable, catch_block,
|
||||||
RelocInfo::kNoPosition);
|
RelocInfo::kNoPosition);
|
||||||
@ -2562,12 +2566,12 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
|||||||
if (catch_block != NULL) {
|
if (catch_block != NULL) {
|
||||||
ASSERT(finally_block == NULL);
|
ASSERT(finally_block == NULL);
|
||||||
ASSERT(catch_scope != NULL && catch_variable != NULL);
|
ASSERT(catch_scope != NULL && catch_variable != NULL);
|
||||||
int index = current_function_state_->NextHandlerIndex();
|
int index = function_state_->NextHandlerIndex();
|
||||||
result = factory()->NewTryCatchStatement(
|
result = factory()->NewTryCatchStatement(
|
||||||
index, try_block, catch_scope, catch_variable, catch_block, pos);
|
index, try_block, catch_scope, catch_variable, catch_block, pos);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(finally_block != NULL);
|
ASSERT(finally_block != NULL);
|
||||||
int index = current_function_state_->NextHandlerIndex();
|
int index = function_state_->NextHandlerIndex();
|
||||||
result = factory()->NewTryFinallyStatement(
|
result = factory()->NewTryFinallyStatement(
|
||||||
index, try_block, finally_block, pos);
|
index, try_block, finally_block, pos);
|
||||||
// Combine the jump targets of the try block and the possible catch block.
|
// Combine the jump targets of the try block and the possible catch block.
|
||||||
@ -2647,9 +2651,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
|
|||||||
|
|
||||||
if (for_of != NULL) {
|
if (for_of != NULL) {
|
||||||
Factory* heap_factory = isolate()->factory();
|
Factory* heap_factory = isolate()->factory();
|
||||||
Variable* iterator = top_scope_->DeclarationScope()->NewTemporary(
|
Variable* iterator = scope_->DeclarationScope()->NewTemporary(
|
||||||
heap_factory->dot_iterator_string());
|
heap_factory->dot_iterator_string());
|
||||||
Variable* result = top_scope_->DeclarationScope()->NewTemporary(
|
Variable* result = scope_->DeclarationScope()->NewTemporary(
|
||||||
heap_factory->dot_result_string());
|
heap_factory->dot_result_string());
|
||||||
|
|
||||||
Expression* assign_iterator;
|
Expression* assign_iterator;
|
||||||
@ -2716,9 +2720,9 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
Statement* init = NULL;
|
Statement* init = NULL;
|
||||||
|
|
||||||
// Create an in-between scope for let-bound iteration variables.
|
// Create an in-between scope for let-bound iteration variables.
|
||||||
Scope* saved_scope = top_scope_;
|
Scope* saved_scope = scope_;
|
||||||
Scope* for_scope = NewScope(top_scope_, BLOCK_SCOPE);
|
Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
|
||||||
top_scope_ = for_scope;
|
scope_ = for_scope;
|
||||||
|
|
||||||
Expect(Token::FOR, CHECK_OK);
|
Expect(Token::FOR, CHECK_OK);
|
||||||
Expect(Token::LPAREN, CHECK_OK);
|
Expect(Token::LPAREN, CHECK_OK);
|
||||||
@ -2745,14 +2749,14 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
|
|
||||||
VariableProxy* each =
|
VariableProxy* each =
|
||||||
top_scope_->NewUnresolved(factory(), name, interface);
|
scope_->NewUnresolved(factory(), name, interface);
|
||||||
Statement* body = ParseStatement(NULL, CHECK_OK);
|
Statement* body = ParseStatement(NULL, CHECK_OK);
|
||||||
InitializeForEachStatement(loop, each, enumerable, body);
|
InitializeForEachStatement(loop, each, enumerable, body);
|
||||||
Block* result =
|
Block* result =
|
||||||
factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
|
factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
|
||||||
result->AddStatement(variable_statement, zone());
|
result->AddStatement(variable_statement, zone());
|
||||||
result->AddStatement(loop, zone());
|
result->AddStatement(loop, zone());
|
||||||
top_scope_ = saved_scope;
|
scope_ = saved_scope;
|
||||||
for_scope->set_end_position(scanner().location().end_pos);
|
for_scope->set_end_position(scanner().location().end_pos);
|
||||||
for_scope = for_scope->FinalizeBlockScope();
|
for_scope = for_scope->FinalizeBlockScope();
|
||||||
ASSERT(for_scope == NULL);
|
ASSERT(for_scope == NULL);
|
||||||
@ -2791,20 +2795,20 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
Handle<String> tempstr =
|
Handle<String> tempstr =
|
||||||
heap_factory->NewConsString(heap_factory->dot_for_string(), name);
|
heap_factory->NewConsString(heap_factory->dot_for_string(), name);
|
||||||
Handle<String> tempname = heap_factory->InternalizeString(tempstr);
|
Handle<String> tempname = heap_factory->InternalizeString(tempstr);
|
||||||
Variable* temp = top_scope_->DeclarationScope()->NewTemporary(tempname);
|
Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname);
|
||||||
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
|
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
|
||||||
ForEachStatement* loop =
|
ForEachStatement* loop =
|
||||||
factory()->NewForEachStatement(mode, labels, pos);
|
factory()->NewForEachStatement(mode, labels, pos);
|
||||||
Target target(&this->target_stack_, loop);
|
Target target(&this->target_stack_, loop);
|
||||||
|
|
||||||
// The expression does not see the loop variable.
|
// The expression does not see the loop variable.
|
||||||
top_scope_ = saved_scope;
|
scope_ = saved_scope;
|
||||||
Expression* enumerable = ParseExpression(true, CHECK_OK);
|
Expression* enumerable = ParseExpression(true, CHECK_OK);
|
||||||
top_scope_ = for_scope;
|
scope_ = for_scope;
|
||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
|
|
||||||
VariableProxy* each =
|
VariableProxy* each =
|
||||||
top_scope_->NewUnresolved(factory(), name, Interface::NewValue());
|
scope_->NewUnresolved(factory(), name, Interface::NewValue());
|
||||||
Statement* body = ParseStatement(NULL, CHECK_OK);
|
Statement* body = ParseStatement(NULL, CHECK_OK);
|
||||||
Block* body_block =
|
Block* body_block =
|
||||||
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
|
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
|
||||||
@ -2816,7 +2820,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
body_block->AddStatement(assignment_statement, zone());
|
body_block->AddStatement(assignment_statement, zone());
|
||||||
body_block->AddStatement(body, zone());
|
body_block->AddStatement(body, zone());
|
||||||
InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
|
InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
|
||||||
top_scope_ = saved_scope;
|
scope_ = saved_scope;
|
||||||
for_scope->set_end_position(scanner().location().end_pos);
|
for_scope->set_end_position(scanner().location().end_pos);
|
||||||
for_scope = for_scope->FinalizeBlockScope();
|
for_scope = for_scope->FinalizeBlockScope();
|
||||||
body_block->set_scope(for_scope);
|
body_block->set_scope(for_scope);
|
||||||
@ -2850,7 +2854,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
|
|
||||||
Statement* body = ParseStatement(NULL, CHECK_OK);
|
Statement* body = ParseStatement(NULL, CHECK_OK);
|
||||||
InitializeForEachStatement(loop, expression, enumerable, body);
|
InitializeForEachStatement(loop, expression, enumerable, body);
|
||||||
top_scope_ = saved_scope;
|
scope_ = saved_scope;
|
||||||
for_scope->set_end_position(scanner().location().end_pos);
|
for_scope->set_end_position(scanner().location().end_pos);
|
||||||
for_scope = for_scope->FinalizeBlockScope();
|
for_scope = for_scope->FinalizeBlockScope();
|
||||||
ASSERT(for_scope == NULL);
|
ASSERT(for_scope == NULL);
|
||||||
@ -2885,7 +2889,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
|
|
||||||
Statement* body = ParseStatement(NULL, CHECK_OK);
|
Statement* body = ParseStatement(NULL, CHECK_OK);
|
||||||
top_scope_ = saved_scope;
|
scope_ = saved_scope;
|
||||||
for_scope->set_end_position(scanner().location().end_pos);
|
for_scope->set_end_position(scanner().location().end_pos);
|
||||||
for_scope = for_scope->FinalizeBlockScope();
|
for_scope = for_scope->FinalizeBlockScope();
|
||||||
if (for_scope != NULL) {
|
if (for_scope != NULL) {
|
||||||
@ -2961,7 +2965,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
|||||||
expression = NewThrowReferenceError(message);
|
expression = NewThrowReferenceError(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!top_scope_->is_classic_mode()) {
|
if (!scope_->is_classic_mode()) {
|
||||||
// Assignment to eval or arguments is disallowed in strict mode.
|
// Assignment to eval or arguments is disallowed in strict mode.
|
||||||
CheckStrictModeLValue(expression, CHECK_OK);
|
CheckStrictModeLValue(expression, CHECK_OK);
|
||||||
}
|
}
|
||||||
@ -2981,7 +2985,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
|||||||
property != NULL &&
|
property != NULL &&
|
||||||
property->obj()->AsVariableProxy() != NULL &&
|
property->obj()->AsVariableProxy() != NULL &&
|
||||||
property->obj()->AsVariableProxy()->is_this()) {
|
property->obj()->AsVariableProxy()->is_this()) {
|
||||||
current_function_state_->AddProperty();
|
function_state_->AddProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we assign a function literal to a property we pretenure the
|
// If we assign a function literal to a property we pretenure the
|
||||||
@ -3017,11 +3021,11 @@ Expression* Parser::ParseYieldExpression(bool* ok) {
|
|||||||
Yield::Kind kind =
|
Yield::Kind kind =
|
||||||
Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
|
Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
|
||||||
Expression* generator_object = factory()->NewVariableProxy(
|
Expression* generator_object = factory()->NewVariableProxy(
|
||||||
current_function_state_->generator_object_variable());
|
function_state_->generator_object_variable());
|
||||||
Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
|
Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
|
||||||
Yield* yield = factory()->NewYield(generator_object, expression, kind, pos);
|
Yield* yield = factory()->NewYield(generator_object, expression, kind, pos);
|
||||||
if (kind == Yield::DELEGATING) {
|
if (kind == Yield::DELEGATING) {
|
||||||
yield->set_index(current_function_state_->NextHandlerIndex());
|
yield->set_index(function_state_->NextHandlerIndex());
|
||||||
}
|
}
|
||||||
return yield;
|
return yield;
|
||||||
}
|
}
|
||||||
@ -3185,7 +3189,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "delete identifier" is a syntax error in strict mode.
|
// "delete identifier" is a syntax error in strict mode.
|
||||||
if (op == Token::DELETE && !top_scope_->is_classic_mode()) {
|
if (op == Token::DELETE && !scope_->is_classic_mode()) {
|
||||||
VariableProxy* operand = expression->AsVariableProxy();
|
VariableProxy* operand = expression->AsVariableProxy();
|
||||||
if (operand != NULL && !operand->is_this()) {
|
if (operand != NULL && !operand->is_this()) {
|
||||||
ReportMessage("strict_delete", Vector<const char*>::empty());
|
ReportMessage("strict_delete", Vector<const char*>::empty());
|
||||||
@ -3233,7 +3237,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
|
|||||||
expression = NewThrowReferenceError(message);
|
expression = NewThrowReferenceError(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!top_scope_->is_classic_mode()) {
|
if (!scope_->is_classic_mode()) {
|
||||||
// Prefix expression operand in strict mode may not be eval or arguments.
|
// Prefix expression operand in strict mode may not be eval or arguments.
|
||||||
CheckStrictModeLValue(expression, CHECK_OK);
|
CheckStrictModeLValue(expression, CHECK_OK);
|
||||||
}
|
}
|
||||||
@ -3267,7 +3271,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
|
|||||||
expression = NewThrowReferenceError(message);
|
expression = NewThrowReferenceError(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!top_scope_->is_classic_mode()) {
|
if (!scope_->is_classic_mode()) {
|
||||||
// Postfix expression operand in strict mode may not be eval or arguments.
|
// Postfix expression operand in strict mode may not be eval or arguments.
|
||||||
CheckStrictModeLValue(expression, CHECK_OK);
|
CheckStrictModeLValue(expression, CHECK_OK);
|
||||||
}
|
}
|
||||||
@ -3338,7 +3342,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
|
|||||||
VariableProxy* callee = result->AsVariableProxy();
|
VariableProxy* callee = result->AsVariableProxy();
|
||||||
if (callee != NULL &&
|
if (callee != NULL &&
|
||||||
callee->IsVariable(isolate()->factory()->eval_string())) {
|
callee->IsVariable(isolate()->factory()->eval_string())) {
|
||||||
top_scope_->DeclarationScope()->RecordEvalCall();
|
scope_->DeclarationScope()->RecordEvalCall();
|
||||||
}
|
}
|
||||||
result = factory()->NewCall(result, args, pos);
|
result = factory()->NewCall(result, args, pos);
|
||||||
if (fni_ != NULL) fni_->RemoveLastFunction();
|
if (fni_ != NULL) fni_->RemoveLastFunction();
|
||||||
@ -3522,7 +3526,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
|
|||||||
switch (peek()) {
|
switch (peek()) {
|
||||||
case Token::THIS: {
|
case Token::THIS: {
|
||||||
Consume(Token::THIS);
|
Consume(Token::THIS);
|
||||||
result = factory()->NewVariableProxy(top_scope_->receiver());
|
result = factory()->NewVariableProxy(scope_->receiver());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3553,7 +3557,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
|
|||||||
PrintF("# Variable %s ", name->ToAsciiArray());
|
PrintF("# Variable %s ", name->ToAsciiArray());
|
||||||
#endif
|
#endif
|
||||||
Interface* interface = Interface::NewUnknown(zone());
|
Interface* interface = Interface::NewUnknown(zone());
|
||||||
result = top_scope_->NewUnresolved(factory(), name, interface, pos);
|
result = scope_->NewUnresolved(factory(), name, interface, pos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3643,7 +3647,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
|
|||||||
Expect(Token::RBRACK, CHECK_OK);
|
Expect(Token::RBRACK, CHECK_OK);
|
||||||
|
|
||||||
// Update the scope information before the pre-parsing bailout.
|
// Update the scope information before the pre-parsing bailout.
|
||||||
int literal_index = current_function_state_->NextMaterializedLiteralIndex();
|
int literal_index = function_state_->NextMaterializedLiteralIndex();
|
||||||
|
|
||||||
return factory()->NewArrayLiteral(values, literal_index, pos);
|
return factory()->NewArrayLiteral(values, literal_index, pos);
|
||||||
}
|
}
|
||||||
@ -3705,7 +3709,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|||||||
int number_of_boilerplate_properties = 0;
|
int number_of_boilerplate_properties = 0;
|
||||||
bool has_function = false;
|
bool has_function = false;
|
||||||
|
|
||||||
ObjectLiteralChecker checker(this, top_scope_->language_mode());
|
ObjectLiteralChecker checker(this, scope_->language_mode());
|
||||||
|
|
||||||
Expect(Token::LBRACE, CHECK_OK);
|
Expect(Token::LBRACE, CHECK_OK);
|
||||||
|
|
||||||
@ -3826,7 +3830,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|||||||
// Mark top-level object literals that contain function literals and
|
// Mark top-level object literals that contain function literals and
|
||||||
// pretenure the literal so it can be added as a constant function
|
// pretenure the literal so it can be added as a constant function
|
||||||
// property.
|
// property.
|
||||||
if (top_scope_->DeclarationScope()->is_global_scope() &&
|
if (scope_->DeclarationScope()->is_global_scope() &&
|
||||||
value->AsFunctionLiteral() != NULL) {
|
value->AsFunctionLiteral() != NULL) {
|
||||||
has_function = true;
|
has_function = true;
|
||||||
value->AsFunctionLiteral()->set_pretenure();
|
value->AsFunctionLiteral()->set_pretenure();
|
||||||
@ -3849,7 +3853,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|||||||
Expect(Token::RBRACE, CHECK_OK);
|
Expect(Token::RBRACE, CHECK_OK);
|
||||||
|
|
||||||
// Computation of literal_index must happen before pre parse bailout.
|
// Computation of literal_index must happen before pre parse bailout.
|
||||||
int literal_index = current_function_state_->NextMaterializedLiteralIndex();
|
int literal_index = function_state_->NextMaterializedLiteralIndex();
|
||||||
|
|
||||||
return factory()->NewObjectLiteral(properties,
|
return factory()->NewObjectLiteral(properties,
|
||||||
literal_index,
|
literal_index,
|
||||||
@ -4027,14 +4031,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
// one relative to the deserialized scope chain. Otherwise we must be
|
// one relative to the deserialized scope chain. Otherwise we must be
|
||||||
// compiling a function in an inner declaration scope in the eval, e.g. a
|
// compiling a function in an inner declaration scope in the eval, e.g. a
|
||||||
// nested function, and hoisting works normally relative to that.
|
// nested function, and hoisting works normally relative to that.
|
||||||
Scope* declaration_scope = top_scope_->DeclarationScope();
|
Scope* declaration_scope = scope_->DeclarationScope();
|
||||||
Scope* original_declaration_scope = original_scope_->DeclarationScope();
|
Scope* original_declaration_scope = original_scope_->DeclarationScope();
|
||||||
Scope* scope =
|
Scope* scope =
|
||||||
function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
|
function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
|
||||||
(original_scope_ == original_declaration_scope ||
|
(original_scope_ == original_declaration_scope ||
|
||||||
declaration_scope != original_declaration_scope)
|
declaration_scope != original_declaration_scope)
|
||||||
? NewScope(declaration_scope, FUNCTION_SCOPE)
|
? NewScope(declaration_scope, FUNCTION_SCOPE)
|
||||||
: NewScope(top_scope_, FUNCTION_SCOPE);
|
: NewScope(scope_, FUNCTION_SCOPE);
|
||||||
ZoneList<Statement*>* body = NULL;
|
ZoneList<Statement*>* body = NULL;
|
||||||
int materialized_literal_count = -1;
|
int materialized_literal_count = -1;
|
||||||
int expected_property_count = -1;
|
int expected_property_count = -1;
|
||||||
@ -4051,20 +4055,20 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
AstProperties ast_properties;
|
AstProperties ast_properties;
|
||||||
BailoutReason dont_optimize_reason = kNoReason;
|
BailoutReason dont_optimize_reason = kNoReason;
|
||||||
// Parse function body.
|
// Parse function body.
|
||||||
{ FunctionState function_state(this, scope);
|
{ FunctionState function_state(&function_state_, &scope_, scope, zone());
|
||||||
top_scope_->SetScopeName(function_name);
|
scope_->SetScopeName(function_name);
|
||||||
|
|
||||||
if (is_generator) {
|
if (is_generator) {
|
||||||
// For generators, allocating variables in contexts is currently a win
|
// For generators, allocating variables in contexts is currently a win
|
||||||
// because it minimizes the work needed to suspend and resume an
|
// because it minimizes the work needed to suspend and resume an
|
||||||
// activation.
|
// activation.
|
||||||
top_scope_->ForceContextAllocation();
|
scope_->ForceContextAllocation();
|
||||||
|
|
||||||
// Calling a generator returns a generator object. That object is stored
|
// Calling a generator returns a generator object. That object is stored
|
||||||
// in a temporary variable, a definition that is used by "yield"
|
// in a temporary variable, a definition that is used by "yield"
|
||||||
// expressions. Presence of a variable for the generator object in the
|
// expressions. Presence of a variable for the generator object in the
|
||||||
// FunctionState indicates that this function is a generator.
|
// FunctionState indicates that this function is a generator.
|
||||||
Variable* temp = top_scope_->DeclarationScope()->NewTemporary(
|
Variable* temp = scope_->DeclarationScope()->NewTemporary(
|
||||||
isolate()->factory()->dot_generator_object_string());
|
isolate()->factory()->dot_generator_object_string());
|
||||||
function_state.set_generator_object_variable(temp);
|
function_state.set_generator_object_variable(temp);
|
||||||
}
|
}
|
||||||
@ -4094,12 +4098,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
if (!reserved_loc.IsValid() && is_strict_reserved) {
|
if (!reserved_loc.IsValid() && is_strict_reserved) {
|
||||||
reserved_loc = scanner().location();
|
reserved_loc = scanner().location();
|
||||||
}
|
}
|
||||||
if (!dupe_error_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
|
if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) {
|
||||||
duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
|
duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
|
||||||
dupe_error_loc = scanner().location();
|
dupe_error_loc = scanner().location();
|
||||||
}
|
}
|
||||||
|
|
||||||
top_scope_->DeclareParameter(param_name, VAR);
|
scope_->DeclareParameter(param_name, VAR);
|
||||||
num_parameters++;
|
num_parameters++;
|
||||||
if (num_parameters > Code::kMaxArguments) {
|
if (num_parameters > Code::kMaxArguments) {
|
||||||
ReportMessageAt(scanner().location(), "too_many_parameters");
|
ReportMessageAt(scanner().location(), "too_many_parameters");
|
||||||
@ -4124,13 +4128,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
|
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
|
||||||
if (is_extended_mode()) fvar_init_op = Token::INIT_CONST_HARMONY;
|
if (is_extended_mode()) fvar_init_op = Token::INIT_CONST_HARMONY;
|
||||||
VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST;
|
VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST;
|
||||||
fvar = new(zone()) Variable(top_scope_,
|
fvar = new(zone()) Variable(scope_,
|
||||||
function_name, fvar_mode, true /* is valid LHS */,
|
function_name, fvar_mode, true /* is valid LHS */,
|
||||||
Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
|
Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
|
||||||
VariableProxy* proxy = factory()->NewVariableProxy(fvar);
|
VariableProxy* proxy = factory()->NewVariableProxy(fvar);
|
||||||
VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
|
VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
|
||||||
proxy, fvar_mode, top_scope_, RelocInfo::kNoPosition);
|
proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
|
||||||
top_scope_->DeclareFunctionVar(fvar_declaration);
|
scope_->DeclareFunctionVar(fvar_declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine whether the function will be lazily compiled.
|
// Determine whether the function will be lazily compiled.
|
||||||
@ -4145,7 +4149,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
// These are all things we can know at this point, without looking at the
|
// These are all things we can know at this point, without looking at the
|
||||||
// function itself.
|
// function itself.
|
||||||
bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
|
bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
|
||||||
top_scope_->AllowsLazyCompilation() &&
|
scope_->AllowsLazyCompilation() &&
|
||||||
!parenthesized_function_);
|
!parenthesized_function_);
|
||||||
parenthesized_function_ = false; // The bit was set for this function only.
|
parenthesized_function_ = false; // The bit was set for this function only.
|
||||||
|
|
||||||
@ -4171,7 +4175,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
scope->end_position() - function_block_pos);
|
scope->end_position() - function_block_pos);
|
||||||
materialized_literal_count = entry.literal_count();
|
materialized_literal_count = entry.literal_count();
|
||||||
expected_property_count = entry.property_count();
|
expected_property_count = entry.property_count();
|
||||||
top_scope_->SetLanguageMode(entry.language_mode());
|
scope_->SetLanguageMode(entry.language_mode());
|
||||||
} else {
|
} else {
|
||||||
is_lazily_compiled = false;
|
is_lazily_compiled = false;
|
||||||
}
|
}
|
||||||
@ -4206,7 +4210,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
scope->end_position() - function_block_pos);
|
scope->end_position() - function_block_pos);
|
||||||
materialized_literal_count = logger.literals();
|
materialized_literal_count = logger.literals();
|
||||||
expected_property_count = logger.properties();
|
expected_property_count = logger.properties();
|
||||||
top_scope_->SetLanguageMode(logger.language_mode());
|
scope_->SetLanguageMode(logger.language_mode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4214,7 +4218,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
|
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
|
||||||
body = new(zone()) ZoneList<Statement*>(8, zone());
|
body = new(zone()) ZoneList<Statement*>(8, zone());
|
||||||
if (fvar != NULL) {
|
if (fvar != NULL) {
|
||||||
VariableProxy* fproxy = top_scope_->NewUnresolved(
|
VariableProxy* fproxy = scope_->NewUnresolved(
|
||||||
factory(), function_name, Interface::NewConst());
|
factory(), function_name, Interface::NewConst());
|
||||||
fproxy->BindTo(fvar);
|
fproxy->BindTo(fvar);
|
||||||
body->Add(factory()->NewExpressionStatement(
|
body->Add(factory()->NewExpressionStatement(
|
||||||
@ -4234,11 +4238,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject),
|
Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject),
|
||||||
arguments, pos);
|
arguments, pos);
|
||||||
VariableProxy* init_proxy = factory()->NewVariableProxy(
|
VariableProxy* init_proxy = factory()->NewVariableProxy(
|
||||||
current_function_state_->generator_object_variable());
|
function_state_->generator_object_variable());
|
||||||
Assignment* assignment = factory()->NewAssignment(
|
Assignment* assignment = factory()->NewAssignment(
|
||||||
Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
|
Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
|
||||||
VariableProxy* get_proxy = factory()->NewVariableProxy(
|
VariableProxy* get_proxy = factory()->NewVariableProxy(
|
||||||
current_function_state_->generator_object_variable());
|
function_state_->generator_object_variable());
|
||||||
Yield* yield = factory()->NewYield(
|
Yield* yield = factory()->NewYield(
|
||||||
get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
|
get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
|
||||||
body->Add(factory()->NewExpressionStatement(
|
body->Add(factory()->NewExpressionStatement(
|
||||||
@ -4249,7 +4253,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
|
|
||||||
if (is_generator) {
|
if (is_generator) {
|
||||||
VariableProxy* get_proxy = factory()->NewVariableProxy(
|
VariableProxy* get_proxy = factory()->NewVariableProxy(
|
||||||
current_function_state_->generator_object_variable());
|
function_state_->generator_object_variable());
|
||||||
Expression *undefined = factory()->NewLiteral(
|
Expression *undefined = factory()->NewLiteral(
|
||||||
isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
|
isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
|
||||||
Yield* yield = factory()->NewYield(
|
Yield* yield = factory()->NewYield(
|
||||||
@ -4268,7 +4272,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
|
|
||||||
// Validate strict mode. We can do this only after parsing the function,
|
// Validate strict mode. We can do this only after parsing the function,
|
||||||
// since the function can declare itself strict.
|
// since the function can declare itself strict.
|
||||||
if (!top_scope_->is_classic_mode()) {
|
if (!scope_->is_classic_mode()) {
|
||||||
if (IsEvalOrArguments(function_name)) {
|
if (IsEvalOrArguments(function_name)) {
|
||||||
ReportMessageAt(function_name_location, "strict_eval_arguments");
|
ReportMessageAt(function_name_location, "strict_eval_arguments");
|
||||||
*ok = false;
|
*ok = false;
|
||||||
@ -4349,7 +4353,7 @@ PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
|
|||||||
allow_harmony_numeric_literals());
|
allow_harmony_numeric_literals());
|
||||||
}
|
}
|
||||||
PreParser::PreParseResult result =
|
PreParser::PreParseResult result =
|
||||||
reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
|
reusable_preparser_->PreParseLazyFunction(scope_->language_mode(),
|
||||||
is_generator(),
|
is_generator(),
|
||||||
logger);
|
logger);
|
||||||
return result;
|
return result;
|
||||||
@ -4369,7 +4373,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
|
|||||||
if (extension_ != NULL) {
|
if (extension_ != NULL) {
|
||||||
// The extension structures are only accessible while parsing the
|
// The extension structures are only accessible while parsing the
|
||||||
// very first time not when reparsing because of lazy compilation.
|
// very first time not when reparsing because of lazy compilation.
|
||||||
top_scope_->DeclarationScope()->ForceEagerCompilation();
|
scope_->DeclarationScope()->ForceEagerCompilation();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Runtime::Function* function = Runtime::FunctionForName(name);
|
const Runtime::Function* function = Runtime::FunctionForName(name);
|
||||||
@ -4437,7 +4441,7 @@ void Parser::MarkAsLValue(Expression* expression) {
|
|||||||
// in strict mode.
|
// in strict mode.
|
||||||
void Parser::CheckStrictModeLValue(Expression* expression,
|
void Parser::CheckStrictModeLValue(Expression* expression,
|
||||||
bool* ok) {
|
bool* ok) {
|
||||||
ASSERT(!top_scope_->is_classic_mode());
|
ASSERT(!scope_->is_classic_mode());
|
||||||
VariableProxy* lhs = expression != NULL
|
VariableProxy* lhs = expression != NULL
|
||||||
? expression->AsVariableProxy()
|
? expression->AsVariableProxy()
|
||||||
: NULL;
|
: NULL;
|
||||||
|
24
src/parser.h
24
src/parser.h
@ -498,7 +498,9 @@ class Parser : public ParserBase<ParserTraits> {
|
|||||||
|
|
||||||
class FunctionState BASE_EMBEDDED {
|
class FunctionState BASE_EMBEDDED {
|
||||||
public:
|
public:
|
||||||
FunctionState(Parser* parser, Scope* scope);
|
FunctionState(FunctionState** function_state_stack,
|
||||||
|
Scope** scope_stack, Scope* scope,
|
||||||
|
Zone* zone);
|
||||||
~FunctionState();
|
~FunctionState();
|
||||||
|
|
||||||
int NextMaterializedLiteralIndex() {
|
int NextMaterializedLiteralIndex() {
|
||||||
@ -545,9 +547,11 @@ class Parser : public ParserBase<ParserTraits> {
|
|||||||
// indicates that this function is not a generator.
|
// indicates that this function is not a generator.
|
||||||
Variable* generator_object_variable_;
|
Variable* generator_object_variable_;
|
||||||
|
|
||||||
Parser* parser_;
|
FunctionState** function_state_stack_;
|
||||||
FunctionState* outer_function_state_;
|
FunctionState* outer_function_state_;
|
||||||
|
Scope** scope_stack_;
|
||||||
Scope* outer_scope_;
|
Scope* outer_scope_;
|
||||||
|
Isolate* isolate_;
|
||||||
int saved_ast_node_id_;
|
int saved_ast_node_id_;
|
||||||
AstNodeFactory<AstConstructionVisitor> factory_;
|
AstNodeFactory<AstConstructionVisitor> factory_;
|
||||||
};
|
};
|
||||||
@ -590,17 +594,17 @@ class Parser : public ParserBase<ParserTraits> {
|
|||||||
symbol_cache_.Initialize(data ? data->symbol_count() : 0, zone());
|
symbol_cache_.Initialize(data ? data->symbol_count() : 0, zone());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inside_with() const { return top_scope_->inside_with(); }
|
bool inside_with() const { return scope_->inside_with(); }
|
||||||
Scanner& scanner() { return scanner_; }
|
Scanner& scanner() { return scanner_; }
|
||||||
Mode mode() const { return mode_; }
|
Mode mode() const { return mode_; }
|
||||||
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
|
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
|
||||||
bool is_extended_mode() {
|
bool is_extended_mode() {
|
||||||
ASSERT(top_scope_ != NULL);
|
ASSERT(scope_ != NULL);
|
||||||
return top_scope_->is_extended_mode();
|
return scope_->is_extended_mode();
|
||||||
}
|
}
|
||||||
Scope* DeclarationScope(VariableMode mode) {
|
Scope* DeclarationScope(VariableMode mode) {
|
||||||
return IsLexicalVariableMode(mode)
|
return IsLexicalVariableMode(mode)
|
||||||
? top_scope_ : top_scope_->DeclarationScope();
|
? scope_ : scope_->DeclarationScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
// All ParseXXX functions take as the last argument an *ok parameter
|
// All ParseXXX functions take as the last argument an *ok parameter
|
||||||
@ -767,7 +771,7 @@ class Parser : public ParserBase<ParserTraits> {
|
|||||||
SingletonLogger* logger);
|
SingletonLogger* logger);
|
||||||
|
|
||||||
AstNodeFactory<AstConstructionVisitor>* factory() {
|
AstNodeFactory<AstConstructionVisitor>* factory() {
|
||||||
return current_function_state_->factory();
|
return function_state_->factory();
|
||||||
}
|
}
|
||||||
|
|
||||||
Isolate* isolate_;
|
Isolate* isolate_;
|
||||||
@ -776,9 +780,9 @@ class Parser : public ParserBase<ParserTraits> {
|
|||||||
Handle<Script> script_;
|
Handle<Script> script_;
|
||||||
Scanner scanner_;
|
Scanner scanner_;
|
||||||
PreParser* reusable_preparser_;
|
PreParser* reusable_preparser_;
|
||||||
Scope* top_scope_;
|
Scope* scope_; // Scope stack.
|
||||||
Scope* original_scope_; // for ES5 function declarations in sloppy eval
|
Scope* original_scope_; // for ES5 function declarations in sloppy eval
|
||||||
FunctionState* current_function_state_;
|
FunctionState* function_state_; // Function state stack.
|
||||||
Target* target_stack_; // for break, continue statements
|
Target* target_stack_; // for break, continue statements
|
||||||
v8::Extension* extension_;
|
v8::Extension* extension_;
|
||||||
ScriptDataImpl* pre_parse_data_;
|
ScriptDataImpl* pre_parse_data_;
|
||||||
@ -788,8 +792,6 @@ class Parser : public ParserBase<ParserTraits> {
|
|||||||
|
|
||||||
Zone* zone_;
|
Zone* zone_;
|
||||||
CompilationInfo* info_;
|
CompilationInfo* info_;
|
||||||
friend class BlockState;
|
|
||||||
friend class FunctionState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,12 +61,12 @@ bool PreParserTraits::is_classic_mode() const {
|
|||||||
|
|
||||||
|
|
||||||
bool PreParserTraits::is_generator() const {
|
bool PreParserTraits::is_generator() const {
|
||||||
return pre_parser_->scope_->is_generator();
|
return pre_parser_->function_state_->is_generator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PreParserTraits::NextMaterializedLiteralIndex() {
|
int PreParserTraits::NextMaterializedLiteralIndex() {
|
||||||
return pre_parser_->scope_->NextMaterializedLiteralIndex();
|
return pre_parser_->function_state_->NextMaterializedLiteralIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -126,9 +126,9 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
|||||||
LanguageMode mode, bool is_generator, ParserRecorder* log) {
|
LanguageMode mode, bool is_generator, ParserRecorder* log) {
|
||||||
log_ = log;
|
log_ = log;
|
||||||
// Lazy functions always have trivial outer scopes (no with/catch scopes).
|
// Lazy functions always have trivial outer scopes (no with/catch scopes).
|
||||||
Scope top_scope(&scope_, kTopLevelScope);
|
FunctionState top_scope(&function_state_, &scope_, GLOBAL_SCOPE);
|
||||||
set_language_mode(mode);
|
scope_->SetLanguageMode(mode);
|
||||||
Scope function_scope(&scope_, kFunctionScope);
|
FunctionState function_scope(&function_state_, &scope_, FUNCTION_SCOPE);
|
||||||
function_scope.set_is_generator(is_generator);
|
function_scope.set_is_generator(is_generator);
|
||||||
ASSERT_EQ(Token::LBRACE, scanner()->current_token());
|
ASSERT_EQ(Token::LBRACE, scanner()->current_token());
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
@ -206,8 +206,8 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
|
|||||||
Statement statement = ParseSourceElement(CHECK_OK);
|
Statement statement = ParseSourceElement(CHECK_OK);
|
||||||
if (directive_prologue) {
|
if (directive_prologue) {
|
||||||
if (statement.IsUseStrictLiteral()) {
|
if (statement.IsUseStrictLiteral()) {
|
||||||
set_language_mode(allow_harmony_scoping() ?
|
scope_->SetLanguageMode(allow_harmony_scoping() ?
|
||||||
EXTENDED_MODE : STRICT_MODE);
|
EXTENDED_MODE : STRICT_MODE);
|
||||||
} else if (!statement.IsStringLiteral()) {
|
} else if (!statement.IsStringLiteral()) {
|
||||||
directive_prologue = false;
|
directive_prologue = false;
|
||||||
}
|
}
|
||||||
@ -352,7 +352,7 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
|
|||||||
//
|
//
|
||||||
Expect(Token::LBRACE, CHECK_OK);
|
Expect(Token::LBRACE, CHECK_OK);
|
||||||
while (peek() != Token::RBRACE) {
|
while (peek() != Token::RBRACE) {
|
||||||
if (is_extended_mode()) {
|
if (scope_->is_extended_mode()) {
|
||||||
ParseSourceElement(CHECK_OK);
|
ParseSourceElement(CHECK_OK);
|
||||||
} else {
|
} else {
|
||||||
ParseStatement(CHECK_OK);
|
ParseStatement(CHECK_OK);
|
||||||
@ -416,7 +416,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
|
|||||||
// existing pages. Therefore we keep allowing const with the old
|
// existing pages. Therefore we keep allowing const with the old
|
||||||
// non-harmony semantics in classic mode.
|
// non-harmony semantics in classic mode.
|
||||||
Consume(Token::CONST);
|
Consume(Token::CONST);
|
||||||
switch (language_mode()) {
|
switch (scope_->language_mode()) {
|
||||||
case CLASSIC_MODE:
|
case CLASSIC_MODE:
|
||||||
break;
|
break;
|
||||||
case STRICT_MODE: {
|
case STRICT_MODE: {
|
||||||
@ -442,7 +442,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
|
|||||||
//
|
//
|
||||||
// * It is a Syntax Error if the code that matches this production is not
|
// * It is a Syntax Error if the code that matches this production is not
|
||||||
// contained in extended code.
|
// contained in extended code.
|
||||||
if (!is_extended_mode()) {
|
if (!scope_->is_extended_mode()) {
|
||||||
ReportMessageAt(scanner()->peek_location(), "illegal_let");
|
ReportMessageAt(scanner()->peek_location(), "illegal_let");
|
||||||
*ok = false;
|
*ok = false;
|
||||||
return Statement::Default();
|
return Statement::Default();
|
||||||
@ -602,7 +602,7 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
|
|||||||
ParseExpression(true, CHECK_OK);
|
ParseExpression(true, CHECK_OK);
|
||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
|
|
||||||
Scope::InsideWith iw(scope_);
|
BlockState block_state(&scope_, WITH_SCOPE);
|
||||||
ParseStatement(CHECK_OK);
|
ParseStatement(CHECK_OK);
|
||||||
return Statement::Default();
|
return Statement::Default();
|
||||||
}
|
}
|
||||||
@ -775,7 +775,8 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
|
|||||||
Expect(Token::LPAREN, CHECK_OK);
|
Expect(Token::LPAREN, CHECK_OK);
|
||||||
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
{ Scope::InsideWith iw(scope_);
|
{
|
||||||
|
BlockState block_state(&scope_, WITH_SCOPE);
|
||||||
ParseBlock(CHECK_OK);
|
ParseBlock(CHECK_OK);
|
||||||
}
|
}
|
||||||
tok = peek();
|
tok = peek();
|
||||||
@ -833,7 +834,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
|||||||
// YieldExpression
|
// YieldExpression
|
||||||
// LeftHandSideExpression AssignmentOperator AssignmentExpression
|
// LeftHandSideExpression AssignmentOperator AssignmentExpression
|
||||||
|
|
||||||
if (scope_->is_generator() && peek() == Token::YIELD) {
|
if (function_state_->is_generator() && peek() == Token::YIELD) {
|
||||||
return ParseYieldExpression(ok);
|
return ParseYieldExpression(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,7 +860,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
|||||||
ParseAssignmentExpression(accept_IN, CHECK_OK);
|
ParseAssignmentExpression(accept_IN, CHECK_OK);
|
||||||
|
|
||||||
if ((op == Token::ASSIGN) && expression.IsThisProperty()) {
|
if ((op == Token::ASSIGN) && expression.IsThisProperty()) {
|
||||||
scope_->AddProperty();
|
function_state_->AddProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Expression::Default();
|
return Expression::Default();
|
||||||
@ -1219,7 +1220,7 @@ PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
|
|||||||
}
|
}
|
||||||
Expect(Token::RBRACK, CHECK_OK);
|
Expect(Token::RBRACK, CHECK_OK);
|
||||||
|
|
||||||
scope_->NextMaterializedLiteralIndex();
|
function_state_->NextMaterializedLiteralIndex();
|
||||||
return Expression::Default();
|
return Expression::Default();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1231,7 +1232,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
|
|||||||
// | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
|
// | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
|
||||||
// )*[','] '}'
|
// )*[','] '}'
|
||||||
|
|
||||||
ObjectLiteralChecker checker(this, language_mode());
|
ObjectLiteralChecker checker(this, scope_->language_mode());
|
||||||
|
|
||||||
Expect(Token::LBRACE, CHECK_OK);
|
Expect(Token::LBRACE, CHECK_OK);
|
||||||
while (peek() != Token::RBRACE) {
|
while (peek() != Token::RBRACE) {
|
||||||
@ -1301,7 +1302,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
|
|||||||
}
|
}
|
||||||
Expect(Token::RBRACE, CHECK_OK);
|
Expect(Token::RBRACE, CHECK_OK);
|
||||||
|
|
||||||
scope_->NextMaterializedLiteralIndex();
|
function_state_->NextMaterializedLiteralIndex();
|
||||||
return Expression::Default();
|
return Expression::Default();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1339,8 +1340,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
|||||||
|
|
||||||
// Parse function body.
|
// Parse function body.
|
||||||
ScopeType outer_scope_type = scope_->type();
|
ScopeType outer_scope_type = scope_->type();
|
||||||
bool inside_with = scope_->IsInsideWith();
|
bool inside_with = scope_->inside_with();
|
||||||
Scope function_scope(&scope_, kFunctionScope);
|
FunctionState function_scope(&function_state_, &scope_, FUNCTION_SCOPE);
|
||||||
function_scope.set_is_generator(is_generator);
|
function_scope.set_is_generator(is_generator);
|
||||||
// FormalParameterList ::
|
// FormalParameterList ::
|
||||||
// '(' (Identifier)*[','] ')'
|
// '(' (Identifier)*[','] ')'
|
||||||
@ -1388,7 +1389,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
|||||||
// Determine if the function will be lazily compiled.
|
// Determine if the function will be lazily compiled.
|
||||||
// Currently only happens to top-level functions.
|
// Currently only happens to top-level functions.
|
||||||
// Optimistically assume that all top-level functions are lazily compiled.
|
// Optimistically assume that all top-level functions are lazily compiled.
|
||||||
bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
|
bool is_lazily_compiled = (outer_scope_type == GLOBAL_SCOPE &&
|
||||||
!inside_with && allow_lazy() &&
|
!inside_with && allow_lazy() &&
|
||||||
!parenthesized_function_);
|
!parenthesized_function_);
|
||||||
parenthesized_function_ = false;
|
parenthesized_function_ = false;
|
||||||
@ -1450,9 +1451,9 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
|
|||||||
ASSERT_EQ(Token::RBRACE, scanner()->peek());
|
ASSERT_EQ(Token::RBRACE, scanner()->peek());
|
||||||
int body_end = scanner()->peek_location().end_pos;
|
int body_end = scanner()->peek_location().end_pos;
|
||||||
log_->LogFunction(body_start, body_end,
|
log_->LogFunction(body_start, body_end,
|
||||||
scope_->materialized_literal_count(),
|
function_state_->materialized_literal_count(),
|
||||||
scope_->expected_properties(),
|
function_state_->expected_properties(),
|
||||||
language_mode());
|
scope_->language_mode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
135
src/preparser.h
135
src/preparser.h
@ -512,6 +512,7 @@ class PreParser : public ParserBase<PreParserTraits> {
|
|||||||
uintptr_t stack_limit)
|
uintptr_t stack_limit)
|
||||||
: ParserBase<PreParserTraits>(scanner, stack_limit, this),
|
: ParserBase<PreParserTraits>(scanner, stack_limit, this),
|
||||||
log_(log),
|
log_(log),
|
||||||
|
function_state_(NULL),
|
||||||
scope_(NULL) { }
|
scope_(NULL) { }
|
||||||
|
|
||||||
~PreParser() {}
|
~PreParser() {}
|
||||||
@ -521,7 +522,7 @@ class PreParser : public ParserBase<PreParserTraits> {
|
|||||||
// captured the syntax error), and false if a stack-overflow happened
|
// captured the syntax error), and false if a stack-overflow happened
|
||||||
// during parsing.
|
// during parsing.
|
||||||
PreParseResult PreParseProgram() {
|
PreParseResult PreParseProgram() {
|
||||||
Scope top_scope(&scope_, kTopLevelScope);
|
FunctionState top_scope(&function_state_, &scope_, GLOBAL_SCOPE);
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
int start_position = scanner()->peek_location().beg_pos;
|
int start_position = scanner()->peek_location().beg_pos;
|
||||||
ParseSourceElements(Token::EOS, &ok);
|
ParseSourceElements(Token::EOS, &ok);
|
||||||
@ -554,11 +555,6 @@ class PreParser : public ParserBase<PreParserTraits> {
|
|||||||
// are either being counted in the preparser data, or is important
|
// are either being counted in the preparser data, or is important
|
||||||
// to throw the correct syntax error exceptions.
|
// to throw the correct syntax error exceptions.
|
||||||
|
|
||||||
enum ScopeType {
|
|
||||||
kTopLevelScope,
|
|
||||||
kFunctionScope
|
|
||||||
};
|
|
||||||
|
|
||||||
enum VariableDeclarationContext {
|
enum VariableDeclarationContext {
|
||||||
kSourceElement,
|
kSourceElement,
|
||||||
kStatement,
|
kStatement,
|
||||||
@ -626,61 +622,97 @@ class PreParser : public ParserBase<PreParserTraits> {
|
|||||||
|
|
||||||
class Scope {
|
class Scope {
|
||||||
public:
|
public:
|
||||||
Scope(Scope** variable, ScopeType type)
|
explicit Scope(Scope* outer_scope, ScopeType scope_type)
|
||||||
: variable_(variable),
|
: scope_type_(scope_type) {
|
||||||
prev_(*variable),
|
if (outer_scope) {
|
||||||
type_(type),
|
scope_inside_with_ =
|
||||||
materialized_literal_count_(0),
|
outer_scope->scope_inside_with_ || is_with_scope();
|
||||||
expected_properties_(0),
|
language_mode_ = outer_scope->language_mode();
|
||||||
with_nesting_count_(0),
|
} else {
|
||||||
language_mode_(
|
scope_inside_with_ = is_with_scope();
|
||||||
(prev_ != NULL) ? prev_->language_mode() : CLASSIC_MODE),
|
language_mode_ = CLASSIC_MODE;
|
||||||
is_generator_(false) {
|
}
|
||||||
*variable = this;
|
|
||||||
}
|
}
|
||||||
~Scope() { *variable_ = prev_; }
|
|
||||||
int NextMaterializedLiteralIndex() { return materialized_literal_count_++; }
|
bool is_with_scope() const { return scope_type_ == WITH_SCOPE; }
|
||||||
void AddProperty() { expected_properties_++; }
|
bool is_classic_mode() const {
|
||||||
ScopeType type() { return type_; }
|
return language_mode() == CLASSIC_MODE;
|
||||||
int expected_properties() { return expected_properties_; }
|
|
||||||
int materialized_literal_count() { return materialized_literal_count_; }
|
|
||||||
bool IsInsideWith() { return with_nesting_count_ != 0; }
|
|
||||||
bool is_generator() { return is_generator_; }
|
|
||||||
void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
|
|
||||||
bool is_classic_mode() {
|
|
||||||
return language_mode_ == CLASSIC_MODE;
|
|
||||||
}
|
}
|
||||||
LanguageMode language_mode() {
|
bool is_extended_mode() {
|
||||||
return language_mode_;
|
return language_mode() == EXTENDED_MODE;
|
||||||
}
|
}
|
||||||
void set_language_mode(LanguageMode language_mode) {
|
bool inside_with() const {
|
||||||
|
return scope_inside_with_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopeType type() { return scope_type_; }
|
||||||
|
LanguageMode language_mode() const { return language_mode_; }
|
||||||
|
void SetLanguageMode(LanguageMode language_mode) {
|
||||||
language_mode_ = language_mode;
|
language_mode_ = language_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InsideWith {
|
private:
|
||||||
public:
|
ScopeType scope_type_;
|
||||||
explicit InsideWith(Scope* scope) : scope_(scope) {
|
bool scope_inside_with_;
|
||||||
scope->with_nesting_count_++;
|
LanguageMode language_mode_;
|
||||||
}
|
};
|
||||||
|
|
||||||
~InsideWith() { scope_->with_nesting_count_--; }
|
class FunctionState {
|
||||||
|
public:
|
||||||
private:
|
FunctionState(FunctionState** function_state_stack, Scope** scope_stack,
|
||||||
Scope* scope_;
|
ScopeType scope_type)
|
||||||
DISALLOW_COPY_AND_ASSIGN(InsideWith);
|
: function_state_stack_(function_state_stack),
|
||||||
};
|
outer_function_state_(*function_state_stack),
|
||||||
|
scope_stack_(scope_stack),
|
||||||
|
outer_scope_(*scope_stack),
|
||||||
|
scope_(*scope_stack, scope_type),
|
||||||
|
materialized_literal_count_(0),
|
||||||
|
expected_properties_(0),
|
||||||
|
is_generator_(false) {
|
||||||
|
*scope_stack = &scope_;
|
||||||
|
*function_state_stack = this;
|
||||||
|
}
|
||||||
|
~FunctionState() {
|
||||||
|
*scope_stack_ = outer_scope_;
|
||||||
|
*function_state_stack_ = outer_function_state_;
|
||||||
|
}
|
||||||
|
int NextMaterializedLiteralIndex() { return materialized_literal_count_++; }
|
||||||
|
void AddProperty() { expected_properties_++; }
|
||||||
|
int expected_properties() { return expected_properties_; }
|
||||||
|
int materialized_literal_count() { return materialized_literal_count_; }
|
||||||
|
bool is_generator() { return is_generator_; }
|
||||||
|
void set_is_generator(bool is_generator) { is_generator_ = is_generator; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Scope** const variable_;
|
FunctionState** const function_state_stack_;
|
||||||
Scope* const prev_;
|
FunctionState* const outer_function_state_;
|
||||||
const ScopeType type_;
|
Scope** const scope_stack_;
|
||||||
|
Scope* const outer_scope_;
|
||||||
|
Scope scope_;
|
||||||
|
|
||||||
int materialized_literal_count_;
|
int materialized_literal_count_;
|
||||||
int expected_properties_;
|
int expected_properties_;
|
||||||
int with_nesting_count_;
|
|
||||||
LanguageMode language_mode_;
|
LanguageMode language_mode_;
|
||||||
bool is_generator_;
|
bool is_generator_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BlockState {
|
||||||
|
public:
|
||||||
|
BlockState(Scope** scope_stack, ScopeType scope_type)
|
||||||
|
: scope_stack_(scope_stack),
|
||||||
|
outer_scope_(*scope_stack),
|
||||||
|
scope_(*scope_stack, scope_type) {
|
||||||
|
*scope_stack_ = &scope_;
|
||||||
|
}
|
||||||
|
|
||||||
|
~BlockState() { *scope_stack_ = outer_scope_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Scope** scope_stack_;
|
||||||
|
Scope* outer_scope_;
|
||||||
|
Scope scope_;
|
||||||
|
};
|
||||||
|
|
||||||
// All ParseXXX functions take as the last argument an *ok parameter
|
// All ParseXXX functions take as the last argument an *ok parameter
|
||||||
// which is set to false if parsing failed; it is unchanged otherwise.
|
// which is set to false if parsing failed; it is unchanged otherwise.
|
||||||
// By making the 'exception handling' explicit, we are forced to check
|
// By making the 'exception handling' explicit, we are forced to check
|
||||||
@ -740,19 +772,10 @@ class PreParser : public ParserBase<PreParserTraits> {
|
|||||||
// Log the currently parsed string literal.
|
// Log the currently parsed string literal.
|
||||||
Expression GetStringSymbol();
|
Expression GetStringSymbol();
|
||||||
|
|
||||||
void set_language_mode(LanguageMode language_mode) {
|
|
||||||
scope_->set_language_mode(language_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_extended_mode() {
|
|
||||||
return scope_->language_mode() == EXTENDED_MODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LanguageMode language_mode() { return scope_->language_mode(); }
|
|
||||||
|
|
||||||
bool CheckInOrOf(bool accept_OF);
|
bool CheckInOrOf(bool accept_OF);
|
||||||
|
|
||||||
ParserRecorder* log_;
|
ParserRecorder* log_;
|
||||||
|
FunctionState* function_state_;
|
||||||
Scope* scope_;
|
Scope* scope_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user