Initial commit
[yaffs-website] / node_modules / node-sass / src / libsass / src / environment.cpp
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   : local_frame_(std::map<std::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_(std::map<std::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_(std::map<std::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   std::map<std::string, T>& Environment<T>::local_frame() {
49     return local_frame_;
50   }
51
52   template <typename T>
53   bool Environment<T>::has_local(const std::string& key) const
54   { return local_frame_.find(key) != local_frame_.end(); }
55
56   template <typename T>
57   T& Environment<T>::get_local(const std::string& key)
58   { return local_frame_[key]; }
59
60   template <typename T>
61   void Environment<T>::set_local(const std::string& key, T val)
62   {
63     local_frame_[key] = val;
64   }
65
66   template <typename T>
67   void Environment<T>::del_local(const std::string& key)
68   { local_frame_.erase(key); }
69
70   template <typename T>
71   Environment<T>* Environment<T>::global_env()
72   {
73     Environment* cur = this;
74     while (cur->is_lexical()) {
75       cur = cur->parent_;
76     }
77     return cur;
78   }
79
80   template <typename T>
81   bool Environment<T>::has_global(const std::string& key)
82   { return global_env()->has(key); }
83
84   template <typename T>
85   T& Environment<T>::get_global(const std::string& key)
86   { return (*global_env())[key]; }
87
88   template <typename T>
89   void Environment<T>::set_global(const std::string& key, T val)
90   {
91     global_env()->local_frame_[key] = val;
92   }
93
94   template <typename T>
95   void Environment<T>::del_global(const std::string& key)
96   { global_env()->local_frame_.erase(key); }
97
98   template <typename T>
99   Environment<T>* Environment<T>::lexical_env(const std::string& key)
100   {
101     Environment* cur = this;
102     while (cur) {
103       if (cur->has_local(key)) {
104         return cur;
105       }
106       cur = cur->parent_;
107     }
108     return this;
109   }
110
111   // see if we have a lexical variable
112   // move down the stack but stop before we
113   // reach the global frame (is not included)
114   template <typename T>
115   bool Environment<T>::has_lexical(const std::string& key) const
116   {
117     auto cur = this;
118     while (cur->is_lexical()) {
119       if (cur->has_local(key)) return true;
120       cur = cur->parent_;
121     }
122     return false;
123   }
124
125   // see if we have a lexical we could update
126   // either update already existing lexical value
127   // or if flag is set, we create one if no lexical found
128   template <typename T>
129   void Environment<T>::set_lexical(const std::string& key, T val)
130   {
131     auto cur = this; bool shadow = false;
132     while (cur->is_lexical() || shadow) {
133       if (cur->has_local(key)) {
134         cur->set_local(key, val);
135         return;
136       }
137       shadow = cur->is_shadow();
138       cur = cur->parent_;
139     }
140     set_local(key, val);
141   }
142
143   // look on the full stack for key
144   // include all scopes available
145   template <typename T>
146   bool Environment<T>::has(const std::string& key) const
147   {
148     auto cur = this;
149     while (cur) {
150       if (cur->has_local(key)) {
151         return true;
152       }
153       cur = cur->parent_;
154     }
155     return false;
156   }
157
158   // use array access for getter and setter functions
159   template <typename T>
160   T& Environment<T>::operator[](const std::string& key)
161   {
162     auto cur = this;
163     while (cur) {
164       if (cur->has_local(key)) {
165         return cur->get_local(key);
166       }
167       cur = cur->parent_;
168     }
169     return get_local(key);
170   }
171
172   #ifdef DEBUG
173   template <typename T>
174   size_t Environment<T>::print(std::string prefix)
175   {
176     size_t indent = 0;
177     if (parent_) indent = parent_->print(prefix) + 1;
178     std::cerr << prefix << std::string(indent, ' ') << "== " << this << std::endl;
179     for (typename std::map<std::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
180       if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) {
181         std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second;
182         if (Value_Ptr val = Cast<Value>(i->second))
183         { std::cerr << " : " << val->to_string(); }
184         std::cerr << std::endl;
185       }
186     }
187     return indent ;
188   }
189   #endif
190
191   // compile implementation for AST_Node
192   template class Environment<AST_Node_Obj>;
193
194 }
195