environment.hpp
3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#ifndef SASS_ENVIRONMENT_H
#define SASS_ENVIRONMENT_H
#include <string>
#include "ast_fwd_decl.hpp"
#include "ast_def_macros.hpp"
namespace Sass {
typedef environment_map<std::string, AST_Node_Obj>::iterator EnvIter;
class EnvResult {
public:
EnvIter it;
bool found;
public:
EnvResult(EnvIter it, bool found)
: it(it), found(found) {}
};
template <typename T>
class Environment {
// TODO: test with map
environment_map<std::string, T> local_frame_;
ADD_PROPERTY(Environment*, parent)
ADD_PROPERTY(bool, is_shadow)
public:
Environment(bool is_shadow = false);
Environment(Environment* env, bool is_shadow = false);
Environment(Environment& env, bool is_shadow = false);
// link parent to create a stack
void link(Environment& env);
void link(Environment* env);
// this is used to find the global frame
// which is the second last on the stack
bool is_lexical() const;
// only match the real root scope
// there is still a parent around
// not sure what it is actually use for
// I guess we store functions etc. there
bool is_global() const;
// scope operates on the current frame
environment_map<std::string, T>& local_frame();
bool has_local(const std::string& key) const;
EnvResult find_local(const std::string& key);
T& get_local(const std::string& key);
// set variable on the current frame
void set_local(const std::string& key, const T& val);
void set_local(const std::string& key, T&& val);
void del_local(const std::string& key);
// global operates on the global frame
// which is the second last on the stack
Environment* global_env();
// get the env where the variable already exists
// if it does not yet exist, we return current env
Environment* lexical_env(const std::string& key);
bool has_global(const std::string& key);
T& get_global(const std::string& key);
// set a variable on the global frame
void set_global(const std::string& key, const T& val);
void set_global(const std::string& key, T&& val);
void del_global(const std::string& key);
// see if we have a lexical variable
// move down the stack but stop before we
// reach the global frame (is not included)
bool has_lexical(const std::string& key) const;
// see if we have a lexical we could update
// either update already existing lexical value
// or we create a new one on the current frame
void set_lexical(const std::string& key, T&& val);
void set_lexical(const std::string& key, const T& val);
// look on the full stack for key
// include all scopes available
bool has(const std::string& key) const;
// look on the full stack for key
// include all scopes available
EnvResult find(const std::string& key);
// use array access for getter and setter functions
T& operator[](const std::string& key);
#ifdef DEBUG
size_t print(std::string prefix = "");
#endif
};
// define typedef for our use case
typedef Environment<AST_Node_Obj> Env;
}
#endif