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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.gitmodules +3 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.md +97 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +51 -0
- data/ext/depend +4 -0
- data/ext/extconf.rb +92 -0
- data/ext/libsass/VERSION +1 -0
- data/ext/libsass/contrib/plugin.cpp +60 -0
- data/ext/libsass/include/sass/base.h +97 -0
- data/ext/libsass/include/sass/context.h +174 -0
- data/ext/libsass/include/sass/functions.h +139 -0
- data/ext/libsass/include/sass/values.h +145 -0
- data/ext/libsass/include/sass/version.h +12 -0
- data/ext/libsass/include/sass.h +15 -0
- data/ext/libsass/include/sass2scss.h +120 -0
- data/ext/libsass/src/MurmurHash2.hpp +91 -0
- data/ext/libsass/src/ast.cpp +953 -0
- data/ext/libsass/src/ast.hpp +1064 -0
- data/ext/libsass/src/ast2c.cpp +80 -0
- data/ext/libsass/src/ast2c.hpp +39 -0
- data/ext/libsass/src/ast_def_macros.hpp +140 -0
- data/ext/libsass/src/ast_fwd_decl.cpp +31 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +274 -0
- data/ext/libsass/src/ast_helpers.hpp +316 -0
- data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
- data/ext/libsass/src/ast_sel_super.cpp +539 -0
- data/ext/libsass/src/ast_sel_unify.cpp +275 -0
- data/ext/libsass/src/ast_sel_weave.cpp +616 -0
- data/ext/libsass/src/ast_selectors.cpp +1070 -0
- data/ext/libsass/src/ast_selectors.hpp +523 -0
- data/ext/libsass/src/ast_supports.cpp +114 -0
- data/ext/libsass/src/ast_supports.hpp +121 -0
- data/ext/libsass/src/ast_values.cpp +1154 -0
- data/ext/libsass/src/ast_values.hpp +498 -0
- data/ext/libsass/src/b64/cencode.h +32 -0
- data/ext/libsass/src/b64/encode.h +79 -0
- data/ext/libsass/src/backtrace.cpp +50 -0
- data/ext/libsass/src/backtrace.hpp +29 -0
- data/ext/libsass/src/base64vlq.cpp +47 -0
- data/ext/libsass/src/base64vlq.hpp +30 -0
- data/ext/libsass/src/bind.cpp +312 -0
- data/ext/libsass/src/bind.hpp +15 -0
- data/ext/libsass/src/c2ast.cpp +64 -0
- data/ext/libsass/src/c2ast.hpp +14 -0
- data/ext/libsass/src/c99func.c +54 -0
- data/ext/libsass/src/cencode.c +106 -0
- data/ext/libsass/src/check_nesting.cpp +393 -0
- data/ext/libsass/src/check_nesting.hpp +70 -0
- data/ext/libsass/src/color_maps.cpp +652 -0
- data/ext/libsass/src/color_maps.hpp +323 -0
- data/ext/libsass/src/color_spaces.cpp +241 -0
- data/ext/libsass/src/color_spaces.hpp +227 -0
- data/ext/libsass/src/constants.cpp +199 -0
- data/ext/libsass/src/constants.hpp +200 -0
- data/ext/libsass/src/context.cpp +870 -0
- data/ext/libsass/src/context.hpp +140 -0
- data/ext/libsass/src/cssize.cpp +521 -0
- data/ext/libsass/src/cssize.hpp +71 -0
- data/ext/libsass/src/dart_helpers.hpp +199 -0
- data/ext/libsass/src/debug.hpp +43 -0
- data/ext/libsass/src/debugger.hpp +964 -0
- data/ext/libsass/src/emitter.cpp +297 -0
- data/ext/libsass/src/emitter.hpp +101 -0
- data/ext/libsass/src/environment.cpp +260 -0
- data/ext/libsass/src/environment.hpp +124 -0
- data/ext/libsass/src/error_handling.cpp +239 -0
- data/ext/libsass/src/error_handling.hpp +248 -0
- data/ext/libsass/src/eval.cpp +1543 -0
- data/ext/libsass/src/eval.hpp +110 -0
- data/ext/libsass/src/eval_selectors.cpp +75 -0
- data/ext/libsass/src/expand.cpp +875 -0
- data/ext/libsass/src/expand.hpp +98 -0
- data/ext/libsass/src/extender.cpp +1226 -0
- data/ext/libsass/src/extender.hpp +399 -0
- data/ext/libsass/src/extension.cpp +43 -0
- data/ext/libsass/src/extension.hpp +89 -0
- data/ext/libsass/src/file.cpp +531 -0
- data/ext/libsass/src/file.hpp +124 -0
- data/ext/libsass/src/fn_colors.cpp +836 -0
- data/ext/libsass/src/fn_colors.hpp +99 -0
- data/ext/libsass/src/fn_lists.cpp +285 -0
- data/ext/libsass/src/fn_lists.hpp +34 -0
- data/ext/libsass/src/fn_maps.cpp +94 -0
- data/ext/libsass/src/fn_maps.hpp +30 -0
- data/ext/libsass/src/fn_miscs.cpp +248 -0
- data/ext/libsass/src/fn_miscs.hpp +40 -0
- data/ext/libsass/src/fn_numbers.cpp +246 -0
- data/ext/libsass/src/fn_numbers.hpp +45 -0
- data/ext/libsass/src/fn_selectors.cpp +205 -0
- data/ext/libsass/src/fn_selectors.hpp +35 -0
- data/ext/libsass/src/fn_strings.cpp +268 -0
- data/ext/libsass/src/fn_strings.hpp +34 -0
- data/ext/libsass/src/fn_utils.cpp +159 -0
- data/ext/libsass/src/fn_utils.hpp +62 -0
- data/ext/libsass/src/inspect.cpp +1126 -0
- data/ext/libsass/src/inspect.hpp +101 -0
- data/ext/libsass/src/json.cpp +1436 -0
- data/ext/libsass/src/json.hpp +117 -0
- data/ext/libsass/src/kwd_arg_macros.hpp +28 -0
- data/ext/libsass/src/lexer.cpp +122 -0
- data/ext/libsass/src/lexer.hpp +304 -0
- data/ext/libsass/src/listize.cpp +70 -0
- data/ext/libsass/src/listize.hpp +37 -0
- data/ext/libsass/src/mapping.hpp +19 -0
- data/ext/libsass/src/memory/allocator.cpp +48 -0
- data/ext/libsass/src/memory/allocator.hpp +138 -0
- data/ext/libsass/src/memory/config.hpp +20 -0
- data/ext/libsass/src/memory/memory_pool.hpp +186 -0
- data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
- data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
- data/ext/libsass/src/memory.hpp +12 -0
- data/ext/libsass/src/operation.hpp +223 -0
- data/ext/libsass/src/operators.cpp +267 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/ordered_map.hpp +112 -0
- data/ext/libsass/src/output.cpp +320 -0
- data/ext/libsass/src/output.hpp +47 -0
- data/ext/libsass/src/parser.cpp +3059 -0
- data/ext/libsass/src/parser.hpp +395 -0
- data/ext/libsass/src/parser_selectors.cpp +189 -0
- data/ext/libsass/src/permutate.hpp +164 -0
- data/ext/libsass/src/plugins.cpp +188 -0
- data/ext/libsass/src/plugins.hpp +57 -0
- data/ext/libsass/src/position.cpp +163 -0
- data/ext/libsass/src/position.hpp +147 -0
- data/ext/libsass/src/prelexer.cpp +1780 -0
- data/ext/libsass/src/prelexer.hpp +484 -0
- data/ext/libsass/src/remove_placeholders.cpp +86 -0
- data/ext/libsass/src/remove_placeholders.hpp +37 -0
- data/ext/libsass/src/sass.cpp +156 -0
- data/ext/libsass/src/sass.hpp +147 -0
- data/ext/libsass/src/sass2scss.cpp +895 -0
- data/ext/libsass/src/sass_context.cpp +742 -0
- data/ext/libsass/src/sass_context.hpp +129 -0
- data/ext/libsass/src/sass_functions.cpp +210 -0
- data/ext/libsass/src/sass_functions.hpp +50 -0
- data/ext/libsass/src/sass_values.cpp +362 -0
- data/ext/libsass/src/sass_values.hpp +82 -0
- data/ext/libsass/src/settings.hpp +19 -0
- data/ext/libsass/src/source.cpp +69 -0
- data/ext/libsass/src/source.hpp +95 -0
- data/ext/libsass/src/source_data.hpp +32 -0
- data/ext/libsass/src/source_map.cpp +202 -0
- data/ext/libsass/src/source_map.hpp +65 -0
- data/ext/libsass/src/stylesheet.cpp +22 -0
- data/ext/libsass/src/stylesheet.hpp +57 -0
- data/ext/libsass/src/to_value.cpp +114 -0
- data/ext/libsass/src/to_value.hpp +46 -0
- data/ext/libsass/src/units.cpp +507 -0
- data/ext/libsass/src/units.hpp +110 -0
- data/ext/libsass/src/utf8/checked.h +336 -0
- data/ext/libsass/src/utf8/core.h +332 -0
- data/ext/libsass/src/utf8/unchecked.h +235 -0
- data/ext/libsass/src/utf8.h +34 -0
- data/ext/libsass/src/utf8_string.cpp +104 -0
- data/ext/libsass/src/utf8_string.hpp +38 -0
- data/ext/libsass/src/util.cpp +723 -0
- data/ext/libsass/src/util.hpp +105 -0
- data/ext/libsass/src/util_string.cpp +125 -0
- data/ext/libsass/src/util_string.hpp +73 -0
- data/ext/libsass/src/values.cpp +140 -0
- data/ext/libsass/src/values.hpp +12 -0
- data/lib/sassc/dependency.rb +17 -0
- data/lib/sassc/engine.rb +141 -0
- data/lib/sassc/error.rb +37 -0
- data/lib/sassc/functions_handler.rb +73 -0
- data/lib/sassc/import_handler.rb +50 -0
- data/lib/sassc/importer.rb +31 -0
- data/lib/sassc/native/native_context_api.rb +147 -0
- data/lib/sassc/native/native_functions_api.rb +159 -0
- data/lib/sassc/native/sass2scss_api.rb +10 -0
- data/lib/sassc/native/sass_input_style.rb +13 -0
- data/lib/sassc/native/sass_output_style.rb +12 -0
- data/lib/sassc/native/sass_value.rb +97 -0
- data/lib/sassc/native/string_list.rb +10 -0
- data/lib/sassc/native.rb +64 -0
- data/lib/sassc/sass_2_scss.rb +9 -0
- data/lib/sassc/script/functions.rb +8 -0
- data/lib/sassc/script/value/bool.rb +32 -0
- data/lib/sassc/script/value/color.rb +95 -0
- data/lib/sassc/script/value/list.rb +136 -0
- data/lib/sassc/script/value/map.rb +69 -0
- data/lib/sassc/script/value/number.rb +389 -0
- data/lib/sassc/script/value/string.rb +96 -0
- data/lib/sassc/script/value.rb +137 -0
- data/lib/sassc/script/value_conversion/base.rb +13 -0
- data/lib/sassc/script/value_conversion/bool.rb +13 -0
- data/lib/sassc/script/value_conversion/color.rb +18 -0
- data/lib/sassc/script/value_conversion/list.rb +25 -0
- data/lib/sassc/script/value_conversion/map.rb +21 -0
- data/lib/sassc/script/value_conversion/number.rb +13 -0
- data/lib/sassc/script/value_conversion/string.rb +17 -0
- data/lib/sassc/script/value_conversion.rb +69 -0
- data/lib/sassc/script.rb +17 -0
- data/lib/sassc/util/normalized_map.rb +117 -0
- data/lib/sassc/util.rb +231 -0
- data/lib/sassc/version.rb +5 -0
- data/lib/sassc.rb +57 -0
- data/sassc.gemspec +69 -0
- data/test/css_color_level4_test.rb +168 -0
- data/test/custom_importer_test.rb +127 -0
- data/test/engine_test.rb +314 -0
- data/test/error_test.rb +29 -0
- data/test/fixtures/paths.scss +10 -0
- data/test/functions_test.rb +340 -0
- data/test/native_test.rb +213 -0
- data/test/output_style_test.rb +107 -0
- data/test/sass_2_scss_test.rb +14 -0
- data/test/test_helper.rb +45 -0
- 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
|
+
}
|