| // 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_ |