blob: a1619c4de8a892b9065d13207d3011e3bf66b9eb [file] [log] [blame]
dan sinclairc2d97ae2020-04-03 02:35:23 +00001// 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
dan sinclairc2d97ae2020-04-03 02:35:23 +000017#include <unordered_map>
18#include <vector>
19
dan sinclair795b6b52021-01-11 15:10:19 +000020#include "src/symbol.h"
21
dan sinclairc2d97ae2020-04-03 02:35:23 +000022namespace tint {
23
24/// Used to store a stack of scope information.
25/// The stack starts with a global scope which can not be popped.
26template <class T>
27class ScopeStack {
28 public:
29 /// Constructor
30 ScopeStack() {
31 // Push global bucket
32 stack_.push_back({});
33 }
34 /// Copy Constructor
35 ScopeStack(const ScopeStack&) = default;
36 ~ScopeStack() = default;
37
38 /// Push a new scope on to the stack
39 void push_scope() { stack_.push_back({}); }
40
41 /// Pop the scope off the top of the stack
42 void pop_scope() {
43 if (stack_.size() > 1) {
44 stack_.pop_back();
45 }
46 }
47
48 /// Set a global variable in the stack
dan sinclair795b6b52021-01-11 15:10:19 +000049 /// @param symbol the symbol of the variable
dan sinclairc2d97ae2020-04-03 02:35:23 +000050 /// @param val the value
Ben Claytonf6866a22021-01-11 22:02:42 +000051 void set_global(const Symbol& symbol, T val) { stack_[0][symbol] = val; }
Sarah Mashayekhid3107bd2020-08-11 20:44:06 +000052
dan sinclair795b6b52021-01-11 15:10:19 +000053 /// Sets variable into the top most scope of the stack
54 /// @param symbol the symbol of the variable
55 /// @param val the value
Ben Claytonf6866a22021-01-11 22:02:42 +000056 void set(const Symbol& symbol, T val) { stack_.back()[symbol] = val; }
dan sinclair795b6b52021-01-11 15:10:19 +000057
58 /// Checks for the given `symbol` in the stack
59 /// @param symbol the symbol to look for
60 /// @returns true if the stack contains `symbol`
61 bool has(const Symbol& symbol) const { return get(symbol, nullptr); }
62
63 /// Retrieves a given variable from the stack
64 /// @param symbol the symbol to look for
65 /// @param ret where to place the value
66 /// @returns true if the symbol was successfully found, false otherwise
67 bool get(const Symbol& symbol, T* ret) const {
68 return get(symbol, ret, nullptr);
69 }
70
71 /// Retrieves a given variable from the stack
72 /// @param symbol the symbol to look for
73 /// @param ret where to place the value
74 /// @param is_global set true if the symbol references a global variable
Sarah Mashayekhid3107bd2020-08-11 20:44:06 +000075 /// otherwise unchanged
dan sinclair795b6b52021-01-11 15:10:19 +000076 /// @returns true if the symbol was successfully found, false otherwise
77 bool get(const Symbol& symbol, T* ret, bool* is_global) const {
dan sinclairc2d97ae2020-04-03 02:35:23 +000078 for (auto iter = stack_.rbegin(); iter != stack_.rend(); ++iter) {
79 auto& map = *iter;
Ben Claytonf6866a22021-01-11 22:02:42 +000080 auto val = map.find(symbol);
Sarah Mashayekhid3107bd2020-08-11 20:44:06 +000081
dan sinclairc2d97ae2020-04-03 02:35:23 +000082 if (val != map.end()) {
83 if (ret) {
84 *ret = val->second;
85 }
Sarah Mashayekhid3107bd2020-08-11 20:44:06 +000086 if (is_global && iter == stack_.rend() - 1) {
87 *is_global = true;
88 }
dan sinclairc2d97ae2020-04-03 02:35:23 +000089 return true;
90 }
91 }
92 return false;
93 }
94
95 private:
Ben Claytonf6866a22021-01-11 22:02:42 +000096 std::vector<std::unordered_map<Symbol, T>> stack_;
dan sinclairc2d97ae2020-04-03 02:35:23 +000097};
98
99} // namespace tint
100
101#endif // SRC_SCOPE_STACK_H_