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