1 // Copyright 2020 The Tint Authors. // 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 #ifndef SRC_SCOPE_STACK_H_ 15 #define SRC_SCOPE_STACK_H_ 16 17 #include <unordered_map> 18 #include <utility> 19 #include <vector> 20 21 #include "src/symbol.h" 22 23 namespace tint { 24 25 /// Used to store a stack of scope information. 26 /// The stack starts with a global scope which can not be popped. 27 template <class T> 28 class ScopeStack { 29 public: 30 /// Constructor ScopeStack()31 ScopeStack() { 32 // Push global bucket 33 stack_.push_back({}); 34 } 35 /// Copy Constructor 36 ScopeStack(const ScopeStack&) = default; 37 ~ScopeStack() = default; 38 39 /// Push a new scope on to the stack Push()40 void Push() { stack_.push_back({}); } 41 42 /// Pop the scope off the top of the stack Pop()43 void Pop() { 44 if (stack_.size() > 1) { 45 stack_.pop_back(); 46 } 47 } 48 49 /// Assigns the value into the top most scope of the stack. 50 /// @param symbol the symbol of the value 51 /// @param val the value 52 /// @returns the old value if there was an existing symbol at the top of the 53 /// stack, otherwise the zero initializer for type T. Set(const Symbol & symbol,T val)54 T Set(const Symbol& symbol, T val) { 55 std::swap(val, stack_.back()[symbol]); 56 return val; 57 } 58 59 /// Retrieves a value from the stack 60 /// @param symbol the symbol to look for 61 /// @returns the value, or the zero initializer if the value was not found Get(const Symbol & symbol)62 T Get(const Symbol& symbol) const { 63 for (auto iter = stack_.rbegin(); iter != stack_.rend(); ++iter) { 64 auto& map = *iter; 65 auto val = map.find(symbol); 66 if (val != map.end()) { 67 return val->second; 68 } 69 } 70 71 return T{}; 72 } 73 74 private: 75 std::vector<std::unordered_map<Symbol, T>> stack_; 76 }; 77 78 } // namespace tint 79 80 #endif // SRC_SCOPE_STACK_H_ 81