diff options
Diffstat (limited to 'src/ast/scopes.cc')
-rw-r--r-- | src/ast/scopes.cc | 170 |
1 files changed, 14 insertions, 156 deletions
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc index c2b05b7c..7c87ce39 100644 --- a/src/ast/scopes.cc +++ b/src/ast/scopes.cc @@ -27,12 +27,10 @@ VariableMap::VariableMap(Zone* zone) zone_(zone) {} VariableMap::~VariableMap() {} - Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, VariableMode mode, Variable::Kind kind, InitializationFlag initialization_flag, - MaybeAssignedFlag maybe_assigned_flag, - int declaration_group_start) { + MaybeAssignedFlag maybe_assigned_flag) { // AstRawStrings are unambiguous, i.e., the same string is always represented // by the same AstRawString*. // FIXME(marja): fix the type of Lookup. @@ -42,14 +40,8 @@ Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, if (p->value == NULL) { // The variable has not been declared yet -> insert it. DCHECK(p->key == name); - if (kind == Variable::CLASS) { - p->value = new (zone()) - ClassVariable(scope, name, mode, initialization_flag, - maybe_assigned_flag, declaration_group_start); - } else { - p->value = new (zone()) Variable( - scope, name, mode, kind, initialization_flag, maybe_assigned_flag); - } + p->value = new (zone()) Variable(scope, name, mode, kind, + initialization_flag, maybe_assigned_flag); } return reinterpret_cast<Variable*>(p->value); } @@ -103,8 +95,7 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, sloppy_block_function_map_(zone), already_resolved_(false), ast_value_factory_(ast_value_factory), - zone_(zone), - class_declaration_group_start_(-1) { + zone_(zone) { SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(), function_kind); // The outermost scope must be a script scope. @@ -112,7 +103,6 @@ Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, DCHECK(!HasIllegalRedeclaration()); } - Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, Handle<ScopeInfo> scope_info, AstValueFactory* value_factory) : inner_scopes_(4, zone), @@ -125,8 +115,7 @@ Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, sloppy_block_function_map_(zone), already_resolved_(true), ast_value_factory_(value_factory), - zone_(zone), - class_declaration_group_start_(-1) { + zone_(zone) { SetDefaults(scope_type, NULL, scope_info); if (!scope_info.is_null()) { num_heap_slots_ = scope_info_->ContextLength(); @@ -137,7 +126,6 @@ Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, AddInnerScope(inner_scope); } - Scope::Scope(Zone* zone, Scope* inner_scope, const AstRawString* catch_variable_name, AstValueFactory* value_factory) @@ -151,8 +139,7 @@ Scope::Scope(Zone* zone, Scope* inner_scope, sloppy_block_function_map_(zone), already_resolved_(true), ast_value_factory_(value_factory), - zone_(zone), - class_declaration_group_start_(-1) { + zone_(zone) { SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); AddInnerScope(inner_scope); ++num_var_or_const_; @@ -528,19 +515,17 @@ Variable* Scope::DeclareParameter( return var; } - Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, InitializationFlag init_flag, Variable::Kind kind, - MaybeAssignedFlag maybe_assigned_flag, - int declaration_group_start) { + MaybeAssignedFlag maybe_assigned_flag) { DCHECK(!already_resolved()); // This function handles VAR, LET, and CONST modes. DYNAMIC variables are - // introduces during variable allocation, and TEMPORARY variables are + // introduced during variable allocation, and TEMPORARY variables are // allocated via NewTemporary(). DCHECK(IsDeclaredVariableMode(mode)); ++num_var_or_const_; return variables_.Declare(this, name, mode, kind, init_flag, - maybe_assigned_flag, declaration_group_start); + maybe_assigned_flag); } @@ -660,11 +645,9 @@ class VarAndOrder { int order_; }; - -void Scope::CollectStackAndContextLocals( - ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals, - ZoneList<Variable*>* context_globals, - ZoneList<Variable*>* strong_mode_free_variables) { +void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, + ZoneList<Variable*>* context_locals, + ZoneList<Variable*>* context_globals) { DCHECK(stack_locals != NULL); DCHECK(context_locals != NULL); DCHECK(context_globals != NULL); @@ -691,11 +674,6 @@ void Scope::CollectStackAndContextLocals( p != NULL; p = variables_.Next(p)) { Variable* var = reinterpret_cast<Variable*>(p->value); - if (strong_mode_free_variables && var->has_strong_mode_reference() && - var->mode() == DYNAMIC_GLOBAL) { - strong_mode_free_variables->Add(var, zone()); - } - if (var->is_used()) { vars.Add(VarAndOrder(var, p->order), zone()); } @@ -1017,9 +995,7 @@ void Scope::Print(int n) { if (HasTrivialOuterContext()) { Indent(n1, "// scope has trivial outer context\n"); } - if (is_strong(language_mode())) { - Indent(n1, "// strong mode scope\n"); - } else if (is_strict(language_mode())) { + if (is_strict(language_mode())) { Indent(n1, "// strict mode scope\n"); } if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); @@ -1204,10 +1180,6 @@ bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, switch (binding_kind) { case BOUND: - // We found a variable binding. - if (is_strong(language_mode())) { - if (!CheckStrongModeDeclaration(proxy, var)) return false; - } break; case BOUND_EVAL_SHADOWED: @@ -1245,126 +1217,12 @@ bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, DCHECK(var != NULL); if (proxy->is_assigned()) var->set_maybe_assigned(); - if (is_strong(language_mode())) { - // Record that the variable is referred to from strong mode. Also, record - // the position. - var->RecordStrongModeReference(proxy->position(), proxy->end_position()); - } - proxy->BindTo(var); return true; } -bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) { - // Check for declaration-after use (for variables) in strong mode. Note that - // we can only do this in the case where we have seen the declaration. And we - // always allow referencing functions (for now). - - // This might happen during lazy compilation; we don't keep track of - // initializer positions for variables stored in ScopeInfo, so we cannot check - // bindings against them. TODO(marja, rossberg): remove this hack. - if (var->initializer_position() == RelocInfo::kNoPosition) return true; - - // Allow referencing the class name from methods of that class, even though - // the initializer position for class names is only after the body. - Scope* scope = this; - while (scope) { - if (scope->ClassVariableForMethod() == var) return true; - scope = scope->outer_scope(); - } - - // Allow references from methods to classes declared later, if we detect no - // problematic dependency cycles. Note that we can be inside multiple methods - // at the same time, and it's enough if we find one where the reference is - // allowed. - if (var->is_class() && - var->AsClassVariable()->declaration_group_start() >= 0) { - for (scope = this; scope && scope != var->scope(); - scope = scope->outer_scope()) { - ClassVariable* class_var = scope->ClassVariableForMethod(); - // A method is referring to some other class, possibly declared - // later. Referring to a class declared earlier is always OK and covered - // by the code outside this if. Here we only need to allow special cases - // for referring to a class which is declared later. - - // Referring to a class C declared later is OK under the following - // circumstances: - - // 1. The class declarations are in a consecutive group with no other - // declarations or statements in between, and - - // 2. There is no dependency cycle where the first edge is an - // initialization time dependency (computed property name or extends - // clause) from C to something that depends on this class directly or - // transitively. - if (class_var && - class_var->declaration_group_start() == - var->AsClassVariable()->declaration_group_start()) { - return true; - } - - // TODO(marja,rossberg): implement the dependency cycle detection. Here we - // undershoot the target and allow referring to any class in the same - // consectuive declaration group. - - // The cycle detection can work roughly like this: 1) detect init-time - // references here (they are free variables which are inside the class - // scope but not inside a method scope - no parser changes needed to - // detect them) 2) if we encounter an init-time reference here, allow it, - // but record it for a later dependency cycle check 3) also record - // non-init-time references here 4) after scope analysis is done, analyse - // the dependency cycles: an illegal cycle is one starting with an - // init-time reference and leading back to the starting point with either - // non-init-time and init-time references. - } - } - - // If both the use and the declaration are inside an eval scope (possibly - // indirectly), or one of them is, we need to check whether they are inside - // the same eval scope or different ones. - - // TODO(marja,rossberg): Detect errors across different evals (depends on the - // future of eval in strong mode). - const Scope* eval_for_use = NearestOuterEvalScope(); - const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope(); - - if (proxy->position() != RelocInfo::kNoPosition && - proxy->position() < var->initializer_position() && !var->is_function() && - eval_for_use == eval_for_declaration) { - DCHECK(proxy->end_position() != RelocInfo::kNoPosition); - ReportMessage(proxy->position(), proxy->end_position(), - MessageTemplate::kStrongUseBeforeDeclaration, - proxy->raw_name()); - return false; - } - return true; -} - - -ClassVariable* Scope::ClassVariableForMethod() const { - // TODO(marja, rossberg): This fails to find a class variable in the following - // cases: - // let A = class { ... } - // It needs to be investigated whether this causes any practical problems. - if (!is_function_scope()) return nullptr; - if (IsInObjectLiteral(function_kind_)) return nullptr; - if (!IsConciseMethod(function_kind_) && !IsClassConstructor(function_kind_) && - !IsAccessorFunction(function_kind_)) { - return nullptr; - } - DCHECK_NOT_NULL(outer_scope_); - // The class scope contains at most one variable, the class name. - DCHECK(outer_scope_->variables_.occupancy() <= 1); - if (outer_scope_->variables_.occupancy() == 0) return nullptr; - VariableMap::Entry* p = outer_scope_->variables_.Start(); - Variable* var = reinterpret_cast<Variable*>(p->value); - if (!var->is_class()) return nullptr; - return var->AsClassVariable(); -} - - bool Scope::ResolveVariablesRecursively(ParseInfo* info, AstNodeFactory* factory) { DCHECK(info->script_scope()->is_script_scope()); @@ -1646,7 +1504,7 @@ void Scope::AllocateVariablesRecursively(Isolate* isolate) { } // If scope is already resolved, we still need to allocate - // variables in inner scopes which might not had been resolved yet. + // variables in inner scopes which might not have been resolved yet. if (already_resolved()) return; // The number of slots required for variables. num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |