sassc4 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +16 -0
  5. data/CHANGELOG.md +97 -0
  6. data/CODE_OF_CONDUCT.md +10 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +80 -0
  10. data/Rakefile +51 -0
  11. data/ext/depend +4 -0
  12. data/ext/extconf.rb +92 -0
  13. data/ext/libsass/VERSION +1 -0
  14. data/ext/libsass/contrib/plugin.cpp +60 -0
  15. data/ext/libsass/include/sass/base.h +97 -0
  16. data/ext/libsass/include/sass/context.h +174 -0
  17. data/ext/libsass/include/sass/functions.h +139 -0
  18. data/ext/libsass/include/sass/values.h +145 -0
  19. data/ext/libsass/include/sass/version.h +12 -0
  20. data/ext/libsass/include/sass.h +15 -0
  21. data/ext/libsass/include/sass2scss.h +120 -0
  22. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  23. data/ext/libsass/src/ast.cpp +953 -0
  24. data/ext/libsass/src/ast.hpp +1064 -0
  25. data/ext/libsass/src/ast2c.cpp +80 -0
  26. data/ext/libsass/src/ast2c.hpp +39 -0
  27. data/ext/libsass/src/ast_def_macros.hpp +140 -0
  28. data/ext/libsass/src/ast_fwd_decl.cpp +31 -0
  29. data/ext/libsass/src/ast_fwd_decl.hpp +274 -0
  30. data/ext/libsass/src/ast_helpers.hpp +316 -0
  31. data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
  32. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  33. data/ext/libsass/src/ast_sel_unify.cpp +275 -0
  34. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  35. data/ext/libsass/src/ast_selectors.cpp +1070 -0
  36. data/ext/libsass/src/ast_selectors.hpp +523 -0
  37. data/ext/libsass/src/ast_supports.cpp +114 -0
  38. data/ext/libsass/src/ast_supports.hpp +121 -0
  39. data/ext/libsass/src/ast_values.cpp +1154 -0
  40. data/ext/libsass/src/ast_values.hpp +498 -0
  41. data/ext/libsass/src/b64/cencode.h +32 -0
  42. data/ext/libsass/src/b64/encode.h +79 -0
  43. data/ext/libsass/src/backtrace.cpp +50 -0
  44. data/ext/libsass/src/backtrace.hpp +29 -0
  45. data/ext/libsass/src/base64vlq.cpp +47 -0
  46. data/ext/libsass/src/base64vlq.hpp +30 -0
  47. data/ext/libsass/src/bind.cpp +312 -0
  48. data/ext/libsass/src/bind.hpp +15 -0
  49. data/ext/libsass/src/c2ast.cpp +64 -0
  50. data/ext/libsass/src/c2ast.hpp +14 -0
  51. data/ext/libsass/src/c99func.c +54 -0
  52. data/ext/libsass/src/cencode.c +106 -0
  53. data/ext/libsass/src/check_nesting.cpp +393 -0
  54. data/ext/libsass/src/check_nesting.hpp +70 -0
  55. data/ext/libsass/src/color_maps.cpp +652 -0
  56. data/ext/libsass/src/color_maps.hpp +323 -0
  57. data/ext/libsass/src/color_spaces.cpp +241 -0
  58. data/ext/libsass/src/color_spaces.hpp +227 -0
  59. data/ext/libsass/src/constants.cpp +199 -0
  60. data/ext/libsass/src/constants.hpp +200 -0
  61. data/ext/libsass/src/context.cpp +870 -0
  62. data/ext/libsass/src/context.hpp +140 -0
  63. data/ext/libsass/src/cssize.cpp +521 -0
  64. data/ext/libsass/src/cssize.hpp +71 -0
  65. data/ext/libsass/src/dart_helpers.hpp +199 -0
  66. data/ext/libsass/src/debug.hpp +43 -0
  67. data/ext/libsass/src/debugger.hpp +964 -0
  68. data/ext/libsass/src/emitter.cpp +297 -0
  69. data/ext/libsass/src/emitter.hpp +101 -0
  70. data/ext/libsass/src/environment.cpp +260 -0
  71. data/ext/libsass/src/environment.hpp +124 -0
  72. data/ext/libsass/src/error_handling.cpp +239 -0
  73. data/ext/libsass/src/error_handling.hpp +248 -0
  74. data/ext/libsass/src/eval.cpp +1543 -0
  75. data/ext/libsass/src/eval.hpp +110 -0
  76. data/ext/libsass/src/eval_selectors.cpp +75 -0
  77. data/ext/libsass/src/expand.cpp +875 -0
  78. data/ext/libsass/src/expand.hpp +98 -0
  79. data/ext/libsass/src/extender.cpp +1226 -0
  80. data/ext/libsass/src/extender.hpp +399 -0
  81. data/ext/libsass/src/extension.cpp +43 -0
  82. data/ext/libsass/src/extension.hpp +89 -0
  83. data/ext/libsass/src/file.cpp +531 -0
  84. data/ext/libsass/src/file.hpp +124 -0
  85. data/ext/libsass/src/fn_colors.cpp +836 -0
  86. data/ext/libsass/src/fn_colors.hpp +99 -0
  87. data/ext/libsass/src/fn_lists.cpp +285 -0
  88. data/ext/libsass/src/fn_lists.hpp +34 -0
  89. data/ext/libsass/src/fn_maps.cpp +94 -0
  90. data/ext/libsass/src/fn_maps.hpp +30 -0
  91. data/ext/libsass/src/fn_miscs.cpp +248 -0
  92. data/ext/libsass/src/fn_miscs.hpp +40 -0
  93. data/ext/libsass/src/fn_numbers.cpp +246 -0
  94. data/ext/libsass/src/fn_numbers.hpp +45 -0
  95. data/ext/libsass/src/fn_selectors.cpp +205 -0
  96. data/ext/libsass/src/fn_selectors.hpp +35 -0
  97. data/ext/libsass/src/fn_strings.cpp +268 -0
  98. data/ext/libsass/src/fn_strings.hpp +34 -0
  99. data/ext/libsass/src/fn_utils.cpp +159 -0
  100. data/ext/libsass/src/fn_utils.hpp +62 -0
  101. data/ext/libsass/src/inspect.cpp +1126 -0
  102. data/ext/libsass/src/inspect.hpp +101 -0
  103. data/ext/libsass/src/json.cpp +1436 -0
  104. data/ext/libsass/src/json.hpp +117 -0
  105. data/ext/libsass/src/kwd_arg_macros.hpp +28 -0
  106. data/ext/libsass/src/lexer.cpp +122 -0
  107. data/ext/libsass/src/lexer.hpp +304 -0
  108. data/ext/libsass/src/listize.cpp +70 -0
  109. data/ext/libsass/src/listize.hpp +37 -0
  110. data/ext/libsass/src/mapping.hpp +19 -0
  111. data/ext/libsass/src/memory/allocator.cpp +48 -0
  112. data/ext/libsass/src/memory/allocator.hpp +138 -0
  113. data/ext/libsass/src/memory/config.hpp +20 -0
  114. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  115. data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
  116. data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
  117. data/ext/libsass/src/memory.hpp +12 -0
  118. data/ext/libsass/src/operation.hpp +223 -0
  119. data/ext/libsass/src/operators.cpp +267 -0
  120. data/ext/libsass/src/operators.hpp +30 -0
  121. data/ext/libsass/src/ordered_map.hpp +112 -0
  122. data/ext/libsass/src/output.cpp +320 -0
  123. data/ext/libsass/src/output.hpp +47 -0
  124. data/ext/libsass/src/parser.cpp +3059 -0
  125. data/ext/libsass/src/parser.hpp +395 -0
  126. data/ext/libsass/src/parser_selectors.cpp +189 -0
  127. data/ext/libsass/src/permutate.hpp +164 -0
  128. data/ext/libsass/src/plugins.cpp +188 -0
  129. data/ext/libsass/src/plugins.hpp +57 -0
  130. data/ext/libsass/src/position.cpp +163 -0
  131. data/ext/libsass/src/position.hpp +147 -0
  132. data/ext/libsass/src/prelexer.cpp +1780 -0
  133. data/ext/libsass/src/prelexer.hpp +484 -0
  134. data/ext/libsass/src/remove_placeholders.cpp +86 -0
  135. data/ext/libsass/src/remove_placeholders.hpp +37 -0
  136. data/ext/libsass/src/sass.cpp +156 -0
  137. data/ext/libsass/src/sass.hpp +147 -0
  138. data/ext/libsass/src/sass2scss.cpp +895 -0
  139. data/ext/libsass/src/sass_context.cpp +742 -0
  140. data/ext/libsass/src/sass_context.hpp +129 -0
  141. data/ext/libsass/src/sass_functions.cpp +210 -0
  142. data/ext/libsass/src/sass_functions.hpp +50 -0
  143. data/ext/libsass/src/sass_values.cpp +362 -0
  144. data/ext/libsass/src/sass_values.hpp +82 -0
  145. data/ext/libsass/src/settings.hpp +19 -0
  146. data/ext/libsass/src/source.cpp +69 -0
  147. data/ext/libsass/src/source.hpp +95 -0
  148. data/ext/libsass/src/source_data.hpp +32 -0
  149. data/ext/libsass/src/source_map.cpp +202 -0
  150. data/ext/libsass/src/source_map.hpp +65 -0
  151. data/ext/libsass/src/stylesheet.cpp +22 -0
  152. data/ext/libsass/src/stylesheet.hpp +57 -0
  153. data/ext/libsass/src/to_value.cpp +114 -0
  154. data/ext/libsass/src/to_value.hpp +46 -0
  155. data/ext/libsass/src/units.cpp +507 -0
  156. data/ext/libsass/src/units.hpp +110 -0
  157. data/ext/libsass/src/utf8/checked.h +336 -0
  158. data/ext/libsass/src/utf8/core.h +332 -0
  159. data/ext/libsass/src/utf8/unchecked.h +235 -0
  160. data/ext/libsass/src/utf8.h +34 -0
  161. data/ext/libsass/src/utf8_string.cpp +104 -0
  162. data/ext/libsass/src/utf8_string.hpp +38 -0
  163. data/ext/libsass/src/util.cpp +723 -0
  164. data/ext/libsass/src/util.hpp +105 -0
  165. data/ext/libsass/src/util_string.cpp +125 -0
  166. data/ext/libsass/src/util_string.hpp +73 -0
  167. data/ext/libsass/src/values.cpp +140 -0
  168. data/ext/libsass/src/values.hpp +12 -0
  169. data/lib/sassc/dependency.rb +17 -0
  170. data/lib/sassc/engine.rb +141 -0
  171. data/lib/sassc/error.rb +37 -0
  172. data/lib/sassc/functions_handler.rb +73 -0
  173. data/lib/sassc/import_handler.rb +50 -0
  174. data/lib/sassc/importer.rb +31 -0
  175. data/lib/sassc/native/native_context_api.rb +147 -0
  176. data/lib/sassc/native/native_functions_api.rb +159 -0
  177. data/lib/sassc/native/sass2scss_api.rb +10 -0
  178. data/lib/sassc/native/sass_input_style.rb +13 -0
  179. data/lib/sassc/native/sass_output_style.rb +12 -0
  180. data/lib/sassc/native/sass_value.rb +97 -0
  181. data/lib/sassc/native/string_list.rb +10 -0
  182. data/lib/sassc/native.rb +64 -0
  183. data/lib/sassc/sass_2_scss.rb +9 -0
  184. data/lib/sassc/script/functions.rb +8 -0
  185. data/lib/sassc/script/value/bool.rb +32 -0
  186. data/lib/sassc/script/value/color.rb +95 -0
  187. data/lib/sassc/script/value/list.rb +136 -0
  188. data/lib/sassc/script/value/map.rb +69 -0
  189. data/lib/sassc/script/value/number.rb +389 -0
  190. data/lib/sassc/script/value/string.rb +96 -0
  191. data/lib/sassc/script/value.rb +137 -0
  192. data/lib/sassc/script/value_conversion/base.rb +13 -0
  193. data/lib/sassc/script/value_conversion/bool.rb +13 -0
  194. data/lib/sassc/script/value_conversion/color.rb +18 -0
  195. data/lib/sassc/script/value_conversion/list.rb +25 -0
  196. data/lib/sassc/script/value_conversion/map.rb +21 -0
  197. data/lib/sassc/script/value_conversion/number.rb +13 -0
  198. data/lib/sassc/script/value_conversion/string.rb +17 -0
  199. data/lib/sassc/script/value_conversion.rb +69 -0
  200. data/lib/sassc/script.rb +17 -0
  201. data/lib/sassc/util/normalized_map.rb +117 -0
  202. data/lib/sassc/util.rb +231 -0
  203. data/lib/sassc/version.rb +5 -0
  204. data/lib/sassc.rb +57 -0
  205. data/sassc.gemspec +69 -0
  206. data/test/css_color_level4_test.rb +168 -0
  207. data/test/custom_importer_test.rb +127 -0
  208. data/test/engine_test.rb +314 -0
  209. data/test/error_test.rb +29 -0
  210. data/test/fixtures/paths.scss +10 -0
  211. data/test/functions_test.rb +340 -0
  212. data/test/native_test.rb +213 -0
  213. data/test/output_style_test.rb +107 -0
  214. data/test/sass_2_scss_test.rb +14 -0
  215. data/test/test_helper.rb +45 -0
  216. metadata +396 -0
@@ -0,0 +1,1543 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
3
+ #include "sass.hpp"
4
+
5
+ #include <cstdlib>
6
+ #include <cmath>
7
+ #include <iostream>
8
+ #include <sstream>
9
+ #include <iomanip>
10
+ #include <typeinfo>
11
+
12
+ #include "file.hpp"
13
+ #include "eval.hpp"
14
+ #include "ast.hpp"
15
+ #include "bind.hpp"
16
+ #include "util.hpp"
17
+ #include "inspect.hpp"
18
+ #include "operators.hpp"
19
+ #include "environment.hpp"
20
+ #include "position.hpp"
21
+ #include "sass/values.h"
22
+ #include "to_value.hpp"
23
+ #include "ast2c.hpp"
24
+ #include "c2ast.hpp"
25
+ #include "context.hpp"
26
+ #include "backtrace.hpp"
27
+ #include "lexer.hpp"
28
+ #include "prelexer.hpp"
29
+ #include "parser.hpp"
30
+ #include "expand.hpp"
31
+ #include "color_maps.hpp"
32
+ #include "sass_functions.hpp"
33
+ #include "error_handling.hpp"
34
+ #include "util_string.hpp"
35
+
36
+ namespace Sass {
37
+
38
+ Eval::Eval(Expand& exp)
39
+ : exp(exp),
40
+ ctx(exp.ctx),
41
+ traces(exp.traces),
42
+ force(false),
43
+ is_in_comment(false),
44
+ is_in_selector_schema(false)
45
+ {
46
+ bool_true = SASS_MEMORY_NEW(Boolean, "[NA]", true);
47
+ bool_false = SASS_MEMORY_NEW(Boolean, "[NA]", false);
48
+ }
49
+ Eval::~Eval() { }
50
+
51
+ Env* Eval::environment()
52
+ {
53
+ return exp.environment();
54
+ }
55
+
56
+ const sass::string Eval::cwd()
57
+ {
58
+ return ctx.cwd();
59
+ }
60
+
61
+ struct Sass_Inspect_Options& Eval::options()
62
+ {
63
+ return ctx.c_options;
64
+ }
65
+
66
+ struct Sass_Compiler* Eval::compiler()
67
+ {
68
+ return ctx.c_compiler;
69
+ }
70
+
71
+ EnvStack& Eval::env_stack()
72
+ {
73
+ return exp.env_stack;
74
+ }
75
+
76
+ sass::vector<Sass_Callee>& Eval::callee_stack()
77
+ {
78
+ return ctx.callee_stack;
79
+ }
80
+
81
+ Expression* Eval::operator()(Block* b)
82
+ {
83
+ Expression* val = 0;
84
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
85
+ val = b->at(i)->perform(this);
86
+ if (val) return val;
87
+ }
88
+ return val;
89
+ }
90
+
91
+ Expression* Eval::operator()(Assignment* a)
92
+ {
93
+ Env* env = environment();
94
+ sass::string var(a->variable());
95
+ if (a->is_global()) {
96
+ if (!env->has_global(var)) {
97
+ deprecated(
98
+ "!global assignments won't be able to declare new variables in future versions.",
99
+ "Consider adding `" + var + ": null` at the top level.",
100
+ true, a->pstate());
101
+ }
102
+ if (a->is_default()) {
103
+ if (env->has_global(var)) {
104
+ Expression* e = Cast<Expression>(env->get_global(var));
105
+ if (!e || e->concrete_type() == Expression::NULL_VAL) {
106
+ env->set_global(var, a->value()->perform(this));
107
+ }
108
+ }
109
+ else {
110
+ env->set_global(var, a->value()->perform(this));
111
+ }
112
+ }
113
+ else {
114
+ env->set_global(var, a->value()->perform(this));
115
+ }
116
+ }
117
+ else if (a->is_default()) {
118
+ if (env->has_lexical(var)) {
119
+ auto cur = env;
120
+ while (cur && cur->is_lexical()) {
121
+ if (cur->has_local(var)) {
122
+ if (AST_Node_Obj node = cur->get_local(var)) {
123
+ Expression* e = Cast<Expression>(node);
124
+ if (!e || e->concrete_type() == Expression::NULL_VAL) {
125
+ cur->set_local(var, a->value()->perform(this));
126
+ }
127
+ }
128
+ else {
129
+ throw std::runtime_error("Env not in sync");
130
+ }
131
+ return 0;
132
+ }
133
+ cur = cur->parent();
134
+ }
135
+ throw std::runtime_error("Env not in sync");
136
+ }
137
+ else if (env->has_global(var)) {
138
+ if (AST_Node_Obj node = env->get_global(var)) {
139
+ Expression* e = Cast<Expression>(node);
140
+ if (!e || e->concrete_type() == Expression::NULL_VAL) {
141
+ env->set_global(var, a->value()->perform(this));
142
+ }
143
+ }
144
+ }
145
+ else if (env->is_lexical()) {
146
+ env->set_local(var, a->value()->perform(this));
147
+ }
148
+ else {
149
+ env->set_local(var, a->value()->perform(this));
150
+ }
151
+ }
152
+ else {
153
+ env->set_lexical(var, a->value()->perform(this));
154
+ }
155
+ return 0;
156
+ }
157
+
158
+ Expression* Eval::operator()(If* i)
159
+ {
160
+ ExpressionObj rv;
161
+ Env env(environment());
162
+ env_stack().push_back(&env);
163
+ ExpressionObj cond = i->predicate()->perform(this);
164
+ if (!cond->is_false()) {
165
+ rv = i->block()->perform(this);
166
+ }
167
+ else {
168
+ Block_Obj alt = i->alternative();
169
+ if (alt) rv = alt->perform(this);
170
+ }
171
+ env_stack().pop_back();
172
+ return rv.detach();
173
+ }
174
+
175
+ // For does not create a new env scope
176
+ // But iteration vars are reset afterwards
177
+ Expression* Eval::operator()(ForRule* f)
178
+ {
179
+ sass::string variable(f->variable());
180
+ ExpressionObj low = f->lower_bound()->perform(this);
181
+ if (low->concrete_type() != Expression::NUMBER) {
182
+ traces.push_back(Backtrace(low->pstate()));
183
+ throw Exception::TypeMismatch(traces, *low, "integer");
184
+ }
185
+ ExpressionObj high = f->upper_bound()->perform(this);
186
+ if (high->concrete_type() != Expression::NUMBER) {
187
+ traces.push_back(Backtrace(high->pstate()));
188
+ throw Exception::TypeMismatch(traces, *high, "integer");
189
+ }
190
+ Number_Obj sass_start = Cast<Number>(low);
191
+ Number_Obj sass_end = Cast<Number>(high);
192
+ // check if units are valid for sequence
193
+ if (sass_start->unit() != sass_end->unit()) {
194
+ sass::ostream msg; msg << "Incompatible units: '"
195
+ << sass_end->unit() << "' and '"
196
+ << sass_start->unit() << "'.";
197
+ error(msg.str(), low->pstate(), traces);
198
+ }
199
+ double start = sass_start->value();
200
+ double end = sass_end->value();
201
+ // only create iterator once in this environment
202
+ Env env(environment(), true);
203
+ env_stack().push_back(&env);
204
+ Block_Obj body = f->block();
205
+ Expression* val = 0;
206
+ if (start < end) {
207
+ if (f->is_inclusive()) ++end;
208
+ for (double i = start;
209
+ i < end;
210
+ ++i) {
211
+ Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
212
+ env.set_local(variable, it);
213
+ val = body->perform(this);
214
+ if (val) break;
215
+ }
216
+ } else {
217
+ if (f->is_inclusive()) --end;
218
+ for (double i = start;
219
+ i > end;
220
+ --i) {
221
+ Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
222
+ env.set_local(variable, it);
223
+ val = body->perform(this);
224
+ if (val) break;
225
+ }
226
+ }
227
+ env_stack().pop_back();
228
+ return val;
229
+ }
230
+
231
+ // Eval does not create a new env scope
232
+ // But iteration vars are reset afterwards
233
+ Expression* Eval::operator()(EachRule* e)
234
+ {
235
+ sass::vector<sass::string> variables(e->variables());
236
+ ExpressionObj expr = e->list()->perform(this);
237
+ Env env(environment(), true);
238
+ env_stack().push_back(&env);
239
+ List_Obj list;
240
+ Map* map = nullptr;
241
+ if (expr->concrete_type() == Expression::MAP) {
242
+ map = Cast<Map>(expr);
243
+ }
244
+ else if (SelectorList * ls = Cast<SelectorList>(expr)) {
245
+ ExpressionObj rv = Listize::perform(ls);
246
+ list = Cast<List>(rv);
247
+ }
248
+ else if (expr->concrete_type() != Expression::LIST) {
249
+ list = SASS_MEMORY_NEW(List, expr->pstate(), 1, SASS_COMMA);
250
+ list->append(expr);
251
+ }
252
+ else {
253
+ list = Cast<List>(expr);
254
+ }
255
+
256
+ Block_Obj body = e->block();
257
+ ExpressionObj val;
258
+
259
+ if (map) {
260
+ for (ExpressionObj key : map->keys()) {
261
+ ExpressionObj value = map->at(key);
262
+
263
+ if (variables.size() == 1) {
264
+ List* variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE);
265
+ variable->append(key);
266
+ variable->append(value);
267
+ env.set_local(variables[0], variable);
268
+ } else {
269
+ env.set_local(variables[0], key);
270
+ env.set_local(variables[1], value);
271
+ }
272
+
273
+ val = body->perform(this);
274
+ if (val) break;
275
+ }
276
+ }
277
+ else {
278
+ if (list->length() == 1 && Cast<SelectorList>(list)) {
279
+ list = Cast<List>(list);
280
+ }
281
+ for (size_t i = 0, L = list->length(); i < L; ++i) {
282
+ Expression* item = list->at(i);
283
+ // unwrap value if the expression is an argument
284
+ if (Argument* arg = Cast<Argument>(item)) item = arg->value();
285
+ // check if we got passed a list of args (investigate)
286
+ if (List* scalars = Cast<List>(item)) {
287
+ if (variables.size() == 1) {
288
+ Expression* var = scalars;
289
+ env.set_local(variables[0], var);
290
+ } else {
291
+ // https://github.com/sass/libsass/issues/3078
292
+ for (size_t j = 0, K = variables.size(); j < K; ++j) {
293
+ env.set_local(variables[j], j >= scalars->length()
294
+ ? SASS_MEMORY_NEW(Null, expr->pstate()) : scalars->at(j));
295
+ }
296
+ }
297
+ } else {
298
+ if (variables.size() > 0) {
299
+ env.set_local(variables.at(0), item);
300
+ for (size_t j = 1, K = variables.size(); j < K; ++j) {
301
+ // XXX: this is never hit via spec tests
302
+ Expression* res = SASS_MEMORY_NEW(Null, expr->pstate());
303
+ env.set_local(variables[j], res);
304
+ }
305
+ }
306
+ }
307
+ val = body->perform(this);
308
+ if (val) break;
309
+ }
310
+ }
311
+ env_stack().pop_back();
312
+ return val.detach();
313
+ }
314
+
315
+ Expression* Eval::operator()(WhileRule* w)
316
+ {
317
+ ExpressionObj pred = w->predicate();
318
+ Block_Obj body = w->block();
319
+ Env env(environment(), true);
320
+ env_stack().push_back(&env);
321
+ ExpressionObj cond = pred->perform(this);
322
+ while (!cond->is_false()) {
323
+ ExpressionObj val = body->perform(this);
324
+ if (val) {
325
+ env_stack().pop_back();
326
+ return val.detach();
327
+ }
328
+ cond = pred->perform(this);
329
+ }
330
+ env_stack().pop_back();
331
+ return 0;
332
+ }
333
+
334
+ Expression* Eval::operator()(Return* r)
335
+ {
336
+ return r->value()->perform(this);
337
+ }
338
+
339
+ Expression* Eval::operator()(WarningRule* w)
340
+ {
341
+ Sass_Output_Style outstyle = options().output_style;
342
+ options().output_style = NESTED;
343
+ ExpressionObj message = w->message()->perform(this);
344
+ Env* env = environment();
345
+
346
+ // try to use generic function
347
+ if (env->has("@warn[f]")) {
348
+
349
+ // add call stack entry
350
+ callee_stack().push_back({
351
+ "@warn",
352
+ w->pstate().getPath(),
353
+ w->pstate().getLine(),
354
+ w->pstate().getColumn(),
355
+ SASS_CALLEE_FUNCTION,
356
+ { env }
357
+ });
358
+
359
+ Definition* def = Cast<Definition>((*env)["@warn[f]"]);
360
+ // Block_Obj body = def->block();
361
+ // Native_Function func = def->native_function();
362
+ Sass_Function_Entry c_function = def->c_function();
363
+ Sass_Function_Fn c_func = sass_function_get_function(c_function);
364
+
365
+ AST2C ast2c;
366
+ union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
367
+ sass_list_set_value(c_args, 0, message->perform(&ast2c));
368
+ union Sass_Value* c_val = c_func(c_args, c_function, compiler());
369
+ options().output_style = outstyle;
370
+ callee_stack().pop_back();
371
+ sass_delete_value(c_args);
372
+ sass_delete_value(c_val);
373
+ return 0;
374
+
375
+ }
376
+
377
+ sass::string result(unquote(message->to_sass()));
378
+ std::cerr << "WARNING: " << result << std::endl;
379
+ traces.push_back(Backtrace(w->pstate()));
380
+ std::cerr << traces_to_string(traces, " ");
381
+ std::cerr << std::endl;
382
+ options().output_style = outstyle;
383
+ traces.pop_back();
384
+ return 0;
385
+ }
386
+
387
+ Expression* Eval::operator()(ErrorRule* e)
388
+ {
389
+ Sass_Output_Style outstyle = options().output_style;
390
+ options().output_style = NESTED;
391
+ ExpressionObj message = e->message()->perform(this);
392
+ Env* env = environment();
393
+
394
+ // try to use generic function
395
+ if (env->has("@error[f]")) {
396
+
397
+ // add call stack entry
398
+ callee_stack().push_back({
399
+ "@error",
400
+ e->pstate().getPath(),
401
+ e->pstate().getLine(),
402
+ e->pstate().getColumn(),
403
+ SASS_CALLEE_FUNCTION,
404
+ { env }
405
+ });
406
+
407
+ Definition* def = Cast<Definition>((*env)["@error[f]"]);
408
+ // Block_Obj body = def->block();
409
+ // Native_Function func = def->native_function();
410
+ Sass_Function_Entry c_function = def->c_function();
411
+ Sass_Function_Fn c_func = sass_function_get_function(c_function);
412
+
413
+ AST2C ast2c;
414
+ union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
415
+ sass_list_set_value(c_args, 0, message->perform(&ast2c));
416
+ union Sass_Value* c_val = c_func(c_args, c_function, compiler());
417
+ options().output_style = outstyle;
418
+ callee_stack().pop_back();
419
+ sass_delete_value(c_args);
420
+ sass_delete_value(c_val);
421
+ return 0;
422
+
423
+ }
424
+
425
+ sass::string result(unquote(message->to_sass()));
426
+ options().output_style = outstyle;
427
+ error(result, e->pstate(), traces);
428
+ return 0;
429
+ }
430
+
431
+ Expression* Eval::operator()(DebugRule* d)
432
+ {
433
+ Sass_Output_Style outstyle = options().output_style;
434
+ options().output_style = NESTED;
435
+ ExpressionObj message = d->value()->perform(this);
436
+ Env* env = environment();
437
+
438
+ // try to use generic function
439
+ if (env->has("@debug[f]")) {
440
+
441
+ // add call stack entry
442
+ callee_stack().push_back({
443
+ "@debug",
444
+ d->pstate().getPath(),
445
+ d->pstate().getLine(),
446
+ d->pstate().getColumn(),
447
+ SASS_CALLEE_FUNCTION,
448
+ { env }
449
+ });
450
+
451
+ Definition* def = Cast<Definition>((*env)["@debug[f]"]);
452
+ // Block_Obj body = def->block();
453
+ // Native_Function func = def->native_function();
454
+ Sass_Function_Entry c_function = def->c_function();
455
+ Sass_Function_Fn c_func = sass_function_get_function(c_function);
456
+
457
+ AST2C ast2c;
458
+ union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
459
+ sass_list_set_value(c_args, 0, message->perform(&ast2c));
460
+ union Sass_Value* c_val = c_func(c_args, c_function, compiler());
461
+ options().output_style = outstyle;
462
+ callee_stack().pop_back();
463
+ sass_delete_value(c_args);
464
+ sass_delete_value(c_val);
465
+ return 0;
466
+
467
+ }
468
+
469
+ sass::string result(unquote(message->to_sass()));
470
+ sass::string abs_path(Sass::File::rel2abs(d->pstate().getPath(), cwd(), cwd()));
471
+ sass::string rel_path(Sass::File::abs2rel(d->pstate().getPath(), cwd(), cwd()));
472
+ sass::string output_path(Sass::File::path_for_console(rel_path, abs_path, d->pstate().getPath()));
473
+ options().output_style = outstyle;
474
+
475
+ std::cerr << output_path << ":" << d->pstate().getLine() << " DEBUG: " << result;
476
+ std::cerr << std::endl;
477
+ return 0;
478
+ }
479
+
480
+
481
+ Expression* Eval::operator()(List* l)
482
+ {
483
+ // special case for unevaluated map
484
+ if (l->separator() == SASS_HASH) {
485
+ Map_Obj lm = SASS_MEMORY_NEW(Map,
486
+ l->pstate(),
487
+ l->length() / 2);
488
+ for (size_t i = 0, L = l->length(); i < L; i += 2)
489
+ {
490
+ ExpressionObj key = (*l)[i+0]->perform(this);
491
+ ExpressionObj val = (*l)[i+1]->perform(this);
492
+ // make sure the color key never displays its real name
493
+ key->is_delayed(true); // verified
494
+ *lm << std::make_pair(key, val);
495
+ }
496
+ if (lm->has_duplicate_key()) {
497
+ traces.push_back(Backtrace(l->pstate()));
498
+ throw Exception::DuplicateKeyError(traces, *lm, *l);
499
+ }
500
+
501
+ lm->is_interpolant(l->is_interpolant());
502
+ return lm->perform(this);
503
+ }
504
+ // check if we should expand it
505
+ if (l->is_expanded()) return l;
506
+ // regular case for unevaluated lists
507
+ List_Obj ll = SASS_MEMORY_NEW(List,
508
+ l->pstate(),
509
+ l->length(),
510
+ l->separator(),
511
+ l->is_arglist(),
512
+ l->is_bracketed());
513
+ for (size_t i = 0, L = l->length(); i < L; ++i) {
514
+ ll->append((*l)[i]->perform(this));
515
+ }
516
+ ll->is_interpolant(l->is_interpolant());
517
+ ll->from_selector(l->from_selector());
518
+ ll->is_expanded(true);
519
+ return ll.detach();
520
+ }
521
+
522
+ Expression* Eval::operator()(Map* m)
523
+ {
524
+ if (m->is_expanded()) return m;
525
+
526
+ // make sure we're not starting with duplicate keys.
527
+ // the duplicate key state will have been set in the parser phase.
528
+ if (m->has_duplicate_key()) {
529
+ traces.push_back(Backtrace(m->pstate()));
530
+ throw Exception::DuplicateKeyError(traces, *m, *m);
531
+ }
532
+
533
+ Map_Obj mm = SASS_MEMORY_NEW(Map,
534
+ m->pstate(),
535
+ m->length());
536
+ for (auto key : m->keys()) {
537
+ Expression* ex_key = key->perform(this);
538
+ Expression* ex_val = m->at(key);
539
+ if (ex_val == NULL) continue;
540
+ ex_val = ex_val->perform(this);
541
+ *mm << std::make_pair(ex_key, ex_val);
542
+ }
543
+
544
+ // check the evaluated keys aren't duplicates.
545
+ if (mm->has_duplicate_key()) {
546
+ traces.push_back(Backtrace(m->pstate()));
547
+ throw Exception::DuplicateKeyError(traces, *mm, *m);
548
+ }
549
+
550
+ mm->is_expanded(true);
551
+ return mm.detach();
552
+ }
553
+
554
+ Expression* Eval::operator()(Binary_Expression* b_in)
555
+ {
556
+
557
+ ExpressionObj lhs = b_in->left();
558
+ ExpressionObj rhs = b_in->right();
559
+ enum Sass_OP op_type = b_in->optype();
560
+
561
+ if (op_type == Sass_OP::AND) {
562
+ // LOCAL_FLAG(force, true);
563
+ lhs = lhs->perform(this);
564
+ if (!*lhs) return lhs.detach();
565
+ return rhs->perform(this);
566
+ }
567
+ else if (op_type == Sass_OP::OR) {
568
+ // LOCAL_FLAG(force, true);
569
+ lhs = lhs->perform(this);
570
+ if (*lhs) return lhs.detach();
571
+ return rhs->perform(this);
572
+ }
573
+
574
+ // Evaluate variables as early o
575
+ while (Variable* l_v = Cast<Variable>(lhs)) {
576
+ lhs = operator()(l_v);
577
+ }
578
+ while (Variable* r_v = Cast<Variable>(rhs)) {
579
+ rhs = operator()(r_v);
580
+ }
581
+
582
+ Binary_ExpressionObj b = b_in;
583
+
584
+ // Evaluate sub-expressions early on
585
+ while (Binary_Expression* l_b = Cast<Binary_Expression>(lhs)) {
586
+ if (!force && l_b->is_delayed()) break;
587
+ lhs = operator()(l_b);
588
+ }
589
+ while (Binary_Expression* r_b = Cast<Binary_Expression>(rhs)) {
590
+ if (!force && r_b->is_delayed()) break;
591
+ rhs = operator()(r_b);
592
+ }
593
+
594
+ // don't eval delayed expressions (the '/' when used as a separator)
595
+ if (!force && op_type == Sass_OP::DIV && b->is_delayed()) {
596
+ b->right(b->right()->perform(this));
597
+ b->left(b->left()->perform(this));
598
+ return b.detach();
599
+ }
600
+
601
+ // specific types we know are final
602
+ // handle them early to avoid overhead
603
+ if (Number* l_n = Cast<Number>(lhs)) {
604
+ // lhs is number and rhs is number
605
+ if (Number* r_n = Cast<Number>(rhs)) {
606
+ try {
607
+ switch (op_type) {
608
+ case Sass_OP::EQ: return *l_n == *r_n ? bool_true : bool_false;
609
+ case Sass_OP::NEQ: return *l_n == *r_n ? bool_false : bool_true;
610
+ case Sass_OP::LT: return *l_n < *r_n ? bool_true : bool_false;
611
+ case Sass_OP::GTE: return *l_n < *r_n ? bool_false : bool_true;
612
+ case Sass_OP::LTE: return *l_n < *r_n || *l_n == *r_n ? bool_true : bool_false;
613
+ case Sass_OP::GT: return *l_n < *r_n || *l_n == *r_n ? bool_false : bool_true;
614
+ case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
615
+ return Operators::op_numbers(op_type, *l_n, *r_n, options(), b_in->pstate());
616
+ default: break;
617
+ }
618
+ }
619
+ catch (Exception::OperationError& err)
620
+ {
621
+ traces.push_back(Backtrace(b_in->pstate()));
622
+ throw Exception::SassValueError(traces, b_in->pstate(), err);
623
+ }
624
+ }
625
+ // lhs is number and rhs is color
626
+ // Todo: allow to work with HSLA colors
627
+ else if (Color* r_col = Cast<Color>(rhs)) {
628
+ Color_RGBA_Obj r_c = r_col->toRGBA();
629
+ try {
630
+ switch (op_type) {
631
+ case Sass_OP::EQ: return *l_n == *r_c ? bool_true : bool_false;
632
+ case Sass_OP::NEQ: return *l_n == *r_c ? bool_false : bool_true;
633
+ case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
634
+ return Operators::op_number_color(op_type, *l_n, *r_c, options(), b_in->pstate());
635
+ default: break;
636
+ }
637
+ }
638
+ catch (Exception::OperationError& err)
639
+ {
640
+ traces.push_back(Backtrace(b_in->pstate()));
641
+ throw Exception::SassValueError(traces, b_in->pstate(), err);
642
+ }
643
+ }
644
+ }
645
+ else if (Color* l_col = Cast<Color>(lhs)) {
646
+ Color_RGBA_Obj l_c = l_col->toRGBA();
647
+ // lhs is color and rhs is color
648
+ if (Color* r_col = Cast<Color>(rhs)) {
649
+ Color_RGBA_Obj r_c = r_col->toRGBA();
650
+ try {
651
+ switch (op_type) {
652
+ case Sass_OP::EQ: return *l_c == *r_c ? bool_true : bool_false;
653
+ case Sass_OP::NEQ: return *l_c == *r_c ? bool_false : bool_true;
654
+ case Sass_OP::LT: return *l_c < *r_c ? bool_true : bool_false;
655
+ case Sass_OP::GTE: return *l_c < *r_c ? bool_false : bool_true;
656
+ case Sass_OP::LTE: return *l_c < *r_c || *l_c == *r_c ? bool_true : bool_false;
657
+ case Sass_OP::GT: return *l_c < *r_c || *l_c == *r_c ? bool_false : bool_true;
658
+ case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
659
+ return Operators::op_colors(op_type, *l_c, *r_c, options(), b_in->pstate());
660
+ default: break;
661
+ }
662
+ }
663
+ catch (Exception::OperationError& err)
664
+ {
665
+ traces.push_back(Backtrace(b_in->pstate()));
666
+ throw Exception::SassValueError(traces, b_in->pstate(), err);
667
+ }
668
+ }
669
+ // lhs is color and rhs is number
670
+ else if (Number* r_n = Cast<Number>(rhs)) {
671
+ try {
672
+ switch (op_type) {
673
+ case Sass_OP::EQ: return *l_c == *r_n ? bool_true : bool_false;
674
+ case Sass_OP::NEQ: return *l_c == *r_n ? bool_false : bool_true;
675
+ case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
676
+ return Operators::op_color_number(op_type, *l_c, *r_n, options(), b_in->pstate());
677
+ default: break;
678
+ }
679
+ }
680
+ catch (Exception::OperationError& err)
681
+ {
682
+ traces.push_back(Backtrace(b_in->pstate()));
683
+ throw Exception::SassValueError(traces, b_in->pstate(), err);
684
+ }
685
+ }
686
+ }
687
+
688
+ String_Schema_Obj ret_schema;
689
+
690
+ // only the last item will be used to eval the binary expression
691
+ if (String_Schema* s_l = Cast<String_Schema>(b->left())) {
692
+ if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) {
693
+ ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
694
+ Binary_ExpressionObj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
695
+ b->op(), s_l->last(), b->right());
696
+ bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // unverified
697
+ for (size_t i = 0; i < s_l->length() - 1; ++i) {
698
+ ret_schema->append(s_l->at(i)->perform(this));
699
+ }
700
+ ret_schema->append(bin_ex->perform(this));
701
+ return ret_schema->perform(this);
702
+ }
703
+ }
704
+ if (String_Schema* s_r = Cast<String_Schema>(b->right())) {
705
+
706
+ if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) {
707
+ ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
708
+ Binary_ExpressionObj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
709
+ b->op(), b->left(), s_r->first());
710
+ bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // verified
711
+ ret_schema->append(bin_ex->perform(this));
712
+ for (size_t i = 1; i < s_r->length(); ++i) {
713
+ ret_schema->append(s_r->at(i)->perform(this));
714
+ }
715
+ return ret_schema->perform(this);
716
+ }
717
+ }
718
+
719
+ // fully evaluate their values
720
+ if (op_type == Sass_OP::EQ ||
721
+ op_type == Sass_OP::NEQ ||
722
+ op_type == Sass_OP::GT ||
723
+ op_type == Sass_OP::GTE ||
724
+ op_type == Sass_OP::LT ||
725
+ op_type == Sass_OP::LTE)
726
+ {
727
+ LOCAL_FLAG(force, true);
728
+ lhs->is_expanded(false);
729
+ lhs->set_delayed(false);
730
+ lhs = lhs->perform(this);
731
+ rhs->is_expanded(false);
732
+ rhs->set_delayed(false);
733
+ rhs = rhs->perform(this);
734
+ }
735
+ else {
736
+ lhs = lhs->perform(this);
737
+ }
738
+
739
+ // not a logical connective, so go ahead and eval the rhs
740
+ rhs = rhs->perform(this);
741
+ AST_Node_Obj lu = lhs;
742
+ AST_Node_Obj ru = rhs;
743
+
744
+ Expression::Type l_type;
745
+ Expression::Type r_type;
746
+
747
+ // Is one of the operands an interpolant?
748
+ String_Schema_Obj s1 = Cast<String_Schema>(b->left());
749
+ String_Schema_Obj s2 = Cast<String_Schema>(b->right());
750
+ Binary_ExpressionObj b1 = Cast<Binary_Expression>(b->left());
751
+ Binary_ExpressionObj b2 = Cast<Binary_Expression>(b->right());
752
+
753
+ bool schema_op = false;
754
+
755
+ bool force_delay = (s2 && s2->is_left_interpolant()) ||
756
+ (s1 && s1->is_right_interpolant()) ||
757
+ (b1 && b1->is_right_interpolant()) ||
758
+ (b2 && b2->is_left_interpolant());
759
+
760
+ if ((s1 && s1->has_interpolants()) || (s2 && s2->has_interpolants()) || force_delay)
761
+ {
762
+ if (op_type == Sass_OP::DIV || op_type == Sass_OP::MUL || op_type == Sass_OP::MOD || op_type == Sass_OP::ADD || op_type == Sass_OP::SUB ||
763
+ op_type == Sass_OP::EQ) {
764
+ // If possible upgrade LHS to a number (for number to string compare)
765
+ if (String_Constant* str = Cast<String_Constant>(lhs)) {
766
+ sass::string value(str->value());
767
+ const char* start = value.c_str();
768
+ if (Prelexer::sequence < Prelexer::dimension, Prelexer::end_of_file >(start) != 0) {
769
+ lhs = Parser::lexed_dimension(b->pstate(), str->value());
770
+ }
771
+ }
772
+ // If possible upgrade RHS to a number (for string to number compare)
773
+ if (String_Constant* str = Cast<String_Constant>(rhs)) {
774
+ sass::string value(str->value());
775
+ const char* start = value.c_str();
776
+ if (Prelexer::sequence < Prelexer::dimension, Prelexer::number >(start) != 0) {
777
+ rhs = Parser::lexed_dimension(b->pstate(), str->value());
778
+ }
779
+ }
780
+ }
781
+
782
+ To_Value to_value(ctx);
783
+ ValueObj v_l = Cast<Value>(lhs->perform(&to_value));
784
+ ValueObj v_r = Cast<Value>(rhs->perform(&to_value));
785
+
786
+ if (force_delay) {
787
+ sass::string str("");
788
+ str += v_l->to_string(options());
789
+ if (b->op().ws_before) str += " ";
790
+ str += b->separator();
791
+ if (b->op().ws_after) str += " ";
792
+ str += v_r->to_string(options());
793
+ String_Constant* val = SASS_MEMORY_NEW(String_Constant, b->pstate(), str);
794
+ val->is_interpolant(b->left()->has_interpolant());
795
+ return val;
796
+ }
797
+ }
798
+
799
+ // see if it's a relational expression
800
+ try {
801
+ switch(op_type) {
802
+ case Sass_OP::EQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::eq(lhs, rhs));
803
+ case Sass_OP::NEQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::neq(lhs, rhs));
804
+ case Sass_OP::GT: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::gt(lhs, rhs));
805
+ case Sass_OP::GTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::gte(lhs, rhs));
806
+ case Sass_OP::LT: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::lt(lhs, rhs));
807
+ case Sass_OP::LTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::lte(lhs, rhs));
808
+ default: break;
809
+ }
810
+ }
811
+ catch (Exception::OperationError& err)
812
+ {
813
+ traces.push_back(Backtrace(b->pstate()));
814
+ throw Exception::SassValueError(traces, b->pstate(), err);
815
+ }
816
+
817
+ l_type = lhs->concrete_type();
818
+ r_type = rhs->concrete_type();
819
+
820
+ // ToDo: throw error in op functions
821
+ // ToDo: then catch and re-throw them
822
+ ExpressionObj rv;
823
+ try {
824
+ SourceSpan pstate(b->pstate());
825
+ if (l_type == Expression::NUMBER && r_type == Expression::NUMBER) {
826
+ Number* l_n = Cast<Number>(lhs);
827
+ Number* r_n = Cast<Number>(rhs);
828
+ l_n->reduce(); r_n->reduce();
829
+ rv = Operators::op_numbers(op_type, *l_n, *r_n, options(), pstate);
830
+ }
831
+ else if (l_type == Expression::NUMBER && r_type == Expression::COLOR) {
832
+ Number* l_n = Cast<Number>(lhs);
833
+ Color_RGBA_Obj r_c = Cast<Color>(rhs)->toRGBA();
834
+ rv = Operators::op_number_color(op_type, *l_n, *r_c, options(), pstate);
835
+ }
836
+ else if (l_type == Expression::COLOR && r_type == Expression::NUMBER) {
837
+ Color_RGBA_Obj l_c = Cast<Color>(lhs)->toRGBA();
838
+ Number* r_n = Cast<Number>(rhs);
839
+ rv = Operators::op_color_number(op_type, *l_c, *r_n, options(), pstate);
840
+ }
841
+ else if (l_type == Expression::COLOR && r_type == Expression::COLOR) {
842
+ Color_RGBA_Obj l_c = Cast<Color>(lhs)->toRGBA();
843
+ Color_RGBA_Obj r_c = Cast<Color>(rhs)->toRGBA();
844
+ rv = Operators::op_colors(op_type, *l_c, *r_c, options(), pstate);
845
+ }
846
+ else {
847
+ To_Value to_value(ctx);
848
+ // this will leak if perform does not return a value!
849
+ ValueObj v_l = Cast<Value>(lhs->perform(&to_value));
850
+ ValueObj v_r = Cast<Value>(rhs->perform(&to_value));
851
+ bool interpolant = b->is_right_interpolant() ||
852
+ b->is_left_interpolant() ||
853
+ b->is_interpolant();
854
+ if (op_type == Sass_OP::SUB) interpolant = false;
855
+ // if (op_type == Sass_OP::DIV) interpolant = true;
856
+ // check for type violations
857
+ if (l_type == Expression::MAP || l_type == Expression::FUNCTION_VAL) {
858
+ traces.push_back(Backtrace(v_l->pstate()));
859
+ throw Exception::InvalidValue(traces, *v_l);
860
+ }
861
+ if (r_type == Expression::MAP || l_type == Expression::FUNCTION_VAL) {
862
+ traces.push_back(Backtrace(v_r->pstate()));
863
+ throw Exception::InvalidValue(traces, *v_r);
864
+ }
865
+ Value* ex = Operators::op_strings(b->op(), *v_l, *v_r, options(), pstate, !interpolant); // pass true to compress
866
+ if (String_Constant* str = Cast<String_Constant>(ex))
867
+ {
868
+ if (str->concrete_type() == Expression::STRING)
869
+ {
870
+ String_Constant* lstr = Cast<String_Constant>(lhs);
871
+ String_Constant* rstr = Cast<String_Constant>(rhs);
872
+ if (op_type != Sass_OP::SUB) {
873
+ if (String_Constant* org = lstr ? lstr : rstr)
874
+ { str->quote_mark(org->quote_mark()); }
875
+ }
876
+ }
877
+ }
878
+ ex->is_interpolant(b->is_interpolant());
879
+ rv = ex;
880
+ }
881
+ }
882
+ catch (Exception::OperationError& err)
883
+ {
884
+ traces.push_back(Backtrace(b->pstate()));
885
+ // throw Exception::Base(b->pstate(), err.what());
886
+ throw Exception::SassValueError(traces, b->pstate(), err);
887
+ }
888
+
889
+ if (rv) {
890
+ if (schema_op) {
891
+ // XXX: this is never hit via spec tests
892
+ (*s2)[0] = rv;
893
+ rv = s2->perform(this);
894
+ }
895
+ }
896
+
897
+ return rv.detach();
898
+
899
+ }
900
+
901
+ Expression* Eval::operator()(Unary_Expression* u)
902
+ {
903
+ ExpressionObj operand = u->operand()->perform(this);
904
+ if (u->optype() == Unary_Expression::NOT) {
905
+ Boolean* result = SASS_MEMORY_NEW(Boolean, u->pstate(), (bool)*operand);
906
+ result->value(!result->value());
907
+ return result;
908
+ }
909
+ else if (Number_Obj nr = Cast<Number>(operand)) {
910
+ // negate value for minus unary expression
911
+ if (u->optype() == Unary_Expression::MINUS) {
912
+ Number_Obj cpy = SASS_MEMORY_COPY(nr);
913
+ cpy->value( - cpy->value() ); // negate value
914
+ return cpy.detach(); // return the copy
915
+ }
916
+ else if (u->optype() == Unary_Expression::SLASH) {
917
+ sass::string str = '/' + nr->to_string(options());
918
+ return SASS_MEMORY_NEW(String_Constant, u->pstate(), str);
919
+ }
920
+ // nothing for positive
921
+ return nr.detach();
922
+ }
923
+ else {
924
+ // Special cases: +/- variables which evaluate to null output just +/-,
925
+ // but +/- null itself outputs the string
926
+ if (operand->concrete_type() == Expression::NULL_VAL && Cast<Variable>(u->operand())) {
927
+ u->operand(SASS_MEMORY_NEW(String_Quoted, u->pstate(), ""));
928
+ }
929
+ // Never apply unary opertions on colors @see #2140
930
+ else if (Color* color = Cast<Color>(operand)) {
931
+ // Use the color name if this was eval with one
932
+ if (color->disp().length() > 0) {
933
+ Unary_ExpressionObj cpy = SASS_MEMORY_COPY(u);
934
+ cpy->operand(SASS_MEMORY_NEW(String_Constant, operand->pstate(), color->disp()));
935
+ return SASS_MEMORY_NEW(String_Quoted,
936
+ cpy->pstate(),
937
+ cpy->inspect());
938
+ }
939
+ }
940
+ else {
941
+ Unary_ExpressionObj cpy = SASS_MEMORY_COPY(u);
942
+ cpy->operand(operand);
943
+ return SASS_MEMORY_NEW(String_Quoted,
944
+ cpy->pstate(),
945
+ cpy->inspect());
946
+ }
947
+
948
+ return SASS_MEMORY_NEW(String_Quoted,
949
+ u->pstate(),
950
+ u->inspect());
951
+ }
952
+ // unreachable
953
+ return u;
954
+ }
955
+
956
+ Expression* Eval::operator()(Function_Call* c)
957
+ {
958
+ if (traces.size() > Constants::MaxCallStack) {
959
+ // XXX: this is never hit via spec tests
960
+ sass::ostream stm;
961
+ stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
962
+ error(stm.str(), c->pstate(), traces);
963
+ }
964
+
965
+ if (Cast<String_Schema>(c->sname())) {
966
+ ExpressionObj evaluated_name = c->sname()->perform(this);
967
+ ExpressionObj evaluated_args = c->arguments()->perform(this);
968
+ sass::string str(evaluated_name->to_string());
969
+ str += evaluated_args->to_string();
970
+ return SASS_MEMORY_NEW(String_Constant, c->pstate(), str);
971
+ }
972
+
973
+ sass::string name(Util::normalize_underscores(c->name()));
974
+ sass::string full_name(name + "[f]");
975
+
976
+ // we make a clone here, need to implement that further
977
+ Arguments_Obj args = c->arguments();
978
+
979
+ Env* env = environment();
980
+ if (!env->has(full_name) || (!c->via_call() && Prelexer::re_special_fun(name.c_str()))) {
981
+ if (!env->has("*[f]")) {
982
+ for (Argument_Obj arg : args->elements()) {
983
+ if (List_Obj ls = Cast<List>(arg->value())) {
984
+ if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate(), traces);
985
+ }
986
+ }
987
+ args = Cast<Arguments>(args->perform(this));
988
+ Function_Call_Obj lit = SASS_MEMORY_NEW(Function_Call,
989
+ c->pstate(),
990
+ c->name(),
991
+ args);
992
+ if (args->has_named_arguments()) {
993
+ error("Plain CSS function " + c->name() + " doesn't support keyword arguments", c->pstate(), traces);
994
+ }
995
+ String_Quoted* str = SASS_MEMORY_NEW(String_Quoted,
996
+ c->pstate(),
997
+ lit->to_string(options()));
998
+ str->is_interpolant(c->is_interpolant());
999
+ return str;
1000
+ } else {
1001
+ // call generic function
1002
+ full_name = "*[f]";
1003
+ }
1004
+ }
1005
+
1006
+ // further delay for calls
1007
+ if (full_name != "call[f]") {
1008
+ args->set_delayed(false); // verified
1009
+ }
1010
+ if (full_name != "if[f]") {
1011
+ args = Cast<Arguments>(args->perform(this));
1012
+ }
1013
+ Definition* def = Cast<Definition>((*env)[full_name]);
1014
+
1015
+ if (c->func()) def = c->func()->definition();
1016
+
1017
+ if (def->is_overload_stub()) {
1018
+ sass::ostream ss;
1019
+ size_t L = args->length();
1020
+ // account for rest arguments
1021
+ if (args->has_rest_argument() && args->length() > 0) {
1022
+ // get the rest arguments list
1023
+ List* rest = Cast<List>(args->last()->value());
1024
+ // arguments before rest argument plus rest
1025
+ if (rest) L += rest->length() - 1;
1026
+ }
1027
+ ss << full_name << L;
1028
+ full_name = ss.str();
1029
+ sass::string resolved_name(full_name);
1030
+ if (!env->has(resolved_name)) error("overloaded function `" + sass::string(c->name()) + "` given wrong number of arguments", c->pstate(), traces);
1031
+ def = Cast<Definition>((*env)[resolved_name]);
1032
+ }
1033
+
1034
+ ExpressionObj result = c;
1035
+ Block_Obj body = def->block();
1036
+ Native_Function func = def->native_function();
1037
+ Sass_Function_Entry c_function = def->c_function();
1038
+
1039
+ if (c->is_css()) return result.detach();
1040
+
1041
+ Parameters_Obj params = def->parameters();
1042
+ Env fn_env(def->environment());
1043
+ env_stack().push_back(&fn_env);
1044
+
1045
+ if (func || body) {
1046
+ bind(sass::string("Function"), c->name(), params, args, &fn_env, this, traces);
1047
+ sass::string msg(", in function `" + c->name() + "`");
1048
+ traces.push_back(Backtrace(c->pstate(), msg));
1049
+ callee_stack().push_back({
1050
+ c->name().c_str(),
1051
+ c->pstate().getPath(),
1052
+ c->pstate().getLine(),
1053
+ c->pstate().getColumn(),
1054
+ SASS_CALLEE_FUNCTION,
1055
+ { env }
1056
+ });
1057
+
1058
+ // eval the body if user-defined or special, invoke underlying CPP function if native
1059
+ if (body /* && !Prelexer::re_special_fun(name.c_str()) */) {
1060
+ result = body->perform(this);
1061
+ }
1062
+ else if (func) {
1063
+ result = func(fn_env, *env, ctx, def->signature(), c->pstate(), traces, exp.getSelectorStack(), exp.originalStack);
1064
+ }
1065
+ if (!result) {
1066
+ error(sass::string("Function ") + c->name() + " finished without @return", c->pstate(), traces);
1067
+ }
1068
+ callee_stack().pop_back();
1069
+ traces.pop_back();
1070
+ }
1071
+
1072
+ // else if it's a user-defined c function
1073
+ // convert call into C-API compatible form
1074
+ else if (c_function) {
1075
+ Sass_Function_Fn c_func = sass_function_get_function(c_function);
1076
+ if (full_name == "*[f]") {
1077
+ String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, c->pstate(), c->name());
1078
+ Arguments_Obj new_args = SASS_MEMORY_NEW(Arguments, c->pstate());
1079
+ new_args->append(SASS_MEMORY_NEW(Argument, c->pstate(), str));
1080
+ new_args->concat(args);
1081
+ args = new_args;
1082
+ }
1083
+
1084
+ // populates env with default values for params
1085
+ sass::string ff(c->name());
1086
+ bind(sass::string("Function"), c->name(), params, args, &fn_env, this, traces);
1087
+ sass::string msg(", in function `" + c->name() + "`");
1088
+ traces.push_back(Backtrace(c->pstate(), msg));
1089
+ callee_stack().push_back({
1090
+ c->name().c_str(),
1091
+ c->pstate().getPath(),
1092
+ c->pstate().getLine(),
1093
+ c->pstate().getColumn(),
1094
+ SASS_CALLEE_C_FUNCTION,
1095
+ { env }
1096
+ });
1097
+
1098
+ AST2C ast2c;
1099
+ union Sass_Value* c_args = sass_make_list(params->length(), SASS_COMMA, false);
1100
+ for(size_t i = 0; i < params->length(); i++) {
1101
+ Parameter_Obj param = params->at(i);
1102
+ sass::string key = param->name();
1103
+ AST_Node_Obj node = fn_env.get_local(key);
1104
+ ExpressionObj arg = Cast<Expression>(node);
1105
+ sass_list_set_value(c_args, i, arg->perform(&ast2c));
1106
+ }
1107
+ union Sass_Value* c_val = c_func(c_args, c_function, compiler());
1108
+ if (sass_value_get_tag(c_val) == SASS_ERROR) {
1109
+ sass::string message("error in C function " + c->name() + ": " + sass_error_get_message(c_val));
1110
+ sass_delete_value(c_val);
1111
+ sass_delete_value(c_args);
1112
+ error(message, c->pstate(), traces);
1113
+ } else if (sass_value_get_tag(c_val) == SASS_WARNING) {
1114
+ sass::string message("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val));
1115
+ sass_delete_value(c_val);
1116
+ sass_delete_value(c_args);
1117
+ error(message, c->pstate(), traces);
1118
+ }
1119
+ result = c2ast(c_val, traces, c->pstate());
1120
+
1121
+ callee_stack().pop_back();
1122
+ traces.pop_back();
1123
+ sass_delete_value(c_args);
1124
+ if (c_val != c_args)
1125
+ sass_delete_value(c_val);
1126
+ }
1127
+
1128
+ // link back to function definition
1129
+ // only do this for custom functions
1130
+ if (result->pstate().getSrcId() == sass::string::npos)
1131
+ result->pstate(c->pstate());
1132
+
1133
+ result = result->perform(this);
1134
+ result->is_interpolant(c->is_interpolant());
1135
+ env_stack().pop_back();
1136
+ return result.detach();
1137
+ }
1138
+
1139
+ Expression* Eval::operator()(Variable* v)
1140
+ {
1141
+ ExpressionObj value;
1142
+ Env* env = environment();
1143
+ const sass::string& name(v->name());
1144
+ EnvResult rv(env->find(name));
1145
+ if (rv.found) value = static_cast<Expression*>(rv.it->second.ptr());
1146
+ else error("Undefined variable: \"" + v->name() + "\".", v->pstate(), traces);
1147
+ if (Argument* arg = Cast<Argument>(value)) value = arg->value();
1148
+ if (Number* nr = Cast<Number>(value)) nr->zero(true); // force flag
1149
+ value->is_interpolant(v->is_interpolant());
1150
+ if (force) value->is_expanded(false);
1151
+ value->set_delayed(false); // verified
1152
+ value = value->perform(this);
1153
+ if(!force) rv.it->second = value;
1154
+ return value.detach();
1155
+ }
1156
+
1157
+ Expression* Eval::operator()(Color_RGBA* c)
1158
+ {
1159
+ return c;
1160
+ }
1161
+
1162
+ Expression* Eval::operator()(Color_HSLA* c)
1163
+ {
1164
+ return c;
1165
+ }
1166
+
1167
+ Expression* Eval::operator()(Number* n)
1168
+ {
1169
+ return n;
1170
+ }
1171
+
1172
+ Expression* Eval::operator()(Boolean* b)
1173
+ {
1174
+ return b;
1175
+ }
1176
+
1177
+ void Eval::interpolation(Context& ctx, sass::string& res, ExpressionObj ex, bool into_quotes, bool was_itpl) {
1178
+
1179
+ bool needs_closing_brace = false;
1180
+
1181
+ if (Arguments* args = Cast<Arguments>(ex)) {
1182
+ List* ll = SASS_MEMORY_NEW(List, args->pstate(), 0, SASS_COMMA);
1183
+ for(auto arg : args->elements()) {
1184
+ ll->append(arg->value());
1185
+ }
1186
+ ll->is_interpolant(args->is_interpolant());
1187
+ needs_closing_brace = true;
1188
+ res += "(";
1189
+ ex = ll;
1190
+ }
1191
+ if (Number* nr = Cast<Number>(ex)) {
1192
+ Number reduced(nr);
1193
+ reduced.reduce();
1194
+ if (!reduced.is_valid_css_unit()) {
1195
+ traces.push_back(Backtrace(nr->pstate()));
1196
+ throw Exception::InvalidValue(traces, *nr);
1197
+ }
1198
+ }
1199
+ if (Argument* arg = Cast<Argument>(ex)) {
1200
+ ex = arg->value();
1201
+ }
1202
+ if (String_Quoted* sq = Cast<String_Quoted>(ex)) {
1203
+ if (was_itpl) {
1204
+ bool was_interpolant = ex->is_interpolant();
1205
+ ex = SASS_MEMORY_NEW(String_Constant, sq->pstate(), sq->value());
1206
+ ex->is_interpolant(was_interpolant);
1207
+ }
1208
+ }
1209
+
1210
+ if (Cast<Null>(ex)) { return; }
1211
+
1212
+ // parent selector needs another go
1213
+ if (Cast<Parent_Reference>(ex)) {
1214
+ // XXX: this is never hit via spec tests
1215
+ ex = ex->perform(this);
1216
+ }
1217
+
1218
+ if (List* l = Cast<List>(ex)) {
1219
+ List_Obj ll = SASS_MEMORY_NEW(List, l->pstate(), 0, l->separator());
1220
+ // this fixes an issue with bourbon sample, not really sure why
1221
+ // if (l->size() && Cast<Null>((*l)[0])) { res += ""; }
1222
+ for(ExpressionObj item : *l) {
1223
+ item->is_interpolant(l->is_interpolant());
1224
+ sass::string rl(""); interpolation(ctx, rl, item, into_quotes, l->is_interpolant());
1225
+ bool is_null = Cast<Null>(item) != 0; // rl != ""
1226
+ if (!is_null) ll->append(SASS_MEMORY_NEW(String_Quoted, item->pstate(), rl));
1227
+ }
1228
+ // Check indicates that we probably should not get a list
1229
+ // here. Normally single list items are already unwrapped.
1230
+ if (l->size() > 1) {
1231
+ // string_to_output would fail "#{'_\a' '_\a'}";
1232
+ sass::string str(ll->to_string(options()));
1233
+ str = read_hex_escapes(str); // read escapes
1234
+ newline_to_space(str); // replace directly
1235
+ res += str; // append to result string
1236
+ } else {
1237
+ res += (ll->to_string(options()));
1238
+ }
1239
+ ll->is_interpolant(l->is_interpolant());
1240
+ }
1241
+
1242
+ // Value
1243
+ // Function_Call
1244
+ // Selector_List
1245
+ // String_Quoted
1246
+ // String_Constant
1247
+ // Binary_Expression
1248
+ else {
1249
+ // ex = ex->perform(this);
1250
+ if (into_quotes && ex->is_interpolant()) {
1251
+ res += evacuate_escapes(ex ? ex->to_string(options()) : "");
1252
+ } else {
1253
+ sass::string str(ex ? ex->to_string(options()) : "");
1254
+ if (into_quotes) str = read_hex_escapes(str);
1255
+ res += str; // append to result string
1256
+ }
1257
+ }
1258
+
1259
+ if (needs_closing_brace) res += ")";
1260
+
1261
+ }
1262
+
1263
+ Expression* Eval::operator()(String_Schema* s)
1264
+ {
1265
+ size_t L = s->length();
1266
+ bool into_quotes = false;
1267
+ if (L > 1) {
1268
+ if (!Cast<String_Quoted>((*s)[0]) && !Cast<String_Quoted>((*s)[L - 1])) {
1269
+ if (String_Constant* l = Cast<String_Constant>((*s)[0])) {
1270
+ if (String_Constant* r = Cast<String_Constant>((*s)[L - 1])) {
1271
+ if (r->value().size() > 0) {
1272
+ if (l->value()[0] == '"' && r->value()[r->value().size() - 1] == '"') into_quotes = true;
1273
+ if (l->value()[0] == '\'' && r->value()[r->value().size() - 1] == '\'') into_quotes = true;
1274
+ }
1275
+ }
1276
+ }
1277
+ }
1278
+ }
1279
+ bool was_quoted = false;
1280
+ bool was_interpolant = false;
1281
+ sass::string res("");
1282
+ for (size_t i = 0; i < L; ++i) {
1283
+ bool is_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
1284
+ if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
1285
+ else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
1286
+ ExpressionObj ex = (*s)[i]->perform(this);
1287
+ interpolation(ctx, res, ex, into_quotes, ex->is_interpolant());
1288
+ was_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
1289
+ was_interpolant = (*s)[i]->is_interpolant();
1290
+
1291
+ }
1292
+ if (!s->is_interpolant()) {
1293
+ if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(Null, s->pstate());
1294
+ String_Constant_Obj str = SASS_MEMORY_NEW(String_Constant, s->pstate(), res, s->css());
1295
+ return str.detach();
1296
+ }
1297
+ // string schema seems to have a special unquoting behavior (also handles "nested" quotes)
1298
+ String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), res, 0, false, false, false, s->css());
1299
+ // if (s->is_interpolant()) str->quote_mark(0);
1300
+ // String_Constant* str = SASS_MEMORY_NEW(String_Constant, s->pstate(), res);
1301
+ if (str->quote_mark()) str->quote_mark('*');
1302
+ else if (!is_in_comment) str->value(string_to_output(str->value()));
1303
+ str->is_interpolant(s->is_interpolant());
1304
+ return str.detach();
1305
+ }
1306
+
1307
+
1308
+ Expression* Eval::operator()(String_Constant* s)
1309
+ {
1310
+ return s;
1311
+ }
1312
+
1313
+ Expression* Eval::operator()(String_Quoted* s)
1314
+ {
1315
+ String_Quoted* str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), "");
1316
+ str->value(s->value());
1317
+ str->quote_mark(s->quote_mark());
1318
+ str->is_interpolant(s->is_interpolant());
1319
+ return str;
1320
+ }
1321
+
1322
+ Expression* Eval::operator()(SupportsOperation* c)
1323
+ {
1324
+ Expression* left = c->left()->perform(this);
1325
+ Expression* right = c->right()->perform(this);
1326
+ SupportsOperation* cc = SASS_MEMORY_NEW(SupportsOperation,
1327
+ c->pstate(),
1328
+ Cast<SupportsCondition>(left),
1329
+ Cast<SupportsCondition>(right),
1330
+ c->operand());
1331
+ return cc;
1332
+ }
1333
+
1334
+ Expression* Eval::operator()(SupportsNegation* c)
1335
+ {
1336
+ Expression* condition = c->condition()->perform(this);
1337
+ SupportsNegation* cc = SASS_MEMORY_NEW(SupportsNegation,
1338
+ c->pstate(),
1339
+ Cast<SupportsCondition>(condition));
1340
+ return cc;
1341
+ }
1342
+
1343
+ Expression* Eval::operator()(SupportsDeclaration* c)
1344
+ {
1345
+ Expression* feature = c->feature()->perform(this);
1346
+ Expression* value = c->value()->perform(this);
1347
+ SupportsDeclaration* cc = SASS_MEMORY_NEW(SupportsDeclaration,
1348
+ c->pstate(),
1349
+ feature,
1350
+ value);
1351
+ return cc;
1352
+ }
1353
+
1354
+ Expression* Eval::operator()(Supports_Interpolation* c)
1355
+ {
1356
+ Expression* value = c->value()->perform(this);
1357
+ Supports_Interpolation* cc = SASS_MEMORY_NEW(Supports_Interpolation,
1358
+ c->pstate(),
1359
+ value);
1360
+ return cc;
1361
+ }
1362
+
1363
+ Expression* Eval::operator()(At_Root_Query* e)
1364
+ {
1365
+ ExpressionObj feature = e->feature();
1366
+ feature = (feature ? feature->perform(this) : 0);
1367
+ ExpressionObj value = e->value();
1368
+ value = (value ? value->perform(this) : 0);
1369
+ Expression* ee = SASS_MEMORY_NEW(At_Root_Query,
1370
+ e->pstate(),
1371
+ Cast<String>(feature),
1372
+ value);
1373
+ return ee;
1374
+ }
1375
+
1376
+ Media_Query* Eval::operator()(Media_Query* q)
1377
+ {
1378
+ String_Obj t = q->media_type();
1379
+ t = static_cast<String*>(t.isNull() ? 0 : t->perform(this));
1380
+ Media_Query_Obj qq = SASS_MEMORY_NEW(Media_Query,
1381
+ q->pstate(),
1382
+ t,
1383
+ q->length(),
1384
+ q->is_negated(),
1385
+ q->is_restricted());
1386
+ for (size_t i = 0, L = q->length(); i < L; ++i) {
1387
+ qq->append(static_cast<Media_Query_Expression*>((*q)[i]->perform(this)));
1388
+ }
1389
+ return qq.detach();
1390
+ }
1391
+
1392
+ Expression* Eval::operator()(Media_Query_Expression* e)
1393
+ {
1394
+ ExpressionObj feature = e->feature();
1395
+ feature = (feature ? feature->perform(this) : 0);
1396
+ if (feature && Cast<String_Quoted>(feature)) {
1397
+ feature = SASS_MEMORY_NEW(String_Quoted,
1398
+ feature->pstate(),
1399
+ Cast<String_Quoted>(feature)->value());
1400
+ }
1401
+ ExpressionObj value = e->value();
1402
+ value = (value ? value->perform(this) : 0);
1403
+ if (value && Cast<String_Quoted>(value)) {
1404
+ // XXX: this is never hit via spec tests
1405
+ value = SASS_MEMORY_NEW(String_Quoted,
1406
+ value->pstate(),
1407
+ Cast<String_Quoted>(value)->value());
1408
+ }
1409
+ return SASS_MEMORY_NEW(Media_Query_Expression,
1410
+ e->pstate(),
1411
+ feature,
1412
+ value,
1413
+ e->is_interpolated());
1414
+ }
1415
+
1416
+ Expression* Eval::operator()(Null* n)
1417
+ {
1418
+ return n;
1419
+ }
1420
+
1421
+ Expression* Eval::operator()(Argument* a)
1422
+ {
1423
+ ExpressionObj val = a->value()->perform(this);
1424
+ bool is_rest_argument = a->is_rest_argument();
1425
+ bool is_keyword_argument = a->is_keyword_argument();
1426
+
1427
+ if (a->is_rest_argument()) {
1428
+ if (val->concrete_type() == Expression::MAP) {
1429
+ is_rest_argument = false;
1430
+ is_keyword_argument = true;
1431
+ }
1432
+ else if(val->concrete_type() != Expression::LIST) {
1433
+ List_Obj wrapper = SASS_MEMORY_NEW(List,
1434
+ val->pstate(),
1435
+ 0,
1436
+ SASS_COMMA,
1437
+ true);
1438
+ wrapper->append(val);
1439
+ val = wrapper;
1440
+ }
1441
+ }
1442
+ return SASS_MEMORY_NEW(Argument,
1443
+ a->pstate(),
1444
+ val,
1445
+ a->name(),
1446
+ is_rest_argument,
1447
+ is_keyword_argument);
1448
+ }
1449
+
1450
+ Expression* Eval::operator()(Arguments* a)
1451
+ {
1452
+ Arguments_Obj aa = SASS_MEMORY_NEW(Arguments, a->pstate());
1453
+ if (a->length() == 0) return aa.detach();
1454
+ for (size_t i = 0, L = a->length(); i < L; ++i) {
1455
+ ExpressionObj rv = (*a)[i]->perform(this);
1456
+ Argument* arg = Cast<Argument>(rv);
1457
+ if (!(arg->is_rest_argument() || arg->is_keyword_argument())) {
1458
+ aa->append(arg);
1459
+ }
1460
+ }
1461
+
1462
+ if (a->has_rest_argument()) {
1463
+ ExpressionObj rest = a->get_rest_argument()->perform(this);
1464
+ ExpressionObj splat = Cast<Argument>(rest)->value()->perform(this);
1465
+
1466
+ Sass_Separator separator = SASS_COMMA;
1467
+ List* ls = Cast<List>(splat);
1468
+ Map* ms = Cast<Map>(splat);
1469
+
1470
+ List_Obj arglist = SASS_MEMORY_NEW(List,
1471
+ splat->pstate(),
1472
+ 0,
1473
+ ls ? ls->separator() : separator,
1474
+ true);
1475
+
1476
+ if (ls && ls->is_arglist()) {
1477
+ arglist->concat(ls);
1478
+ } else if (ms) {
1479
+ aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), ms, "", false, true));
1480
+ } else if (ls) {
1481
+ arglist->concat(ls);
1482
+ } else {
1483
+ arglist->append(splat);
1484
+ }
1485
+ if (arglist->length()) {
1486
+ aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), arglist, "", true));
1487
+ }
1488
+ }
1489
+
1490
+ if (a->has_keyword_argument()) {
1491
+ ExpressionObj rv = a->get_keyword_argument()->perform(this);
1492
+ Argument* rvarg = Cast<Argument>(rv);
1493
+ ExpressionObj kwarg = rvarg->value()->perform(this);
1494
+
1495
+ aa->append(SASS_MEMORY_NEW(Argument, kwarg->pstate(), kwarg, "", false, true));
1496
+ }
1497
+ return aa.detach();
1498
+ }
1499
+
1500
+ Expression* Eval::operator()(Comment* c)
1501
+ {
1502
+ return 0;
1503
+ }
1504
+
1505
+ SelectorList* Eval::operator()(Selector_Schema* s)
1506
+ {
1507
+ LOCAL_FLAG(is_in_selector_schema, true);
1508
+ // the parser will look for a brace to end the selector
1509
+ ExpressionObj sel = s->contents()->perform(this);
1510
+ sass::string result_str(sel->to_string(options()));
1511
+ result_str = unquote(Util::rtrim(result_str));
1512
+ ItplFile* source = SASS_MEMORY_NEW(ItplFile,
1513
+ result_str.c_str(), s->pstate());
1514
+ Parser p(source, ctx, traces);
1515
+
1516
+ // If a schema contains a reference to parent it is already
1517
+ // connected to it, so don't connect implicitly anymore
1518
+ SelectorListObj parsed = p.parseSelectorList(true);
1519
+ flag_is_in_selector_schema.reset();
1520
+ return parsed.detach();
1521
+ }
1522
+
1523
+ Expression* Eval::operator()(Parent_Reference* p)
1524
+ {
1525
+ if (SelectorListObj pr = exp.original()) {
1526
+ return operator()(pr);
1527
+ } else {
1528
+ return SASS_MEMORY_NEW(Null, p->pstate());
1529
+ }
1530
+ }
1531
+
1532
+ SimpleSelector* Eval::operator()(SimpleSelector* s)
1533
+ {
1534
+ return s;
1535
+ }
1536
+
1537
+ PseudoSelector* Eval::operator()(PseudoSelector* pseudo)
1538
+ {
1539
+ // ToDo: should we eval selector?
1540
+ return pseudo;
1541
+ };
1542
+
1543
+ }