aboutsummaryrefslogtreecommitdiff
path: root/src/ast/scopes.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast/scopes.cc')
-rw-r--r--src/ast/scopes.cc170
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;