Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 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_TINT_SCOPE_STACK_H_ |
| 15 | #define SRC_TINT_SCOPE_STACK_H_ |
| 16 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 17 | #include <utility> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 18 | |
| 19 | #include "src/tint/symbol.h" |
Ben Clayton | 9418152 | 2022-11-09 20:55:33 +0000 | [diff] [blame] | 20 | #include "src/tint/utils/hashmap.h" |
| 21 | #include "src/tint/utils/vector.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 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. |
James Price | 2cf32b1 | 2022-05-11 13:50:33 +0000 | [diff] [blame] | 27 | template <class K, class V> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 28 | class ScopeStack { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 29 | public: |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 30 | /// Push a new scope on to the stack |
Ben Clayton | 9418152 | 2022-11-09 20:55:33 +0000 | [diff] [blame] | 31 | void Push() { stack_.Push({}); } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 32 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 33 | /// Pop the scope off the top of the stack |
| 34 | void Pop() { |
Ben Clayton | 9418152 | 2022-11-09 20:55:33 +0000 | [diff] [blame] | 35 | if (stack_.Length() > 1) { |
| 36 | stack_.Pop(); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 37 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 38 | } |
| 39 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 40 | /// Assigns the value into the top most scope of the stack. |
James Price | 2cf32b1 | 2022-05-11 13:50:33 +0000 | [diff] [blame] | 41 | /// @param key the key of the value |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 42 | /// @param val the value |
James Price | 2cf32b1 | 2022-05-11 13:50:33 +0000 | [diff] [blame] | 43 | /// @returns the old value if there was an existing key at the top of the |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 44 | /// stack, otherwise the zero initializer for type T. |
James Price | 2cf32b1 | 2022-05-11 13:50:33 +0000 | [diff] [blame] | 45 | V Set(const K& key, V val) { |
Ben Clayton | 9418152 | 2022-11-09 20:55:33 +0000 | [diff] [blame] | 46 | auto& back = stack_.Back(); |
Ben Clayton | 7c6e229 | 2022-11-23 21:04:25 +0000 | [diff] [blame] | 47 | if (auto el = back.Find(key)) { |
Ben Clayton | 9418152 | 2022-11-09 20:55:33 +0000 | [diff] [blame] | 48 | std::swap(val, *el); |
| 49 | return val; |
| 50 | } |
| 51 | back.Add(key, val); |
| 52 | return {}; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 53 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 54 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 55 | /// Retrieves a value from the stack |
James Price | 2cf32b1 | 2022-05-11 13:50:33 +0000 | [diff] [blame] | 56 | /// @param key the key to look for |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 57 | /// @returns the value, or the zero initializer if the value was not found |
James Price | 2cf32b1 | 2022-05-11 13:50:33 +0000 | [diff] [blame] | 58 | V Get(const K& key) const { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 59 | for (auto iter = stack_.rbegin(); iter != stack_.rend(); ++iter) { |
Ben Clayton | 7c6e229 | 2022-11-23 21:04:25 +0000 | [diff] [blame] | 60 | if (auto val = iter->Find(key)) { |
Ben Clayton | 9418152 | 2022-11-09 20:55:33 +0000 | [diff] [blame] | 61 | return *val; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 62 | } |
| 63 | } |
| 64 | |
James Price | 2cf32b1 | 2022-05-11 13:50:33 +0000 | [diff] [blame] | 65 | return V{}; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 66 | } |
| 67 | |
James Price | be656f7 | 2022-05-11 22:05:15 +0000 | [diff] [blame] | 68 | /// Return the top scope of the stack. |
| 69 | /// @returns the top scope of the stack |
Ben Clayton | 91d39a7 | 2023-01-12 20:31:33 +0000 | [diff] [blame] | 70 | const utils::Hashmap<K, V, 4>& Top() const { return stack_.Back(); } |
James Price | be656f7 | 2022-05-11 22:05:15 +0000 | [diff] [blame] | 71 | |
| 72 | /// Clear the scope stack. |
| 73 | void Clear() { |
Ben Clayton | 9418152 | 2022-11-09 20:55:33 +0000 | [diff] [blame] | 74 | stack_.Clear(); |
| 75 | stack_.Push({}); |
James Price | be656f7 | 2022-05-11 22:05:15 +0000 | [diff] [blame] | 76 | } |
| 77 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 78 | private: |
Ben Clayton | 91d39a7 | 2023-01-12 20:31:33 +0000 | [diff] [blame] | 79 | utils::Vector<utils::Hashmap<K, V, 4>, 8> stack_ = {{}}; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 80 | }; |
| 81 | |
| 82 | } // namespace tint |
| 83 | |
| 84 | #endif // SRC_TINT_SCOPE_STACK_H_ |