Coverage Report

Created: 2025-11-09 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libsass/src/environment.cpp
Line
Count
Source
1
#include "sass.hpp"
2
#include "ast.hpp"
3
#include "environment.hpp"
4
5
namespace Sass {
6
7
  template <typename T>
8
  Environment<T>::Environment(bool is_shadow)
9
6
  : local_frame_(environment_map<sass::string, T>()),
10
6
    parent_(0), is_shadow_(false)
11
6
  { }
12
  template <typename T>
13
  Environment<T>::Environment(Environment<T>* env, bool is_shadow)
14
8
  : local_frame_(environment_map<sass::string, T>()),
15
8
    parent_(env), is_shadow_(is_shadow)
16
8
  { }
17
  template <typename T>
18
  Environment<T>::Environment(Environment<T>& env, bool is_shadow)
19
0
  : local_frame_(environment_map<sass::string, T>()),
20
0
    parent_(&env), is_shadow_(is_shadow)
21
0
  { }
22
23
  // link parent to create a stack
24
  template <typename T>
25
0
  void Environment<T>::link(Environment& env) { parent_ = &env; }
26
  template <typename T>
27
0
  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
4
  {
34
4
    return !! parent_ && parent_->parent_;
35
4
  }
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
0
  {
44
0
    return parent_ && ! parent_->parent_;
45
0
  }
46
47
  template <typename T>
48
0
  environment_map<sass::string, T>& Environment<T>::local_frame() {
49
0
    return local_frame_;
50
0
  }
51
52
  template <typename T>
53
  bool Environment<T>::has_local(const sass::string& key) const
54
522
  { return local_frame_.find(key) != local_frame_.end(); }
55
56
  template <typename T> EnvResult
57
  Environment<T>::find_local(const sass::string& key)
58
2
  {
59
2
    auto end = local_frame_.end();
60
2
    auto it = local_frame_.find(key);
61
2
    return EnvResult(it, it != end);
62
2
  }
63
64
  template <typename T>
65
  T& Environment<T>::get_local(const sass::string& key)
66
522
  { return local_frame_[key]; }
67
68
  template <typename T>
69
  void Environment<T>::set_local(const sass::string& key, const T& val)
70
4
  {
71
4
    local_frame_[key] = val;
72
4
  }
73
  template <typename T>
74
  void Environment<T>::set_local(const sass::string& key, T&& val)
75
0
  {
76
0
    local_frame_[key] = val;
77
0
  }
78
79
  template <typename T>
80
  void Environment<T>::del_local(const sass::string& key)
81
0
  { local_frame_.erase(key); }
82
83
  template <typename T>
84
  Environment<T>* Environment<T>::global_env()
85
0
  {
86
0
    Environment* cur = this;
87
0
    while (cur->is_lexical()) {
88
0
      cur = cur->parent_;
89
0
    }
90
0
    return cur;
91
0
  }
92
93
  template <typename T>
94
  bool Environment<T>::has_global(const sass::string& key)
95
0
  { return global_env()->has(key); }
96
97
  template <typename T>
98
  T& Environment<T>::get_global(const sass::string& key)
99
0
  { return (*global_env())[key]; }
100
101
  template <typename T>
102
  void Environment<T>::set_global(const sass::string& key, const T& val)
103
0
  {
104
0
    global_env()->local_frame_[key] = val;
105
0
  }
106
  template <typename T>
107
  void Environment<T>::set_global(const sass::string& key, T&& val)
108
0
  {
109
0
    global_env()->local_frame_[key] = val;
110
0
  }
111
112
  template <typename T>
113
  void Environment<T>::del_global(const sass::string& key)
114
0
  { global_env()->local_frame_.erase(key); }
115
116
  template <typename T>
117
  Environment<T>* Environment<T>::lexical_env(const sass::string& key)
118
0
  {
119
0
    Environment* cur = this;
120
0
    while (cur) {
121
0
      if (cur->has_local(key)) {
122
0
        return cur;
123
0
      }
124
0
      cur = cur->parent_;
125
0
    }
126
0
    return this;
127
0
  }
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
0
  {
135
0
    auto cur = this;
136
0
    while (cur->is_lexical()) {
137
0
      if (cur->has_local(key)) return true;
138
0
      cur = cur->parent_;
139
0
    }
140
0
    return false;
141
0
  }
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
0
  {
149
0
    Environment<T>* cur = this;
150
0
    bool shadow = false;
151
0
    while ((cur && cur->is_lexical()) || shadow) {
152
0
      EnvResult rv(cur->find_local(key));
153
0
      if (rv.found) {
154
0
        rv.it->second = val;
155
0
        return;
156
0
      }
157
0
      shadow = cur->is_shadow();
158
0
      cur = cur->parent_;
159
0
    }
160
0
    set_local(key, val);
161
0
  }
162
  // this one moves the value
163
  template <typename T>
164
  void Environment<T>::set_lexical(const sass::string& key, T&& val)
165
4
  {
166
4
    Environment<T>* cur = this;
167
4
    bool shadow = false;
168
4
    while ((cur && cur->is_lexical()) || shadow) {
169
0
      EnvResult rv(cur->find_local(key));
170
0
      if (rv.found) {
171
0
        rv.it->second = val;
172
0
        return;
173
0
      }
174
0
      shadow = cur->is_shadow();
175
0
      cur = cur->parent_;
176
0
    }
177
4
    set_local(key, val);
178
4
  }
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
0
  {
185
0
    auto cur = this;
186
0
    while (cur) {
187
0
      if (cur->has_local(key)) {
188
0
        return true;
189
0
      }
190
0
      cur = cur->parent_;
191
0
    }
192
0
    return false;
193
0
  }
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
1
  {
200
1
    auto cur = this;
201
2
    while (true) {
202
2
      EnvResult rv(cur->find_local(key));
203
2
      if (rv.found) return rv;
204
2
      cur = cur->parent_;
205
2
      if (!cur) return rv;
206
2
    }
207
1
  };
208
209
  // use array access for getter and setter functions
210
  template <typename T>
211
  T& Environment<T>::get(const sass::string& key)
212
0
  {
213
0
    auto cur = this;
214
0
    while (cur) {
215
0
      if (cur->has_local(key)) {
216
0
        return cur->get_local(key);
217
0
      }
218
0
      cur = cur->parent_;
219
0
    }
220
0
    return get_local(key);
221
0
  }
222
223
  // use array access for getter and setter functions
224
  template <typename T>
225
  T& Environment<T>::operator[](const sass::string& key)
226
522
  {
227
522
    auto cur = this;
228
1.04k
    while (cur) {
229
522
      if (cur->has_local(key)) {
230
0
        return cur->get_local(key);
231
0
      }
232
522
      cur = cur->parent_;
233
522
    }
234
522
    return get_local(key);
235
522
  }
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