3 #include "environment.hpp"
8 Environment<T>::Environment(bool is_shadow)
9 : local_frame_(std::map<std::string, T>()),
10 parent_(0), is_shadow_(false)
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)
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)
23 // link parent to create a stack
25 void Environment<T>::link(Environment& env) { parent_ = &env; }
27 void Environment<T>::link(Environment* env) { parent_ = env; }
29 // this is used to find the global frame
30 // which is the second last on the stack
32 bool Environment<T>::is_lexical() const
34 return !! parent_ && parent_->parent_;
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
42 bool Environment<T>::is_global() const
44 return parent_ && ! parent_->parent_;
48 std::map<std::string, T>& Environment<T>::local_frame() {
53 bool Environment<T>::has_local(const std::string& key) const
54 { return local_frame_.find(key) != local_frame_.end(); }
57 T& Environment<T>::get_local(const std::string& key)
58 { return local_frame_[key]; }
61 void Environment<T>::set_local(const std::string& key, T val)
63 local_frame_[key] = val;
67 void Environment<T>::del_local(const std::string& key)
68 { local_frame_.erase(key); }
71 Environment<T>* Environment<T>::global_env()
73 Environment* cur = this;
74 while (cur->is_lexical()) {
81 bool Environment<T>::has_global(const std::string& key)
82 { return global_env()->has(key); }
85 T& Environment<T>::get_global(const std::string& key)
86 { return (*global_env())[key]; }
89 void Environment<T>::set_global(const std::string& key, T val)
91 global_env()->local_frame_[key] = val;
95 void Environment<T>::del_global(const std::string& key)
96 { global_env()->local_frame_.erase(key); }
99 Environment<T>* Environment<T>::lexical_env(const std::string& key)
101 Environment* cur = this;
103 if (cur->has_local(key)) {
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
118 while (cur->is_lexical()) {
119 if (cur->has_local(key)) return true;
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)
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);
137 shadow = cur->is_shadow();
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
150 if (cur->has_local(key)) {
158 // use array access for getter and setter functions
159 template <typename T>
160 T& Environment<T>::operator[](const std::string& key)
164 if (cur->has_local(key)) {
165 return cur->get_local(key);
169 return get_local(key);
173 template <typename T>
174 size_t Environment<T>::print(std::string prefix)
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;
191 // compile implementation for AST_Node
192 template class Environment<AST_Node_Obj>;