|
Packit Service |
7770af |
#include "sass.hpp"
|
|
Packit Service |
7770af |
#include "ast.hpp"
|
|
Packit Service |
7770af |
#include "environment.hpp"
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
namespace Sass {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
Environment<T>::Environment(bool is_shadow)
|
|
Packit Service |
7770af |
: local_frame_(environment_map<std::string, T>()),
|
|
Packit Service |
7770af |
parent_(0), is_shadow_(false)
|
|
Packit Service |
7770af |
{ }
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
Environment<T>::Environment(Environment<T>* env, bool is_shadow)
|
|
Packit Service |
7770af |
: local_frame_(environment_map<std::string, T>()),
|
|
Packit Service |
7770af |
parent_(env), is_shadow_(is_shadow)
|
|
Packit Service |
7770af |
{ }
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
Environment<T>::Environment(Environment<T>& env, bool is_shadow)
|
|
Packit Service |
7770af |
: local_frame_(environment_map<std::string, T>()),
|
|
Packit Service |
7770af |
parent_(&env), is_shadow_(is_shadow)
|
|
Packit Service |
7770af |
{ }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// link parent to create a stack
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::link(Environment& env) { parent_ = &env; }
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::link(Environment* env) { parent_ = env; }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// this is used to find the global frame
|
|
Packit Service |
7770af |
// which is the second last on the stack
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
bool Environment<T>::is_lexical() const
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return !! parent_ && parent_->parent_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// only match the real root scope
|
|
Packit Service |
7770af |
// there is still a parent around
|
|
Packit Service |
7770af |
// not sure what it is actually use for
|
|
Packit Service |
7770af |
// I guess we store functions etc. there
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
bool Environment<T>::is_global() const
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return parent_ && ! parent_->parent_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
environment_map<std::string, T>& Environment<T>::local_frame() {
|
|
Packit Service |
7770af |
return local_frame_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
bool Environment<T>::has_local(const std::string& key) const
|
|
Packit Service |
7770af |
{ return local_frame_.find(key) != local_frame_.end(); }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T> EnvResult
|
|
Packit Service |
7770af |
Environment<T>::find_local(const std::string& key)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
auto end = local_frame_.end();
|
|
Packit Service |
7770af |
auto it = local_frame_.find(key);
|
|
Packit Service |
7770af |
return EnvResult(it, it != end);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
T& Environment<T>::get_local(const std::string& key)
|
|
Packit Service |
7770af |
{ return local_frame_[key]; }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::set_local(const std::string& key, const T& val)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
local_frame_[key] = val;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::set_local(const std::string& key, T&& val)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
local_frame_[key] = val;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::del_local(const std::string& key)
|
|
Packit Service |
7770af |
{ local_frame_.erase(key); }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
Environment<T>* Environment<T>::global_env()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Environment* cur = this;
|
|
Packit Service |
7770af |
while (cur->is_lexical()) {
|
|
Packit Service |
7770af |
cur = cur->parent_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return cur;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
bool Environment<T>::has_global(const std::string& key)
|
|
Packit Service |
7770af |
{ return global_env()->has(key); }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
T& Environment<T>::get_global(const std::string& key)
|
|
Packit Service |
7770af |
{ return (*global_env())[key]; }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::set_global(const std::string& key, const T& val)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
global_env()->local_frame_[key] = val;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::set_global(const std::string& key, T&& val)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
global_env()->local_frame_[key] = val;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::del_global(const std::string& key)
|
|
Packit Service |
7770af |
{ global_env()->local_frame_.erase(key); }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
Environment<T>* Environment<T>::lexical_env(const std::string& key)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Environment* cur = this;
|
|
Packit Service |
7770af |
while (cur) {
|
|
Packit Service |
7770af |
if (cur->has_local(key)) {
|
|
Packit Service |
7770af |
return cur;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
cur = cur->parent_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return this;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// see if we have a lexical variable
|
|
Packit Service |
7770af |
// move down the stack but stop before we
|
|
Packit Service |
7770af |
// reach the global frame (is not included)
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
bool Environment<T>::has_lexical(const std::string& key) const
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
auto cur = this;
|
|
Packit Service |
7770af |
while (cur->is_lexical()) {
|
|
Packit Service |
7770af |
if (cur->has_local(key)) return true;
|
|
Packit Service |
7770af |
cur = cur->parent_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return false;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// see if we have a lexical we could update
|
|
Packit Service |
7770af |
// either update already existing lexical value
|
|
Packit Service |
7770af |
// or if flag is set, we create one if no lexical found
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::set_lexical(const std::string& key, const T& val)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Environment<T>* cur = this;
|
|
Packit Service |
7770af |
bool shadow = false;
|
|
Packit Service |
7770af |
while ((cur && cur->is_lexical()) || shadow) {
|
|
Packit Service |
7770af |
EnvResult rv(cur->find_local(key));
|
|
Packit Service |
7770af |
if (rv.found) {
|
|
Packit Service |
7770af |
rv.it->second = val;
|
|
Packit Service |
7770af |
return;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
shadow = cur->is_shadow();
|
|
Packit Service |
7770af |
cur = cur->parent_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
set_local(key, val);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// this one moves the value
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
void Environment<T>::set_lexical(const std::string& key, T&& val)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Environment<T>* cur = this;
|
|
Packit Service |
7770af |
bool shadow = false;
|
|
Packit Service |
7770af |
while ((cur && cur->is_lexical()) || shadow) {
|
|
Packit Service |
7770af |
EnvResult rv(cur->find_local(key));
|
|
Packit Service |
7770af |
if (rv.found) {
|
|
Packit Service |
7770af |
rv.it->second = val;
|
|
Packit Service |
7770af |
return;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
shadow = cur->is_shadow();
|
|
Packit Service |
7770af |
cur = cur->parent_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
set_local(key, val);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// look on the full stack for key
|
|
Packit Service |
7770af |
// include all scopes available
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
bool Environment<T>::has(const std::string& key) const
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
auto cur = this;
|
|
Packit Service |
7770af |
while (cur) {
|
|
Packit Service |
7770af |
if (cur->has_local(key)) {
|
|
Packit Service |
7770af |
return true;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
cur = cur->parent_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return false;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// look on the full stack for key
|
|
Packit Service |
7770af |
// include all scopes available
|
|
Packit Service |
7770af |
template <typename T> EnvResult
|
|
Packit Service |
7770af |
Environment<T>::find(const std::string& key)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
auto cur = this;
|
|
Packit Service |
7770af |
while (true) {
|
|
Packit Service |
7770af |
EnvResult rv(cur->find_local(key));
|
|
Packit Service |
7770af |
if (rv.found) return rv;
|
|
Packit Service |
7770af |
cur = cur->parent_;
|
|
Packit Service |
7770af |
if (!cur) return rv;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
};
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// use array access for getter and setter functions
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
T& Environment<T>::operator[](const std::string& key)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
auto cur = this;
|
|
Packit Service |
7770af |
while (cur) {
|
|
Packit Service |
7770af |
if (cur->has_local(key)) {
|
|
Packit Service |
7770af |
return cur->get_local(key);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
cur = cur->parent_;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return get_local(key);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
#ifdef DEBUG
|
|
Packit Service |
7770af |
template <typename T>
|
|
Packit Service |
7770af |
size_t Environment<T>::print(std::string prefix)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
size_t indent = 0;
|
|
Packit Service |
7770af |
if (parent_) indent = parent_->print(prefix) + 1;
|
|
Packit Service |
7770af |
std::cerr << prefix << std::string(indent, ' ') << "== " << this << std::endl;
|
|
Packit Service |
7770af |
for (typename environment_map<std::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
|
|
Packit Service |
7770af |
if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) {
|
|
Packit Service |
7770af |
std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second;
|
|
Packit Service |
7770af |
if (Value_Ptr val = Cast<Value>(i->second))
|
|
Packit Service |
7770af |
{ std::cerr << " : " << val->to_string(); }
|
|
Packit Service |
7770af |
std::cerr << std::endl;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return indent ;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
#endif
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// compile implementation for AST_Node
|
|
Packit Service |
7770af |
template class Environment<AST_Node_Obj>;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|