1#include "sass.hpp"
2#include "ast.hpp"
3#include "environment.hpp"
4
5namespace Sass {
6
7 template <typename T>
8 Environment<T>::Environment(bool is_shadow)
9 : local_frame_(environment_map<sass::string, T>()),
10 parent_(0), is_shadow_(false)
11 { }
12 template <typename T>
13 Environment<T>::Environment(Environment<T>* env, bool is_shadow)
14 : local_frame_(environment_map<sass::string, T>()),
15 parent_(env), is_shadow_(is_shadow)
16 { }
17 template <typename T>
18 Environment<T>::Environment(Environment<T>& env, bool is_shadow)
19 : local_frame_(environment_map<sass::string, T>()),
20 parent_(&env), is_shadow_(is_shadow)
21 { }
22
23 // link parent to create a stack
24 template <typename T>
25 void Environment<T>::link(Environment& env) { parent_ = &env; }
26 template <typename T>
27 void Environment<T>::link(Environment* env) { parent_ = env; }
28
29 // this is used to find the global frame
30 // which is the second last on the stack
31 template <typename T>
32 bool Environment<T>::is_lexical() const
33 {
34 return !! parent_ && parent_->parent_;
35 }
36
37 // only match the real root scope
38 // there is still a parent around
39 // not sure what it is actually use for
40 // I guess we store functions etc. there
41 template <typename T>
42 bool Environment<T>::is_global() const
43 {
44 return parent_ && ! parent_->parent_;
45 }
46
47 template <typename T>
48 environment_map<sass::string, T>& Environment<T>::local_frame() {
49 return local_frame_;
50 }
51
52 template <typename T>
53 bool Environment<T>::has_local(const sass::string& key) const
54 { return local_frame_.find(key) != local_frame_.end(); }
55
56 template <typename T> EnvResult
57 Environment<T>::find_local(const sass::string& key)
58 {
59 auto end = local_frame_.end();
60 auto it = local_frame_.find(key);
61 return EnvResult(it, it != end);
62 }
63
64 template <typename T>
65 T& Environment<T>::get_local(const sass::string& key)
66 { return local_frame_[key]; }
67
68 template <typename T>
69 void Environment<T>::set_local(const sass::string& key, const T& val)
70 {
71 local_frame_[key] = val;
72 }
73 template <typename T>
74 void Environment<T>::set_local(const sass::string& key, T&& val)
75 {
76 local_frame_[key] = val;
77 }
78
79 template <typename T>
80 void Environment<T>::del_local(const sass::string& key)
81 { local_frame_.erase(key); }
82
83 template <typename T>
84 Environment<T>* Environment<T>::global_env()
85 {
86 Environment* cur = this;
87 while (cur->is_lexical()) {
88 cur = cur->parent_;
89 }
90 return cur;
91 }
92
93 template <typename T>
94 bool Environment<T>::has_global(const sass::string& key)
95 { return global_env()->has(key); }
96
97 template <typename T>
98 T& Environment<T>::get_global(const sass::string& key)
99 { return (*global_env())[key]; }
100
101 template <typename T>
102 void Environment<T>::set_global(const sass::string& key, const T& val)
103 {
104 global_env()->local_frame_[key] = val;
105 }
106 template <typename T>
107 void Environment<T>::set_global(const sass::string& key, T&& val)
108 {
109 global_env()->local_frame_[key] = val;
110 }
111
112 template <typename T>
113 void Environment<T>::del_global(const sass::string& key)
114 { global_env()->local_frame_.erase(key); }
115
116 template <typename T>
117 Environment<T>* Environment<T>::lexical_env(const sass::string& key)
118 {
119 Environment* cur = this;
120 while (cur) {
121 if (cur->has_local(key)) {
122 return cur;
123 }
124 cur = cur->parent_;
125 }
126 return this;
127 }
128
129 // see if we have a lexical variable
130 // move down the stack but stop before we
131 // reach the global frame (is not included)
132 template <typename T>
133 bool Environment<T>::has_lexical(const sass::string& key) const
134 {
135 auto cur = this;
136 while (cur->is_lexical()) {
137 if (cur->has_local(key)) return true;
138 cur = cur->parent_;
139 }
140 return false;
141 }
142
143 // see if we have a lexical we could update
144 // either update already existing lexical value
145 // or if flag is set, we create one if no lexical found
146 template <typename T>
147 void Environment<T>::set_lexical(const sass::string& key, const T& val)
148 {
149 Environment<T>* cur = this;
150 bool shadow = false;
151 while ((cur && cur->is_lexical()) || shadow) {
152 EnvResult rv(cur->find_local(key));
153 if (rv.found) {
154 rv.it->second = val;
155 return;
156 }
157 shadow = cur->is_shadow();
158 cur = cur->parent_;
159 }
160 set_local(key, val);
161 }
162 // this one moves the value
163 template <typename T>
164 void Environment<T>::set_lexical(const sass::string& key, T&& val)
165 {
166 Environment<T>* cur = this;
167 bool shadow = false;
168 while ((cur && cur->is_lexical()) || shadow) {
169 EnvResult rv(cur->find_local(key));
170 if (rv.found) {
171 rv.it->second = val;
172 return;
173 }
174 shadow = cur->is_shadow();
175 cur = cur->parent_;
176 }
177 set_local(key, val);
178 }
179
180 // look on the full stack for key
181 // include all scopes available
182 template <typename T>
183 bool Environment<T>::has(const sass::string& key) const
184 {
185 auto cur = this;
186 while (cur) {
187 if (cur->has_local(key)) {
188 return true;
189 }
190 cur = cur->parent_;
191 }
192 return false;
193 }
194
195 // look on the full stack for key
196 // include all scopes available
197 template <typename T> EnvResult
198 Environment<T>::find(const sass::string& key)
199 {
200 auto cur = this;
201 while (true) {
202 EnvResult rv(cur->find_local(key));
203 if (rv.found) return rv;
204 cur = cur->parent_;
205 if (!cur) return rv;
206 }
207 };
208
209 // use array access for getter and setter functions
210 template <typename T>
211 T& Environment<T>::get(const sass::string& key)
212 {
213 auto cur = this;
214 while (cur) {
215 if (cur->has_local(key)) {
216 return cur->get_local(key);
217 }
218 cur = cur->parent_;
219 }
220 return get_local(key);
221 }
222
223 // use array access for getter and setter functions
224 template <typename T>
225 T& Environment<T>::operator[](const sass::string& key)
226 {
227 auto cur = this;
228 while (cur) {
229 if (cur->has_local(key)) {
230 return cur->get_local(key);
231 }
232 cur = cur->parent_;
233 }
234 return get_local(key);
235 }
236/*
237 #ifdef DEBUG
238 template <typename T>
239 size_t Environment<T>::print(sass::string prefix)
240 {
241 size_t indent = 0;
242 if (parent_) indent = parent_->print(prefix) + 1;
243 std::cerr << prefix << sass::string(indent, ' ') << "== " << this << std::endl;
244 for (typename environment_map<sass::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
245 if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) {
246 std::cerr << prefix << sass::string(indent, ' ') << i->first << " " << i->second;
247 if (Value* val = Cast<Value>(i->second))
248 { std::cerr << " : " << val->to_string(); }
249 std::cerr << std::endl;
250 }
251 }
252 return indent ;
253 }
254 #endif
255*/
256 // compile implementation for AST_Node
257 template class Environment<AST_Node_Obj>;
258
259}
260
261

source code of gtk/subprojects/libsass/src/environment.cpp