1 | #ifndef SASS_OPERATION_H |
2 | #define SASS_OPERATION_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 | // base classes to implement curiously recurring template pattern (CRTP) |
9 | // https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern |
10 | |
11 | #include <typeinfo> |
12 | #include <stdexcept> |
13 | |
14 | #include "ast_fwd_decl.hpp" |
15 | #include "ast_def_macros.hpp" |
16 | |
17 | namespace Sass { |
18 | |
19 | #define ATTACH_ABSTRACT_CRTP_PERFORM_METHODS()\ |
20 | virtual void perform(Operation<void>* op) = 0; \ |
21 | virtual Value* perform(Operation<Value*>* op) = 0; \ |
22 | virtual sass::string perform(Operation<sass::string>* op) = 0; \ |
23 | virtual AST_Node* perform(Operation<AST_Node*>* op) = 0; \ |
24 | virtual Selector* perform(Operation<Selector*>* op) = 0; \ |
25 | virtual Statement* perform(Operation<Statement*>* op) = 0; \ |
26 | virtual Expression* perform(Operation<Expression*>* op) = 0; \ |
27 | virtual union Sass_Value* perform(Operation<union Sass_Value*>* op) = 0; \ |
28 | virtual SupportsCondition* perform(Operation<SupportsCondition*>* op) = 0; \ |
29 | |
30 | // you must add operators to every class |
31 | // ensures `this` of actual instance type |
32 | // we therefore call the specific operator |
33 | // they are virtual so most specific is used |
34 | #define ATTACH_CRTP_PERFORM_METHODS()\ |
35 | virtual void perform(Operation<void>* op) override { return (*op)(this); } \ |
36 | virtual Value* perform(Operation<Value*>* op) override { return (*op)(this); } \ |
37 | virtual sass::string perform(Operation<sass::string>* op) override { return (*op)(this); } \ |
38 | virtual AST_Node* perform(Operation<AST_Node*>* op) override { return (*op)(this); } \ |
39 | virtual Selector* perform(Operation<Selector*>* op) override { return (*op)(this); } \ |
40 | virtual Statement* perform(Operation<Statement*>* op) override { return (*op)(this); } \ |
41 | virtual Expression* perform(Operation<Expression*>* op) override { return (*op)(this); } \ |
42 | virtual union Sass_Value* perform(Operation<union Sass_Value*>* op) override { return (*op)(this); } \ |
43 | virtual SupportsCondition* perform(Operation<SupportsCondition*>* op) override { return (*op)(this); } \ |
44 | |
45 | template<typename T> |
46 | class Operation { |
47 | public: |
48 | virtual T operator()(AST_Node* x) = 0; |
49 | // statements |
50 | virtual T operator()(Block* x) = 0; |
51 | virtual T operator()(StyleRule* x) = 0; |
52 | virtual T operator()(Bubble* x) = 0; |
53 | virtual T operator()(Trace* x) = 0; |
54 | virtual T operator()(SupportsRule* x) = 0; |
55 | virtual T operator()(MediaRule* x) = 0; |
56 | virtual T operator()(CssMediaRule* x) = 0; |
57 | virtual T operator()(CssMediaQuery* x) = 0; |
58 | virtual T operator()(AtRootRule* x) = 0; |
59 | virtual T operator()(AtRule* x) = 0; |
60 | virtual T operator()(Keyframe_Rule* x) = 0; |
61 | virtual T operator()(Declaration* x) = 0; |
62 | virtual T operator()(Assignment* x) = 0; |
63 | virtual T operator()(Import* x) = 0; |
64 | virtual T operator()(Import_Stub* x) = 0; |
65 | virtual T operator()(WarningRule* x) = 0; |
66 | virtual T operator()(ErrorRule* x) = 0; |
67 | virtual T operator()(DebugRule* x) = 0; |
68 | virtual T (Comment* x) = 0; |
69 | virtual T operator()(If* x) = 0; |
70 | virtual T operator()(ForRule* x) = 0; |
71 | virtual T operator()(EachRule* x) = 0; |
72 | virtual T operator()(WhileRule* x) = 0; |
73 | virtual T operator()(Return* x) = 0; |
74 | virtual T operator()(Content* x) = 0; |
75 | virtual T operator()(ExtendRule* x) = 0; |
76 | virtual T operator()(Definition* x) = 0; |
77 | virtual T operator()(Mixin_Call* x) = 0; |
78 | // expressions |
79 | virtual T operator()(Null* x) = 0; |
80 | virtual T operator()(List* x) = 0; |
81 | virtual T operator()(Map* x) = 0; |
82 | virtual T operator()(Function* x) = 0; |
83 | virtual T operator()(Binary_Expression* x) = 0; |
84 | virtual T operator()(Unary_Expression* x) = 0; |
85 | virtual T operator()(Function_Call* x) = 0; |
86 | virtual T operator()(Custom_Warning* x) = 0; |
87 | virtual T operator()(Custom_Error* x) = 0; |
88 | virtual T operator()(Variable* x) = 0; |
89 | virtual T operator()(Number* x) = 0; |
90 | virtual T operator()(Color* x) = 0; |
91 | virtual T operator()(Color_RGBA* x) = 0; |
92 | virtual T operator()(Color_HSLA* x) = 0; |
93 | virtual T operator()(Boolean* x) = 0; |
94 | virtual T operator()(String_Schema* x) = 0; |
95 | virtual T operator()(String_Quoted* x) = 0; |
96 | virtual T operator()(String_Constant* x) = 0; |
97 | virtual T operator()(SupportsCondition* x) = 0; |
98 | virtual T operator()(SupportsOperation* x) = 0; |
99 | virtual T operator()(SupportsNegation* x) = 0; |
100 | virtual T operator()(SupportsDeclaration* x) = 0; |
101 | virtual T operator()(Supports_Interpolation* x) = 0; |
102 | virtual T operator()(Media_Query* x) = 0; |
103 | virtual T operator()(Media_Query_Expression* x) = 0; |
104 | virtual T operator()(At_Root_Query* x) = 0; |
105 | virtual T operator()(Parent_Reference* x) = 0; |
106 | // parameters and arguments |
107 | virtual T operator()(Parameter* x) = 0; |
108 | virtual T operator()(Parameters* x) = 0; |
109 | virtual T operator()(Argument* x) = 0; |
110 | virtual T operator()(Arguments* x) = 0; |
111 | // selectors |
112 | virtual T operator()(Selector_Schema* x) = 0; |
113 | virtual T operator()(PlaceholderSelector* x) = 0; |
114 | virtual T operator()(TypeSelector* x) = 0; |
115 | virtual T operator()(ClassSelector* x) = 0; |
116 | virtual T operator()(IDSelector* x) = 0; |
117 | virtual T operator()(AttributeSelector* x) = 0; |
118 | virtual T operator()(PseudoSelector* x) = 0; |
119 | virtual T operator()(SelectorComponent* x) = 0; |
120 | virtual T operator()(SelectorCombinator* x) = 0; |
121 | virtual T operator()(CompoundSelector* x) = 0; |
122 | virtual T operator()(ComplexSelector* x) = 0; |
123 | virtual T operator()(SelectorList* x) = 0; |
124 | |
125 | }; |
126 | |
127 | // example: Operation_CRTP<Expression*, Eval> |
128 | // T is the base return type of all visitors |
129 | // D is the class derived visitor class |
130 | // normally you want to implement all operators |
131 | template <typename T, typename D> |
132 | class Operation_CRTP : public Operation<T> { |
133 | public: |
134 | T operator()(AST_Node* x) { return static_cast<D*>(this)->fallback(x); } |
135 | // statements |
136 | T operator()(Block* x) { return static_cast<D*>(this)->fallback(x); } |
137 | T operator()(StyleRule* x) { return static_cast<D*>(this)->fallback(x); } |
138 | T operator()(Bubble* x) { return static_cast<D*>(this)->fallback(x); } |
139 | T operator()(Trace* x) { return static_cast<D*>(this)->fallback(x); } |
140 | T operator()(SupportsRule* x) { return static_cast<D*>(this)->fallback(x); } |
141 | T operator()(MediaRule* x) { return static_cast<D*>(this)->fallback(x); } |
142 | T operator()(CssMediaRule* x) { return static_cast<D*>(this)->fallback(x); } |
143 | T operator()(CssMediaQuery* x) { return static_cast<D*>(this)->fallback(x); } |
144 | T operator()(AtRootRule* x) { return static_cast<D*>(this)->fallback(x); } |
145 | T operator()(AtRule* x) { return static_cast<D*>(this)->fallback(x); } |
146 | T operator()(Keyframe_Rule* x) { return static_cast<D*>(this)->fallback(x); } |
147 | T operator()(Declaration* x) { return static_cast<D*>(this)->fallback(x); } |
148 | T operator()(Assignment* x) { return static_cast<D*>(this)->fallback(x); } |
149 | T operator()(Import* x) { return static_cast<D*>(this)->fallback(x); } |
150 | T operator()(Import_Stub* x) { return static_cast<D*>(this)->fallback(x); } |
151 | T operator()(WarningRule* x) { return static_cast<D*>(this)->fallback(x); } |
152 | T operator()(ErrorRule* x) { return static_cast<D*>(this)->fallback(x); } |
153 | T operator()(DebugRule* x) { return static_cast<D*>(this)->fallback(x); } |
154 | T (Comment* x) { return static_cast<D*>(this)->fallback(x); } |
155 | T operator()(If* x) { return static_cast<D*>(this)->fallback(x); } |
156 | T operator()(ForRule* x) { return static_cast<D*>(this)->fallback(x); } |
157 | T operator()(EachRule* x) { return static_cast<D*>(this)->fallback(x); } |
158 | T operator()(WhileRule* x) { return static_cast<D*>(this)->fallback(x); } |
159 | T operator()(Return* x) { return static_cast<D*>(this)->fallback(x); } |
160 | T operator()(Content* x) { return static_cast<D*>(this)->fallback(x); } |
161 | T operator()(ExtendRule* x) { return static_cast<D*>(this)->fallback(x); } |
162 | T operator()(Definition* x) { return static_cast<D*>(this)->fallback(x); } |
163 | T operator()(Mixin_Call* x) { return static_cast<D*>(this)->fallback(x); } |
164 | // expressions |
165 | T operator()(Null* x) { return static_cast<D*>(this)->fallback(x); } |
166 | T operator()(List* x) { return static_cast<D*>(this)->fallback(x); } |
167 | T operator()(Map* x) { return static_cast<D*>(this)->fallback(x); } |
168 | T operator()(Function* x) { return static_cast<D*>(this)->fallback(x); } |
169 | T operator()(Binary_Expression* x) { return static_cast<D*>(this)->fallback(x); } |
170 | T operator()(Unary_Expression* x) { return static_cast<D*>(this)->fallback(x); } |
171 | T operator()(Function_Call* x) { return static_cast<D*>(this)->fallback(x); } |
172 | T operator()(Custom_Warning* x) { return static_cast<D*>(this)->fallback(x); } |
173 | T operator()(Custom_Error* x) { return static_cast<D*>(this)->fallback(x); } |
174 | T operator()(Variable* x) { return static_cast<D*>(this)->fallback(x); } |
175 | T operator()(Number* x) { return static_cast<D*>(this)->fallback(x); } |
176 | T operator()(Color* x) { return static_cast<D*>(this)->fallback(x); } |
177 | T operator()(Color_RGBA* x) { return static_cast<D*>(this)->fallback(x); } |
178 | T operator()(Color_HSLA* x) { return static_cast<D*>(this)->fallback(x); } |
179 | T operator()(Boolean* x) { return static_cast<D*>(this)->fallback(x); } |
180 | T operator()(String_Schema* x) { return static_cast<D*>(this)->fallback(x); } |
181 | T operator()(String_Constant* x) { return static_cast<D*>(this)->fallback(x); } |
182 | T operator()(String_Quoted* x) { return static_cast<D*>(this)->fallback(x); } |
183 | T operator()(SupportsCondition* x) { return static_cast<D*>(this)->fallback(x); } |
184 | T operator()(SupportsOperation* x) { return static_cast<D*>(this)->fallback(x); } |
185 | T operator()(SupportsNegation* x) { return static_cast<D*>(this)->fallback(x); } |
186 | T operator()(SupportsDeclaration* x) { return static_cast<D*>(this)->fallback(x); } |
187 | T operator()(Supports_Interpolation* x) { return static_cast<D*>(this)->fallback(x); } |
188 | T operator()(Media_Query* x) { return static_cast<D*>(this)->fallback(x); } |
189 | T operator()(Media_Query_Expression* x) { return static_cast<D*>(this)->fallback(x); } |
190 | T operator()(At_Root_Query* x) { return static_cast<D*>(this)->fallback(x); } |
191 | T operator()(Parent_Reference* x) { return static_cast<D*>(this)->fallback(x); } |
192 | // parameters and arguments |
193 | T operator()(Parameter* x) { return static_cast<D*>(this)->fallback(x); } |
194 | T operator()(Parameters* x) { return static_cast<D*>(this)->fallback(x); } |
195 | T operator()(Argument* x) { return static_cast<D*>(this)->fallback(x); } |
196 | T operator()(Arguments* x) { return static_cast<D*>(this)->fallback(x); } |
197 | // selectors |
198 | T operator()(Selector_Schema* x) { return static_cast<D*>(this)->fallback(x); } |
199 | T operator()(PlaceholderSelector* x) { return static_cast<D*>(this)->fallback(x); } |
200 | T operator()(TypeSelector* x) { return static_cast<D*>(this)->fallback(x); } |
201 | T operator()(ClassSelector* x) { return static_cast<D*>(this)->fallback(x); } |
202 | T operator()(IDSelector* x) { return static_cast<D*>(this)->fallback(x); } |
203 | T operator()(AttributeSelector* x) { return static_cast<D*>(this)->fallback(x); } |
204 | T operator()(PseudoSelector* x) { return static_cast<D*>(this)->fallback(x); } |
205 | T operator()(SelectorComponent* x) { return static_cast<D*>(this)->fallback(x); } |
206 | T operator()(SelectorCombinator* x) { return static_cast<D*>(this)->fallback(x); } |
207 | T operator()(CompoundSelector* x) { return static_cast<D*>(this)->fallback(x); } |
208 | T operator()(ComplexSelector* x) { return static_cast<D*>(this)->fallback(x); } |
209 | T operator()(SelectorList* x) { return static_cast<D*>(this)->fallback(x); } |
210 | |
211 | // fallback with specific type U |
212 | // will be called if not overloaded |
213 | template <typename U> inline T fallback(U x) |
214 | { |
215 | throw std::runtime_error( |
216 | std::string(typeid(*this).name()) + ": CRTP not implemented for " + typeid(x).name()); |
217 | } |
218 | |
219 | }; |
220 | |
221 | } |
222 | |
223 | #endif |
224 | |