blob: e266886588255d767fccf90f139a1bf73fe94661 [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
dan sinclair795b6b52021-01-11 15:10:19 +000051 void set_global(const Symbol& symbol, T val) {
52 stack_[0][symbol.value()] = val;
Sarah Mashayekhid3107bd2020-08-11 20:44:06 +000053 }
54
dan sinclair795b6b52021-01-11 15:10:19 +000055 /// Sets variable into the top most scope of the stack
56 /// @param symbol the symbol of the variable
57 /// @param val the value
58 void set(const Symbol& symbol, T val) { stack_.back()[symbol.value()] = val; }
59
60 /// Checks for the given `symbol` in the stack
61 /// @param symbol the symbol to look for
62 /// @returns true if the stack contains `symbol`
63 bool has(const Symbol& symbol) const { return get(symbol, nullptr); }
64
65 /// Retrieves a given variable from the stack
66 /// @param symbol the symbol to look for
67 /// @param ret where to place the value
68 /// @returns true if the symbol was successfully found, false otherwise
69 bool get(const Symbol& symbol, T* ret) const {
70 return get(symbol, ret, nullptr);
71 }
72
73 /// Retrieves a given variable from the stack
74 /// @param symbol the symbol to look for
75 /// @param ret where to place the value
76 /// @param is_global set true if the symbol references a global variable
Sarah Mashayekhid3107bd2020-08-11 20:44:06 +000077 /// otherwise unchanged
dan sinclair795b6b52021-01-11 15:10:19 +000078 /// @returns true if the symbol was successfully found, false otherwise
79 bool get(const Symbol& symbol, T* ret, bool* is_global) const {
dan sinclairc2d97ae2020-04-03 02:35:23 +000080 for (auto iter = stack_.rbegin(); iter != stack_.rend(); ++iter) {
81 auto& map = *iter;
dan sinclair795b6b52021-01-11 15:10:19 +000082 auto val = map.find(symbol.value());
Sarah Mashayekhid3107bd2020-08-11 20:44:06 +000083
dan sinclairc2d97ae2020-04-03 02:35:23 +000084 if (val != map.end()) {
85 if (ret) {
86 *ret = val->second;
87 }
Sarah Mashayekhid3107bd2020-08-11 20:44:06 +000088 if (is_global && iter == stack_.rend() - 1) {
89 *is_global = true;
90 }
dan sinclairc2d97ae2020-04-03 02:35:23 +000091 return true;
92 }
93 }
94 return false;
95 }
96
97 private:
dan sinclair795b6b52021-01-11 15:10:19 +000098 std::vector<std::unordered_map<uint32_t, T>> stack_;
dan sinclairc2d97ae2020-04-03 02:35:23 +000099};
100
101} // namespace tint
102
103#endif // SRC_SCOPE_STACK_H_