// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_TORQUE_SCOPE_H_
#define V8_TORQUE_SCOPE_H_
#include <map>
#include <string>
#include "src/torque/ast.h"
#include "src/torque/types.h"
#include "src/torque/utils.h"
namespace v8 {
namespace internal {
namespace torque {
class ScopeChain;
class Variable;
class Declarable;
class Scope {
public:
explicit Scope(ScopeChain& scope_chain);
void Stream(std::ostream& stream) const {
stream << "scope " << std::to_string(scope_number_) << " {";
for (auto& c : lookup_) {
stream << c.first << ",";
}
stream << "}";
}
int scope_number() const { return scope_number_; }
ScopeChain& GetScopeChain() const { return scope_chain_; }
void AddLiveVariables(std::set<const Variable*>& set);
void Print();
class Activator;
private:
friend class ScopeChain;
void CheckAlreadyDeclared(SourcePosition pos, const std::string& name,
const char* new_type);
void Declare(const std::string& name, Declarable* d) {
DCHECK_EQ(lookup_.end(), lookup_.find(name));
DCHECK(d != nullptr);
lookup_[name] = d;
}
Declarable* Lookup(const std::string& name) {
auto i = lookup_.find(name);
if (i == lookup_.end()) {
return nullptr;
}
return i->second;
}
ScopeChain& scope_chain_;
int scope_number_;
int private_label_number_;
std::map<std::string, Declarable*> lookup_;
};
class Scope::Activator {
public:
explicit Activator(Scope* scope);
~Activator();
private:
Scope* scope_;
};
class ScopeChain {
public:
ScopeChain() : next_scope_number_(0) {}
Scope* NewScope();
Scope* TopScope() const { return current_scopes_.back(); }
void PushScope(Scope* scope) { current_scopes_.push_back(scope); }
void PopScope() { current_scopes_.pop_back(); }
std::set<const Variable*> GetLiveVariables() {
std::set<const Variable*> result;
for (auto scope : current_scopes_) {
scope->AddLiveVariables(result);
}
return result;
}
void Declare(const std::string& name, Declarable* d) {
TopScope()->Declare(name, d);
}
Declarable* Lookup(const std::string& name) {
auto e = current_scopes_.rend();
auto c = current_scopes_.rbegin();
while (c != e) {
Declarable* result = (*c)->Lookup(name);
if (result != nullptr) return result;
++c;
}
return nullptr;
}
Declarable* ShallowLookup(const std::string& name) {
auto& e = current_scopes_.back();
return e->Lookup(name);
}
Declarable* LookupGlobalScope(const std::string& name) {
auto& e = current_scopes_.front();
return e->Lookup(name);
}
void Print() {
for (auto s : current_scopes_) {
s->Print();
}
}
struct Snapshot {
ScopeChain* chain;
std::vector<Scope*> current_scopes;
};
Snapshot TaskSnapshot() { return {this, current_scopes_}; }
class ScopedSnapshotRestorer {
public:
explicit ScopedSnapshotRestorer(const Snapshot& snapshot)
: chain_(snapshot.chain) {
saved_ = chain_->current_scopes_;
chain_->current_scopes_ = snapshot.current_scopes;
}
~ScopedSnapshotRestorer() { chain_->current_scopes_ = saved_; }
private:
ScopeChain* chain_;
std::vector<Scope*> saved_;
};
private:
friend class Scope;
friend class ScopedSnapshotRestorer;
int GetNextScopeNumber() { return next_scope_number_++; }
int next_scope_number_;
std::vector<std::unique_ptr<Scope>> scopes_;
std::vector<Scope*> current_scopes_;
};
inline std::ostream& operator<<(std::ostream& os, const Scope& scope) {
scope.Stream(os);
return os;
}
} // namespace torque
} // namespace internal
} // namespace v8
#endif // V8_TORQUE_SCOPE_H_