Blame src/environment.cpp

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