sassc 1.11.4 → 1.12.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 +5 -5
- data/.travis.yml +2 -2
- data/CODE_OF_CONDUCT.md +10 -0
- data/README.md +4 -1
- data/ext/libsass/.editorconfig +1 -1
- data/ext/libsass/.github/CONTRIBUTING.md +7 -7
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +31 -6
- data/ext/libsass/.gitignore +3 -0
- data/ext/libsass/.travis.yml +37 -18
- data/ext/libsass/GNUmakefile.am +23 -37
- data/ext/libsass/Makefile +10 -6
- data/ext/libsass/Makefile.conf +3 -0
- data/ext/libsass/Readme.md +68 -63
- data/ext/libsass/appveyor.yml +7 -3
- data/ext/libsass/configure.ac +10 -14
- data/ext/libsass/docs/api-context-internal.md +29 -21
- data/ext/libsass/docs/api-context.md +26 -6
- data/ext/libsass/docs/api-doc.md +49 -16
- data/ext/libsass/docs/api-function-example.md +1 -1
- data/ext/libsass/docs/api-function.md +31 -7
- data/ext/libsass/docs/api-importer.md +19 -19
- data/ext/libsass/docs/api-value.md +4 -2
- data/ext/libsass/docs/build-on-windows.md +4 -4
- data/ext/libsass/docs/build-with-mingw.md +3 -3
- data/ext/libsass/docs/build.md +9 -9
- data/ext/libsass/docs/custom-functions-internal.md +10 -8
- data/ext/libsass/docs/implementations.md +20 -8
- data/ext/libsass/docs/unicode.md +16 -10
- data/ext/libsass/include/sass/base.h +0 -3
- data/ext/libsass/include/sass/context.h +20 -2
- data/ext/libsass/include/sass/functions.h +31 -0
- data/ext/libsass/include/sass/values.h +3 -1
- data/ext/libsass/include/sass/version.h +1 -1
- data/ext/libsass/include/sass/version.h.in +1 -1
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/res/resource.rc +6 -6
- data/ext/libsass/script/ci-build-libsass +10 -5
- data/ext/libsass/script/ci-build-plugin +62 -0
- data/ext/libsass/script/ci-install-compiler +1 -1
- data/ext/libsass/script/ci-install-deps +4 -7
- data/ext/libsass/script/ci-report-coverage +13 -3
- data/ext/libsass/script/tap-driver +1 -1
- data/ext/libsass/script/tap-runner +1 -1
- data/ext/libsass/src/GNUmakefile.am +1 -1
- data/ext/libsass/src/ast.cpp +537 -762
- data/ext/libsass/src/ast.hpp +377 -419
- data/ext/libsass/src/ast_def_macros.hpp +26 -1
- data/ext/libsass/src/ast_fwd_decl.cpp +29 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +94 -21
- data/ext/libsass/src/b64/encode.h +3 -1
- data/ext/libsass/src/backtrace.cpp +46 -0
- data/ext/libsass/src/backtrace.hpp +7 -54
- data/ext/libsass/src/bind.cpp +72 -50
- data/ext/libsass/src/bind.hpp +0 -1
- data/ext/libsass/src/cencode.c +6 -0
- data/ext/libsass/src/check_nesting.cpp +157 -135
- data/ext/libsass/src/check_nesting.hpp +11 -10
- data/ext/libsass/src/color_maps.cpp +10 -6
- data/ext/libsass/src/color_maps.hpp +6 -8
- data/ext/libsass/src/constants.cpp +4 -3
- data/ext/libsass/src/constants.hpp +4 -3
- data/ext/libsass/src/context.cpp +110 -47
- data/ext/libsass/src/context.hpp +11 -1
- data/ext/libsass/src/cssize.cpp +105 -94
- data/ext/libsass/src/cssize.hpp +4 -5
- data/ext/libsass/src/debugger.hpp +247 -244
- data/ext/libsass/src/emitter.cpp +30 -6
- data/ext/libsass/src/emitter.hpp +7 -0
- data/ext/libsass/src/environment.cpp +67 -16
- data/ext/libsass/src/environment.hpp +28 -7
- data/ext/libsass/src/error_handling.cpp +92 -64
- data/ext/libsass/src/error_handling.hpp +64 -43
- data/ext/libsass/src/eval.cpp +494 -544
- data/ext/libsass/src/eval.hpp +17 -23
- data/ext/libsass/src/expand.cpp +182 -154
- data/ext/libsass/src/expand.hpp +4 -5
- data/ext/libsass/src/extend.cpp +299 -291
- data/ext/libsass/src/extend.hpp +46 -11
- data/ext/libsass/src/file.cpp +103 -36
- data/ext/libsass/src/file.hpp +21 -4
- data/ext/libsass/src/functions.cpp +561 -312
- data/ext/libsass/src/functions.hpp +8 -5
- data/ext/libsass/src/inspect.cpp +108 -53
- data/ext/libsass/src/inspect.hpp +5 -2
- data/ext/libsass/src/lexer.cpp +15 -7
- data/ext/libsass/src/lexer.hpp +13 -4
- data/ext/libsass/src/listize.cpp +3 -2
- data/ext/libsass/src/listize.hpp +0 -1
- data/ext/libsass/src/memory/SharedPtr.cpp +16 -18
- data/ext/libsass/src/memory/SharedPtr.hpp +47 -43
- data/ext/libsass/src/node.cpp +34 -38
- data/ext/libsass/src/node.hpp +6 -8
- data/ext/libsass/src/operation.hpp +2 -2
- data/ext/libsass/src/operators.cpp +240 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/output.cpp +22 -20
- data/ext/libsass/src/parser.cpp +719 -358
- data/ext/libsass/src/parser.hpp +57 -22
- data/ext/libsass/src/plugins.cpp +28 -10
- data/ext/libsass/src/position.cpp +21 -3
- data/ext/libsass/src/position.hpp +2 -1
- data/ext/libsass/src/prelexer.cpp +104 -19
- data/ext/libsass/src/prelexer.hpp +10 -3
- data/ext/libsass/src/remove_placeholders.cpp +9 -10
- data/ext/libsass/src/remove_placeholders.hpp +1 -5
- data/ext/libsass/src/sass.cpp +62 -4
- data/ext/libsass/src/sass.hpp +5 -2
- data/ext/libsass/src/sass_context.cpp +96 -58
- data/ext/libsass/src/sass_context.hpp +7 -5
- data/ext/libsass/src/sass_functions.cpp +63 -1
- data/ext/libsass/src/sass_functions.hpp +19 -1
- data/ext/libsass/src/sass_util.cpp +3 -3
- data/ext/libsass/src/sass_util.hpp +4 -4
- data/ext/libsass/src/sass_values.cpp +42 -39
- data/ext/libsass/src/sass_values.hpp +2 -1
- data/ext/libsass/src/source_map.cpp +16 -18
- data/ext/libsass/src/subset_map.cpp +6 -8
- data/ext/libsass/src/subset_map.hpp +6 -6
- data/ext/libsass/src/to_c.cpp +2 -2
- data/ext/libsass/src/to_value.cpp +8 -3
- data/ext/libsass/src/to_value.hpp +1 -0
- data/ext/libsass/src/units.cpp +349 -45
- data/ext/libsass/src/units.hpp +39 -22
- data/ext/libsass/src/utf8/checked.h +7 -0
- data/ext/libsass/src/utf8/unchecked.h +7 -0
- data/ext/libsass/src/utf8_string.cpp +1 -1
- data/ext/libsass/src/util.cpp +139 -45
- data/ext/libsass/src/util.hpp +4 -7
- data/ext/libsass/src/values.cpp +15 -23
- data/ext/libsass/win/libsass.sln +13 -2
- data/ext/libsass/win/libsass.sln.DotSettings +9 -0
- data/ext/libsass/win/libsass.targets +3 -0
- data/ext/libsass/win/libsass.vcxproj.filters +9 -0
- data/lib/sassc/version.rb +1 -1
- data/sassc.gemspec +1 -1
- data/test/native_test.rb +1 -1
- metadata +11 -4
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
#include <sstream>
|
|
6
6
|
#include <stdexcept>
|
|
7
7
|
#include "position.hpp"
|
|
8
|
+
#include "backtrace.hpp"
|
|
9
|
+
#include "ast_fwd_decl.hpp"
|
|
10
|
+
#include "sass/functions.h"
|
|
8
11
|
|
|
9
12
|
namespace Sass {
|
|
10
13
|
|
|
@@ -15,6 +18,7 @@ namespace Sass {
|
|
|
15
18
|
const std::string def_msg = "Invalid sass detected";
|
|
16
19
|
const std::string def_op_msg = "Undefined operation";
|
|
17
20
|
const std::string def_op_null_msg = "Invalid null operation";
|
|
21
|
+
const std::string def_nesting_limit = "Code too deeply neested";
|
|
18
22
|
|
|
19
23
|
class Base : public std::runtime_error {
|
|
20
24
|
protected:
|
|
@@ -22,9 +26,9 @@ namespace Sass {
|
|
|
22
26
|
std::string prefix;
|
|
23
27
|
public:
|
|
24
28
|
ParserState pstate;
|
|
25
|
-
|
|
29
|
+
Backtraces traces;
|
|
26
30
|
public:
|
|
27
|
-
Base(ParserState pstate, std::string msg
|
|
31
|
+
Base(ParserState pstate, std::string msg, Backtraces traces);
|
|
28
32
|
virtual const char* errtype() const { return prefix.c_str(); }
|
|
29
33
|
virtual const char* what() const throw() { return msg.c_str(); }
|
|
30
34
|
virtual ~Base() throw() {};
|
|
@@ -32,7 +36,7 @@ namespace Sass {
|
|
|
32
36
|
|
|
33
37
|
class InvalidSass : public Base {
|
|
34
38
|
public:
|
|
35
|
-
InvalidSass(ParserState pstate, std::string msg);
|
|
39
|
+
InvalidSass(ParserState pstate, Backtraces traces, std::string msg);
|
|
36
40
|
virtual ~InvalidSass() throw() {};
|
|
37
41
|
};
|
|
38
42
|
|
|
@@ -41,7 +45,7 @@ namespace Sass {
|
|
|
41
45
|
Selector_Ptr parent;
|
|
42
46
|
Selector_Ptr selector;
|
|
43
47
|
public:
|
|
44
|
-
InvalidParent(Selector_Ptr parent, Selector_Ptr selector);
|
|
48
|
+
InvalidParent(Selector_Ptr parent, Backtraces traces, Selector_Ptr selector);
|
|
45
49
|
virtual ~InvalidParent() throw() {};
|
|
46
50
|
};
|
|
47
51
|
|
|
@@ -51,7 +55,7 @@ namespace Sass {
|
|
|
51
55
|
std::string arg;
|
|
52
56
|
std::string fntype;
|
|
53
57
|
public:
|
|
54
|
-
MissingArgument(ParserState pstate, std::string fn, std::string arg, std::string fntype);
|
|
58
|
+
MissingArgument(ParserState pstate, Backtraces traces, std::string fn, std::string arg, std::string fntype);
|
|
55
59
|
virtual ~MissingArgument() throw() {};
|
|
56
60
|
};
|
|
57
61
|
|
|
@@ -62,38 +66,29 @@ namespace Sass {
|
|
|
62
66
|
std::string type;
|
|
63
67
|
const Value_Ptr value;
|
|
64
68
|
public:
|
|
65
|
-
InvalidArgumentType(ParserState pstate, std::string fn, std::string arg, std::string type, const Value_Ptr value = 0);
|
|
69
|
+
InvalidArgumentType(ParserState pstate, Backtraces traces, std::string fn, std::string arg, std::string type, const Value_Ptr value = 0);
|
|
66
70
|
virtual ~InvalidArgumentType() throw() {};
|
|
67
71
|
};
|
|
68
72
|
|
|
69
|
-
class
|
|
73
|
+
class InvalidVarKwdType : public Base {
|
|
74
|
+
protected:
|
|
75
|
+
std::string name;
|
|
76
|
+
const Argument_Ptr arg;
|
|
70
77
|
public:
|
|
71
|
-
|
|
72
|
-
virtual ~
|
|
78
|
+
InvalidVarKwdType(ParserState pstate, Backtraces traces, std::string name, const Argument_Ptr arg = 0);
|
|
79
|
+
virtual ~InvalidVarKwdType() throw() {};
|
|
73
80
|
};
|
|
74
81
|
|
|
75
|
-
|
|
76
|
-
class OperationError : public std::runtime_error {
|
|
77
|
-
protected:
|
|
78
|
-
std::string msg;
|
|
79
|
-
public:
|
|
80
|
-
OperationError(std::string msg = def_op_msg)
|
|
81
|
-
: std::runtime_error(msg), msg(msg)
|
|
82
|
-
{};
|
|
82
|
+
class InvalidSyntax : public Base {
|
|
83
83
|
public:
|
|
84
|
-
|
|
85
|
-
virtual
|
|
86
|
-
virtual ~OperationError() throw() {};
|
|
84
|
+
InvalidSyntax(ParserState pstate, Backtraces traces, std::string msg);
|
|
85
|
+
virtual ~InvalidSyntax() throw() {};
|
|
87
86
|
};
|
|
88
87
|
|
|
89
|
-
class
|
|
90
|
-
protected:
|
|
91
|
-
const Expression& lhs;
|
|
92
|
-
const Expression& rhs;
|
|
88
|
+
class NestingLimitError : public Base {
|
|
93
89
|
public:
|
|
94
|
-
|
|
95
|
-
virtual
|
|
96
|
-
virtual ~ZeroDivisionError() throw() {};
|
|
90
|
+
NestingLimitError(ParserState pstate, Backtraces traces, std::string msg = def_nesting_limit);
|
|
91
|
+
virtual ~NestingLimitError() throw() {};
|
|
97
92
|
};
|
|
98
93
|
|
|
99
94
|
class DuplicateKeyError : public Base {
|
|
@@ -101,7 +96,7 @@ namespace Sass {
|
|
|
101
96
|
const Map& dup;
|
|
102
97
|
const Expression& org;
|
|
103
98
|
public:
|
|
104
|
-
DuplicateKeyError(const Map& dup, const Expression& org);
|
|
99
|
+
DuplicateKeyError(Backtraces traces, const Map& dup, const Expression& org);
|
|
105
100
|
virtual const char* errtype() const { return "Error"; }
|
|
106
101
|
virtual ~DuplicateKeyError() throw() {};
|
|
107
102
|
};
|
|
@@ -111,7 +106,7 @@ namespace Sass {
|
|
|
111
106
|
const Expression& var;
|
|
112
107
|
const std::string type;
|
|
113
108
|
public:
|
|
114
|
-
TypeMismatch(const Expression& var, const std::string type);
|
|
109
|
+
TypeMismatch(Backtraces traces, const Expression& var, const std::string type);
|
|
115
110
|
virtual const char* errtype() const { return "Error"; }
|
|
116
111
|
virtual ~TypeMismatch() throw() {};
|
|
117
112
|
};
|
|
@@ -120,7 +115,7 @@ namespace Sass {
|
|
|
120
115
|
protected:
|
|
121
116
|
const Expression& val;
|
|
122
117
|
public:
|
|
123
|
-
InvalidValue(const Expression& val);
|
|
118
|
+
InvalidValue(Backtraces traces, const Expression& val);
|
|
124
119
|
virtual const char* errtype() const { return "Error"; }
|
|
125
120
|
virtual ~InvalidValue() throw() {};
|
|
126
121
|
};
|
|
@@ -129,17 +124,42 @@ namespace Sass {
|
|
|
129
124
|
protected:
|
|
130
125
|
const AST_Node& node;
|
|
131
126
|
public:
|
|
132
|
-
StackError(const AST_Node& node);
|
|
127
|
+
StackError(Backtraces traces, const AST_Node& node);
|
|
133
128
|
virtual const char* errtype() const { return "SystemStackError"; }
|
|
134
129
|
virtual ~StackError() throw() {};
|
|
135
130
|
};
|
|
136
131
|
|
|
132
|
+
/* common virtual base class (has no pstate or trace) */
|
|
133
|
+
class OperationError : public std::runtime_error {
|
|
134
|
+
protected:
|
|
135
|
+
std::string msg;
|
|
136
|
+
public:
|
|
137
|
+
OperationError(std::string msg = def_op_msg)
|
|
138
|
+
: std::runtime_error(msg), msg(msg)
|
|
139
|
+
{};
|
|
140
|
+
public:
|
|
141
|
+
virtual const char* errtype() const { return "Error"; }
|
|
142
|
+
virtual const char* what() const throw() { return msg.c_str(); }
|
|
143
|
+
virtual ~OperationError() throw() {};
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
class ZeroDivisionError : public OperationError {
|
|
147
|
+
protected:
|
|
148
|
+
const Expression& lhs;
|
|
149
|
+
const Expression& rhs;
|
|
150
|
+
public:
|
|
151
|
+
ZeroDivisionError(const Expression& lhs, const Expression& rhs);
|
|
152
|
+
virtual const char* errtype() const { return "ZeroDivisionError"; }
|
|
153
|
+
virtual ~ZeroDivisionError() throw() {};
|
|
154
|
+
};
|
|
155
|
+
|
|
137
156
|
class IncompatibleUnits : public OperationError {
|
|
138
157
|
protected:
|
|
139
|
-
const
|
|
140
|
-
const
|
|
158
|
+
// const Sass::UnitType lhs;
|
|
159
|
+
// const Sass::UnitType rhs;
|
|
141
160
|
public:
|
|
142
|
-
IncompatibleUnits(const
|
|
161
|
+
IncompatibleUnits(const Units& lhs, const Units& rhs);
|
|
162
|
+
IncompatibleUnits(const UnitType lhs, const UnitType rhs);
|
|
143
163
|
virtual ~IncompatibleUnits() throw() {};
|
|
144
164
|
};
|
|
145
165
|
|
|
@@ -147,16 +167,16 @@ namespace Sass {
|
|
|
147
167
|
protected:
|
|
148
168
|
Expression_Ptr_Const lhs;
|
|
149
169
|
Expression_Ptr_Const rhs;
|
|
150
|
-
const
|
|
170
|
+
const Sass_OP op;
|
|
151
171
|
public:
|
|
152
|
-
UndefinedOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs,
|
|
172
|
+
UndefinedOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, enum Sass_OP op);
|
|
153
173
|
// virtual const char* errtype() const { return "Error"; }
|
|
154
174
|
virtual ~UndefinedOperation() throw() {};
|
|
155
175
|
};
|
|
156
176
|
|
|
157
177
|
class InvalidNullOperation : public UndefinedOperation {
|
|
158
178
|
public:
|
|
159
|
-
InvalidNullOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs,
|
|
179
|
+
InvalidNullOperation(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, enum Sass_OP op);
|
|
160
180
|
virtual ~InvalidNullOperation() throw() {};
|
|
161
181
|
};
|
|
162
182
|
|
|
@@ -164,16 +184,16 @@ namespace Sass {
|
|
|
164
184
|
protected:
|
|
165
185
|
Expression_Ptr_Const lhs;
|
|
166
186
|
Expression_Ptr_Const rhs;
|
|
167
|
-
const
|
|
187
|
+
const Sass_OP op;
|
|
168
188
|
public:
|
|
169
|
-
AlphaChannelsNotEqual(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs,
|
|
189
|
+
AlphaChannelsNotEqual(Expression_Ptr_Const lhs, Expression_Ptr_Const rhs, enum Sass_OP op);
|
|
170
190
|
// virtual const char* errtype() const { return "Error"; }
|
|
171
191
|
virtual ~AlphaChannelsNotEqual() throw() {};
|
|
172
192
|
};
|
|
173
193
|
|
|
174
194
|
class SassValueError : public Base {
|
|
175
195
|
public:
|
|
176
|
-
SassValueError(ParserState pstate, OperationError& err);
|
|
196
|
+
SassValueError(Backtraces traces, ParserState pstate, OperationError& err);
|
|
177
197
|
virtual ~SassValueError() throw() {};
|
|
178
198
|
};
|
|
179
199
|
|
|
@@ -181,14 +201,15 @@ namespace Sass {
|
|
|
181
201
|
|
|
182
202
|
void warn(std::string msg, ParserState pstate);
|
|
183
203
|
void warn(std::string msg, ParserState pstate, Backtrace* bt);
|
|
204
|
+
void warning(std::string msg, ParserState pstate);
|
|
184
205
|
|
|
185
206
|
void deprecated_function(std::string msg, ParserState pstate);
|
|
186
|
-
void deprecated(std::string msg, std::string msg2, ParserState pstate);
|
|
207
|
+
void deprecated(std::string msg, std::string msg2, bool with_column, ParserState pstate);
|
|
187
208
|
void deprecated_bind(std::string msg, ParserState pstate);
|
|
188
209
|
// void deprecated(std::string msg, ParserState pstate, Backtrace* bt);
|
|
189
210
|
|
|
190
|
-
void
|
|
191
|
-
void error(std::string msg, ParserState pstate,
|
|
211
|
+
void coreError(std::string msg, ParserState pstate);
|
|
212
|
+
void error(std::string msg, ParserState pstate, Backtraces& traces);
|
|
192
213
|
|
|
193
214
|
}
|
|
194
215
|
|
data/ext/libsass/src/eval.cpp
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
#include "bind.hpp"
|
|
13
13
|
#include "util.hpp"
|
|
14
14
|
#include "inspect.hpp"
|
|
15
|
+
#include "operators.hpp"
|
|
15
16
|
#include "environment.hpp"
|
|
16
17
|
#include "position.hpp"
|
|
17
18
|
#include "sass/values.h"
|
|
@@ -24,34 +25,21 @@
|
|
|
24
25
|
#include "parser.hpp"
|
|
25
26
|
#include "expand.hpp"
|
|
26
27
|
#include "color_maps.hpp"
|
|
28
|
+
#include "sass_functions.hpp"
|
|
27
29
|
|
|
28
30
|
namespace Sass {
|
|
29
31
|
|
|
30
|
-
inline double add(double x, double y) { return x + y; }
|
|
31
|
-
inline double sub(double x, double y) { return x - y; }
|
|
32
|
-
inline double mul(double x, double y) { return x * y; }
|
|
33
|
-
inline double div(double x, double y) { return x / y; } // x/0 checked by caller
|
|
34
|
-
inline double mod(double x, double y) { // x/0 checked by caller
|
|
35
|
-
if ((x > 0 && y < 0) || (x < 0 && y > 0)) {
|
|
36
|
-
double ret = std::fmod(x, y);
|
|
37
|
-
return ret ? ret + y : ret;
|
|
38
|
-
} else {
|
|
39
|
-
return std::fmod(x, y);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
typedef double (*bop)(double, double);
|
|
43
|
-
bop ops[Sass_OP::NUM_OPS] = {
|
|
44
|
-
0, 0, // and, or
|
|
45
|
-
0, 0, 0, 0, 0, 0, // eq, neq, gt, gte, lt, lte
|
|
46
|
-
add, sub, mul, div, mod
|
|
47
|
-
};
|
|
48
|
-
|
|
49
32
|
Eval::Eval(Expand& exp)
|
|
50
33
|
: exp(exp),
|
|
51
34
|
ctx(exp.ctx),
|
|
35
|
+
traces(exp.traces),
|
|
52
36
|
force(false),
|
|
53
|
-
is_in_comment(false)
|
|
54
|
-
|
|
37
|
+
is_in_comment(false),
|
|
38
|
+
is_in_selector_schema(false)
|
|
39
|
+
{
|
|
40
|
+
bool_true = SASS_MEMORY_NEW(Boolean, "[NA]", true);
|
|
41
|
+
bool_false = SASS_MEMORY_NEW(Boolean, "[NA]", false);
|
|
42
|
+
}
|
|
55
43
|
Eval::~Eval() { }
|
|
56
44
|
|
|
57
45
|
Env* Eval::environment()
|
|
@@ -64,11 +52,6 @@ namespace Sass {
|
|
|
64
52
|
return exp.selector();
|
|
65
53
|
}
|
|
66
54
|
|
|
67
|
-
Backtrace* Eval::backtrace()
|
|
68
|
-
{
|
|
69
|
-
return exp.backtrace();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
55
|
Expression_Ptr Eval::operator()(Block_Ptr b)
|
|
73
56
|
{
|
|
74
57
|
Expression_Ptr val = 0;
|
|
@@ -86,7 +69,7 @@ namespace Sass {
|
|
|
86
69
|
if (a->is_global()) {
|
|
87
70
|
if (a->is_default()) {
|
|
88
71
|
if (env->has_global(var)) {
|
|
89
|
-
Expression_Ptr e =
|
|
72
|
+
Expression_Ptr e = Cast<Expression>(env->get_global(var));
|
|
90
73
|
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
|
91
74
|
env->set_global(var, a->value()->perform(this));
|
|
92
75
|
}
|
|
@@ -105,7 +88,7 @@ namespace Sass {
|
|
|
105
88
|
while (cur && cur->is_lexical()) {
|
|
106
89
|
if (cur->has_local(var)) {
|
|
107
90
|
if (AST_Node_Obj node = cur->get_local(var)) {
|
|
108
|
-
Expression_Ptr e =
|
|
91
|
+
Expression_Ptr e = Cast<Expression>(node);
|
|
109
92
|
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
|
110
93
|
cur->set_local(var, a->value()->perform(this));
|
|
111
94
|
}
|
|
@@ -121,7 +104,7 @@ namespace Sass {
|
|
|
121
104
|
}
|
|
122
105
|
else if (env->has_global(var)) {
|
|
123
106
|
if (AST_Node_Obj node = env->get_global(var)) {
|
|
124
|
-
Expression_Ptr e =
|
|
107
|
+
Expression_Ptr e = Cast<Expression>(node);
|
|
125
108
|
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
|
126
109
|
env->set_global(var, a->value()->perform(this));
|
|
127
110
|
}
|
|
@@ -164,28 +147,28 @@ namespace Sass {
|
|
|
164
147
|
std::string variable(f->variable());
|
|
165
148
|
Expression_Obj low = f->lower_bound()->perform(this);
|
|
166
149
|
if (low->concrete_type() != Expression::NUMBER) {
|
|
167
|
-
|
|
150
|
+
traces.push_back(Backtrace(low->pstate()));
|
|
151
|
+
throw Exception::TypeMismatch(traces, *low, "integer");
|
|
168
152
|
}
|
|
169
153
|
Expression_Obj high = f->upper_bound()->perform(this);
|
|
170
154
|
if (high->concrete_type() != Expression::NUMBER) {
|
|
171
|
-
|
|
155
|
+
traces.push_back(Backtrace(high->pstate()));
|
|
156
|
+
throw Exception::TypeMismatch(traces, *high, "integer");
|
|
172
157
|
}
|
|
173
|
-
Number_Obj sass_start =
|
|
174
|
-
Number_Obj sass_end =
|
|
158
|
+
Number_Obj sass_start = Cast<Number>(low);
|
|
159
|
+
Number_Obj sass_end = Cast<Number>(high);
|
|
175
160
|
// check if units are valid for sequence
|
|
176
161
|
if (sass_start->unit() != sass_end->unit()) {
|
|
177
162
|
std::stringstream msg; msg << "Incompatible units: '"
|
|
178
163
|
<< sass_end->unit() << "' and '"
|
|
179
164
|
<< sass_start->unit() << "'.";
|
|
180
|
-
error(msg.str(), low->pstate(),
|
|
165
|
+
error(msg.str(), low->pstate(), traces);
|
|
181
166
|
}
|
|
182
167
|
double start = sass_start->value();
|
|
183
168
|
double end = sass_end->value();
|
|
184
169
|
// only create iterator once in this environment
|
|
185
170
|
Env env(environment(), true);
|
|
186
171
|
exp.env_stack.push_back(&env);
|
|
187
|
-
Number_Ptr it = SASS_MEMORY_NEW(Number, low->pstate(), start, sass_end->unit());
|
|
188
|
-
env.set_local(variable, it);
|
|
189
172
|
Block_Obj body = f->block();
|
|
190
173
|
Expression_Ptr val = 0;
|
|
191
174
|
if (start < end) {
|
|
@@ -193,7 +176,7 @@ namespace Sass {
|
|
|
193
176
|
for (double i = start;
|
|
194
177
|
i < end;
|
|
195
178
|
++i) {
|
|
196
|
-
it->
|
|
179
|
+
Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
|
|
197
180
|
env.set_local(variable, it);
|
|
198
181
|
val = body->perform(this);
|
|
199
182
|
if (val) break;
|
|
@@ -203,7 +186,7 @@ namespace Sass {
|
|
|
203
186
|
for (double i = start;
|
|
204
187
|
i > end;
|
|
205
188
|
--i) {
|
|
206
|
-
it->
|
|
189
|
+
Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
|
|
207
190
|
env.set_local(variable, it);
|
|
208
191
|
val = body->perform(this);
|
|
209
192
|
if (val) break;
|
|
@@ -224,19 +207,19 @@ namespace Sass {
|
|
|
224
207
|
List_Obj list = 0;
|
|
225
208
|
Map_Ptr map = 0;
|
|
226
209
|
if (expr->concrete_type() == Expression::MAP) {
|
|
227
|
-
map =
|
|
210
|
+
map = Cast<Map>(expr);
|
|
228
211
|
}
|
|
229
|
-
else if (Selector_List_Ptr ls =
|
|
212
|
+
else if (Selector_List_Ptr ls = Cast<Selector_List>(expr)) {
|
|
230
213
|
Listize listize;
|
|
231
214
|
Expression_Obj rv = ls->perform(&listize);
|
|
232
|
-
list =
|
|
215
|
+
list = Cast<List>(rv);
|
|
233
216
|
}
|
|
234
217
|
else if (expr->concrete_type() != Expression::LIST) {
|
|
235
218
|
list = SASS_MEMORY_NEW(List, expr->pstate(), 1, SASS_COMMA);
|
|
236
219
|
list->append(expr);
|
|
237
220
|
}
|
|
238
221
|
else {
|
|
239
|
-
list =
|
|
222
|
+
list = Cast<List>(expr);
|
|
240
223
|
}
|
|
241
224
|
|
|
242
225
|
Block_Obj body = e->block();
|
|
@@ -252,8 +235,8 @@ namespace Sass {
|
|
|
252
235
|
variable->append(value);
|
|
253
236
|
env.set_local(variables[0], variable);
|
|
254
237
|
} else {
|
|
255
|
-
env.set_local(variables[0],
|
|
256
|
-
env.set_local(variables[1],
|
|
238
|
+
env.set_local(variables[0], key);
|
|
239
|
+
env.set_local(variables[1], value);
|
|
257
240
|
}
|
|
258
241
|
|
|
259
242
|
val = body->perform(this);
|
|
@@ -261,15 +244,15 @@ namespace Sass {
|
|
|
261
244
|
}
|
|
262
245
|
}
|
|
263
246
|
else {
|
|
264
|
-
if (list->length() == 1 &&
|
|
265
|
-
list =
|
|
247
|
+
if (list->length() == 1 && Cast<Selector_List>(list)) {
|
|
248
|
+
list = Cast<List>(list);
|
|
266
249
|
}
|
|
267
250
|
for (size_t i = 0, L = list->length(); i < L; ++i) {
|
|
268
|
-
Expression_Ptr
|
|
251
|
+
Expression_Ptr item = list->at(i);
|
|
269
252
|
// unwrap value if the expression is an argument
|
|
270
|
-
if (Argument_Ptr arg =
|
|
253
|
+
if (Argument_Ptr arg = Cast<Argument>(item)) item = arg->value();
|
|
271
254
|
// check if we got passed a list of args (investigate)
|
|
272
|
-
if (List_Ptr scalars =
|
|
255
|
+
if (List_Ptr scalars = Cast<List>(item)) {
|
|
273
256
|
if (variables.size() == 1) {
|
|
274
257
|
Expression_Ptr var = scalars;
|
|
275
258
|
env.set_local(variables[0], var);
|
|
@@ -278,13 +261,13 @@ namespace Sass {
|
|
|
278
261
|
for (size_t j = 0, K = variables.size(); j < K; ++j) {
|
|
279
262
|
Expression_Ptr res = j >= scalars->length()
|
|
280
263
|
? SASS_MEMORY_NEW(Null, expr->pstate())
|
|
281
|
-
:
|
|
264
|
+
: scalars->at(j);
|
|
282
265
|
env.set_local(variables[j], res);
|
|
283
266
|
}
|
|
284
267
|
}
|
|
285
268
|
} else {
|
|
286
269
|
if (variables.size() > 0) {
|
|
287
|
-
env.set_local(variables.at(0),
|
|
270
|
+
env.set_local(variables.at(0), item);
|
|
288
271
|
for (size_t j = 1, K = variables.size(); j < K; ++j) {
|
|
289
272
|
// XXX: this is never hit via spec tests
|
|
290
273
|
Expression_Ptr res = SASS_MEMORY_NEW(Null, expr->pstate());
|
|
@@ -334,17 +317,28 @@ namespace Sass {
|
|
|
334
317
|
// try to use generic function
|
|
335
318
|
if (env->has("@warn[f]")) {
|
|
336
319
|
|
|
337
|
-
|
|
320
|
+
// add call stack entry
|
|
321
|
+
ctx.callee_stack.push_back({
|
|
322
|
+
"@warn",
|
|
323
|
+
w->pstate().path,
|
|
324
|
+
w->pstate().line + 1,
|
|
325
|
+
w->pstate().column + 1,
|
|
326
|
+
SASS_CALLEE_FUNCTION,
|
|
327
|
+
{ env }
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
Definition_Ptr def = Cast<Definition>((*env)["@warn[f]"]);
|
|
338
331
|
// Block_Obj body = def->block();
|
|
339
332
|
// Native_Function func = def->native_function();
|
|
340
333
|
Sass_Function_Entry c_function = def->c_function();
|
|
341
334
|
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
|
342
335
|
|
|
343
336
|
To_C to_c;
|
|
344
|
-
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
|
|
337
|
+
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
|
|
345
338
|
sass_list_set_value(c_args, 0, message->perform(&to_c));
|
|
346
339
|
union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
|
|
347
340
|
ctx.c_options.output_style = outstyle;
|
|
341
|
+
ctx.callee_stack.pop_back();
|
|
348
342
|
sass_delete_value(c_args);
|
|
349
343
|
sass_delete_value(c_val);
|
|
350
344
|
return 0;
|
|
@@ -352,11 +346,12 @@ namespace Sass {
|
|
|
352
346
|
}
|
|
353
347
|
|
|
354
348
|
std::string result(unquote(message->to_sass()));
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
std::cerr <<
|
|
358
|
-
std::cerr << std::endl
|
|
349
|
+
std::cerr << "WARNING: " << result << std::endl;
|
|
350
|
+
traces.push_back(Backtrace(w->pstate()));
|
|
351
|
+
std::cerr << traces_to_string(traces, " ");
|
|
352
|
+
std::cerr << std::endl;
|
|
359
353
|
ctx.c_options.output_style = outstyle;
|
|
354
|
+
traces.pop_back();
|
|
360
355
|
return 0;
|
|
361
356
|
}
|
|
362
357
|
|
|
@@ -370,17 +365,28 @@ namespace Sass {
|
|
|
370
365
|
// try to use generic function
|
|
371
366
|
if (env->has("@error[f]")) {
|
|
372
367
|
|
|
373
|
-
|
|
368
|
+
// add call stack entry
|
|
369
|
+
ctx.callee_stack.push_back({
|
|
370
|
+
"@error",
|
|
371
|
+
e->pstate().path,
|
|
372
|
+
e->pstate().line + 1,
|
|
373
|
+
e->pstate().column + 1,
|
|
374
|
+
SASS_CALLEE_FUNCTION,
|
|
375
|
+
{ env }
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
Definition_Ptr def = Cast<Definition>((*env)["@error[f]"]);
|
|
374
379
|
// Block_Obj body = def->block();
|
|
375
380
|
// Native_Function func = def->native_function();
|
|
376
381
|
Sass_Function_Entry c_function = def->c_function();
|
|
377
382
|
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
|
378
383
|
|
|
379
384
|
To_C to_c;
|
|
380
|
-
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
|
|
385
|
+
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
|
|
381
386
|
sass_list_set_value(c_args, 0, message->perform(&to_c));
|
|
382
387
|
union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
|
|
383
388
|
ctx.c_options.output_style = outstyle;
|
|
389
|
+
ctx.callee_stack.pop_back();
|
|
384
390
|
sass_delete_value(c_args);
|
|
385
391
|
sass_delete_value(c_val);
|
|
386
392
|
return 0;
|
|
@@ -389,7 +395,7 @@ namespace Sass {
|
|
|
389
395
|
|
|
390
396
|
std::string result(unquote(message->to_sass()));
|
|
391
397
|
ctx.c_options.output_style = outstyle;
|
|
392
|
-
error(result, e->pstate());
|
|
398
|
+
error(result, e->pstate(), traces);
|
|
393
399
|
return 0;
|
|
394
400
|
}
|
|
395
401
|
|
|
@@ -403,17 +409,28 @@ namespace Sass {
|
|
|
403
409
|
// try to use generic function
|
|
404
410
|
if (env->has("@debug[f]")) {
|
|
405
411
|
|
|
406
|
-
|
|
412
|
+
// add call stack entry
|
|
413
|
+
ctx.callee_stack.push_back({
|
|
414
|
+
"@debug",
|
|
415
|
+
d->pstate().path,
|
|
416
|
+
d->pstate().line + 1,
|
|
417
|
+
d->pstate().column + 1,
|
|
418
|
+
SASS_CALLEE_FUNCTION,
|
|
419
|
+
{ env }
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
Definition_Ptr def = Cast<Definition>((*env)["@debug[f]"]);
|
|
407
423
|
// Block_Obj body = def->block();
|
|
408
424
|
// Native_Function func = def->native_function();
|
|
409
425
|
Sass_Function_Entry c_function = def->c_function();
|
|
410
426
|
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
|
411
427
|
|
|
412
428
|
To_C to_c;
|
|
413
|
-
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
|
|
429
|
+
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
|
|
414
430
|
sass_list_set_value(c_args, 0, message->perform(&to_c));
|
|
415
431
|
union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
|
|
416
432
|
ctx.c_options.output_style = outstyle;
|
|
433
|
+
ctx.callee_stack.pop_back();
|
|
417
434
|
sass_delete_value(c_args);
|
|
418
435
|
sass_delete_value(c_val);
|
|
419
436
|
return 0;
|
|
@@ -441,14 +458,15 @@ namespace Sass {
|
|
|
441
458
|
l->length() / 2);
|
|
442
459
|
for (size_t i = 0, L = l->length(); i < L; i += 2)
|
|
443
460
|
{
|
|
444
|
-
|
|
445
|
-
|
|
461
|
+
Expression_Obj key = (*l)[i+0]->perform(this);
|
|
462
|
+
Expression_Obj val = (*l)[i+1]->perform(this);
|
|
446
463
|
// make sure the color key never displays its real name
|
|
447
464
|
key->is_delayed(true); // verified
|
|
448
465
|
*lm << std::make_pair(key, val);
|
|
449
466
|
}
|
|
450
467
|
if (lm->has_duplicate_key()) {
|
|
451
|
-
|
|
468
|
+
traces.push_back(Backtrace(l->pstate()));
|
|
469
|
+
throw Exception::DuplicateKeyError(traces, *lm, *l);
|
|
452
470
|
}
|
|
453
471
|
|
|
454
472
|
lm->is_interpolant(l->is_interpolant());
|
|
@@ -461,7 +479,8 @@ namespace Sass {
|
|
|
461
479
|
l->pstate(),
|
|
462
480
|
l->length(),
|
|
463
481
|
l->separator(),
|
|
464
|
-
l->is_arglist()
|
|
482
|
+
l->is_arglist(),
|
|
483
|
+
l->is_bracketed());
|
|
465
484
|
for (size_t i = 0, L = l->length(); i < L; ++i) {
|
|
466
485
|
ll->append((*l)[i]->perform(this));
|
|
467
486
|
}
|
|
@@ -478,7 +497,8 @@ namespace Sass {
|
|
|
478
497
|
// make sure we're not starting with duplicate keys.
|
|
479
498
|
// the duplicate key state will have been set in the parser phase.
|
|
480
499
|
if (m->has_duplicate_key()) {
|
|
481
|
-
|
|
500
|
+
traces.push_back(Backtrace(m->pstate()));
|
|
501
|
+
throw Exception::DuplicateKeyError(traces, *m, *m);
|
|
482
502
|
}
|
|
483
503
|
|
|
484
504
|
Map_Obj mm = SASS_MEMORY_NEW(Map,
|
|
@@ -486,13 +506,16 @@ namespace Sass {
|
|
|
486
506
|
m->length());
|
|
487
507
|
for (auto key : m->keys()) {
|
|
488
508
|
Expression_Ptr ex_key = key->perform(this);
|
|
489
|
-
Expression_Ptr ex_val = m->at(key)
|
|
509
|
+
Expression_Ptr ex_val = m->at(key);
|
|
510
|
+
if (ex_val == NULL) continue;
|
|
511
|
+
ex_val = ex_val->perform(this);
|
|
490
512
|
*mm << std::make_pair(ex_key, ex_val);
|
|
491
513
|
}
|
|
492
514
|
|
|
493
515
|
// check the evaluated keys aren't duplicates.
|
|
494
516
|
if (mm->has_duplicate_key()) {
|
|
495
|
-
|
|
517
|
+
traces.push_back(Backtrace(m->pstate()));
|
|
518
|
+
throw Exception::DuplicateKeyError(traces, *mm, *m);
|
|
496
519
|
}
|
|
497
520
|
|
|
498
521
|
mm->is_expanded(true);
|
|
@@ -502,16 +525,141 @@ namespace Sass {
|
|
|
502
525
|
Expression_Ptr Eval::operator()(Binary_Expression_Ptr b_in)
|
|
503
526
|
{
|
|
504
527
|
|
|
505
|
-
|
|
528
|
+
Expression_Obj lhs = b_in->left();
|
|
529
|
+
Expression_Obj rhs = b_in->right();
|
|
530
|
+
enum Sass_OP op_type = b_in->optype();
|
|
531
|
+
|
|
532
|
+
if (op_type == Sass_OP::AND) {
|
|
533
|
+
// LOCAL_FLAG(force, true);
|
|
534
|
+
lhs = lhs->perform(this);
|
|
535
|
+
if (!*lhs) return lhs.detach();
|
|
536
|
+
return rhs->perform(this);
|
|
537
|
+
}
|
|
538
|
+
else if (op_type == Sass_OP::OR) {
|
|
539
|
+
// LOCAL_FLAG(force, true);
|
|
540
|
+
lhs = lhs->perform(this);
|
|
541
|
+
if (*lhs) return lhs.detach();
|
|
542
|
+
return rhs->perform(this);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Evaluate variables as early o
|
|
546
|
+
while (Variable_Ptr l_v = Cast<Variable>(lhs)) {
|
|
547
|
+
lhs = operator()(l_v);
|
|
548
|
+
}
|
|
549
|
+
while (Variable_Ptr r_v = Cast<Variable>(rhs)) {
|
|
550
|
+
rhs = operator()(r_v);
|
|
551
|
+
}
|
|
552
|
+
|
|
506
553
|
Binary_Expression_Obj b = b_in;
|
|
507
|
-
|
|
554
|
+
|
|
555
|
+
// Evaluate sub-expressions early on
|
|
556
|
+
while (Binary_Expression_Ptr l_b = Cast<Binary_Expression>(lhs)) {
|
|
557
|
+
if (!force && l_b->is_delayed()) break;
|
|
558
|
+
lhs = operator()(l_b);
|
|
559
|
+
}
|
|
560
|
+
while (Binary_Expression_Ptr r_b = Cast<Binary_Expression>(rhs)) {
|
|
561
|
+
if (!force && r_b->is_delayed()) break;
|
|
562
|
+
rhs = operator()(r_b);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// don't eval delayed expressions (the '/' when used as a separator)
|
|
566
|
+
if (!force && op_type == Sass_OP::DIV && b->is_delayed()) {
|
|
567
|
+
b->right(b->right()->perform(this));
|
|
568
|
+
b->left(b->left()->perform(this));
|
|
569
|
+
return b.detach();
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// specific types we know are final
|
|
573
|
+
// handle them early to avoid overhead
|
|
574
|
+
if (Number_Ptr l_n = Cast<Number>(lhs)) {
|
|
575
|
+
// lhs is number and rhs is number
|
|
576
|
+
if (Number_Ptr r_n = Cast<Number>(rhs)) {
|
|
577
|
+
try {
|
|
578
|
+
switch (op_type) {
|
|
579
|
+
case Sass_OP::EQ: return *l_n == *r_n ? bool_true : bool_false;
|
|
580
|
+
case Sass_OP::NEQ: return *l_n == *r_n ? bool_false : bool_true;
|
|
581
|
+
case Sass_OP::LT: return *l_n < *r_n ? bool_true : bool_false;
|
|
582
|
+
case Sass_OP::GTE: return *l_n < *r_n ? bool_false : bool_true;
|
|
583
|
+
case Sass_OP::LTE: return *l_n < *r_n || *l_n == *r_n ? bool_true : bool_false;
|
|
584
|
+
case Sass_OP::GT: return *l_n < *r_n || *l_n == *r_n ? bool_false : bool_true;
|
|
585
|
+
case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
|
|
586
|
+
return Operators::op_numbers(op_type, *l_n, *r_n, ctx.c_options, b_in->pstate());
|
|
587
|
+
default: break;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
catch (Exception::OperationError& err)
|
|
591
|
+
{
|
|
592
|
+
traces.push_back(Backtrace(b_in->pstate()));
|
|
593
|
+
throw Exception::SassValueError(traces, b_in->pstate(), err);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
// lhs is number and rhs is color
|
|
597
|
+
else if (Color_Ptr r_c = Cast<Color>(rhs)) {
|
|
598
|
+
try {
|
|
599
|
+
switch (op_type) {
|
|
600
|
+
case Sass_OP::EQ: return *l_n == *r_c ? bool_true : bool_false;
|
|
601
|
+
case Sass_OP::NEQ: return *l_n == *r_c ? bool_false : bool_true;
|
|
602
|
+
case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
|
|
603
|
+
return Operators::op_number_color(op_type, *l_n, *r_c, ctx.c_options, b_in->pstate());
|
|
604
|
+
default: break;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
catch (Exception::OperationError& err)
|
|
608
|
+
{
|
|
609
|
+
traces.push_back(Backtrace(b_in->pstate()));
|
|
610
|
+
throw Exception::SassValueError(traces, b_in->pstate(), err);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
else if (Color_Ptr l_c = Cast<Color>(lhs)) {
|
|
615
|
+
// lhs is color and rhs is color
|
|
616
|
+
if (Color_Ptr r_c = Cast<Color>(rhs)) {
|
|
617
|
+
try {
|
|
618
|
+
switch (op_type) {
|
|
619
|
+
case Sass_OP::EQ: return *l_c == *r_c ? bool_true : bool_false;
|
|
620
|
+
case Sass_OP::NEQ: return *l_c == *r_c ? bool_false : bool_true;
|
|
621
|
+
case Sass_OP::LT: return *l_c < *r_c ? bool_true : bool_false;
|
|
622
|
+
case Sass_OP::GTE: return *l_c < *r_c ? bool_false : bool_true;
|
|
623
|
+
case Sass_OP::LTE: return *l_c < *r_c || *l_c == *r_c ? bool_true : bool_false;
|
|
624
|
+
case Sass_OP::GT: return *l_c < *r_c || *l_c == *r_c ? bool_false : bool_true;
|
|
625
|
+
case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
|
|
626
|
+
return Operators::op_colors(op_type, *l_c, *r_c, ctx.c_options, b_in->pstate());
|
|
627
|
+
default: break;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
catch (Exception::OperationError& err)
|
|
631
|
+
{
|
|
632
|
+
traces.push_back(Backtrace(b_in->pstate()));
|
|
633
|
+
throw Exception::SassValueError(traces, b_in->pstate(), err);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
// lhs is color and rhs is number
|
|
637
|
+
else if (Number_Ptr r_n = Cast<Number>(rhs)) {
|
|
638
|
+
try {
|
|
639
|
+
switch (op_type) {
|
|
640
|
+
case Sass_OP::EQ: return *l_c == *r_n ? bool_true : bool_false;
|
|
641
|
+
case Sass_OP::NEQ: return *l_c == *r_n ? bool_false : bool_true;
|
|
642
|
+
case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
|
|
643
|
+
return Operators::op_color_number(op_type, *l_c, *r_n, ctx.c_options, b_in->pstate());
|
|
644
|
+
default: break;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
catch (Exception::OperationError& err)
|
|
648
|
+
{
|
|
649
|
+
traces.push_back(Backtrace(b_in->pstate()));
|
|
650
|
+
throw Exception::SassValueError(traces, b_in->pstate(), err);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
String_Schema_Obj ret_schema;
|
|
508
656
|
|
|
509
657
|
// only the last item will be used to eval the binary expression
|
|
510
|
-
if (String_Schema_Ptr s_l =
|
|
658
|
+
if (String_Schema_Ptr s_l = Cast<String_Schema>(b->left())) {
|
|
511
659
|
if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) {
|
|
512
660
|
ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
|
|
513
661
|
Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
|
|
514
|
-
b->op(),
|
|
662
|
+
b->op(), s_l->last(), b->right());
|
|
515
663
|
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // unverified
|
|
516
664
|
for (size_t i = 0; i < s_l->length() - 1; ++i) {
|
|
517
665
|
ret_schema->append(s_l->at(i)->perform(this));
|
|
@@ -520,12 +668,12 @@ namespace Sass {
|
|
|
520
668
|
return ret_schema->perform(this);
|
|
521
669
|
}
|
|
522
670
|
}
|
|
523
|
-
if (String_Schema_Ptr s_r =
|
|
671
|
+
if (String_Schema_Ptr s_r = Cast<String_Schema>(b->right())) {
|
|
524
672
|
|
|
525
673
|
if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) {
|
|
526
674
|
ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
|
|
527
675
|
Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
|
|
528
|
-
b->op(), b->left(),
|
|
676
|
+
b->op(), b->left(), s_r->first());
|
|
529
677
|
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // verified
|
|
530
678
|
ret_schema->append(bin_ex->perform(this));
|
|
531
679
|
for (size_t i = 1; i < s_r->length(); ++i) {
|
|
@@ -535,16 +683,6 @@ namespace Sass {
|
|
|
535
683
|
}
|
|
536
684
|
}
|
|
537
685
|
|
|
538
|
-
// don't eval delayed expressions (the '/' when used as a separator)
|
|
539
|
-
if (!force && op_type == Sass_OP::DIV && b->is_delayed()) {
|
|
540
|
-
b->right(b->right()->perform(this));
|
|
541
|
-
b->left(b->left()->perform(this));
|
|
542
|
-
return b.detach();
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
Expression_Obj lhs = b->left();
|
|
546
|
-
Expression_Obj rhs = b->right();
|
|
547
|
-
|
|
548
686
|
// fully evaluate their values
|
|
549
687
|
if (op_type == Sass_OP::EQ ||
|
|
550
688
|
op_type == Sass_OP::NEQ ||
|
|
@@ -565,32 +703,19 @@ namespace Sass {
|
|
|
565
703
|
lhs = lhs->perform(this);
|
|
566
704
|
}
|
|
567
705
|
|
|
568
|
-
Binary_Expression_Obj u3 = b;
|
|
569
|
-
switch (op_type) {
|
|
570
|
-
case Sass_OP::AND: {
|
|
571
|
-
return *lhs ? b->right()->perform(this) : lhs.detach();
|
|
572
|
-
} break;
|
|
573
|
-
|
|
574
|
-
case Sass_OP::OR: {
|
|
575
|
-
return *lhs ? lhs.detach() : b->right()->perform(this);
|
|
576
|
-
} break;
|
|
577
|
-
|
|
578
|
-
default:
|
|
579
|
-
break;
|
|
580
|
-
}
|
|
581
706
|
// not a logical connective, so go ahead and eval the rhs
|
|
582
707
|
rhs = rhs->perform(this);
|
|
583
|
-
AST_Node_Obj lu =
|
|
584
|
-
AST_Node_Obj ru =
|
|
708
|
+
AST_Node_Obj lu = lhs;
|
|
709
|
+
AST_Node_Obj ru = rhs;
|
|
585
710
|
|
|
586
|
-
Expression::Concrete_Type l_type
|
|
587
|
-
Expression::Concrete_Type r_type
|
|
711
|
+
Expression::Concrete_Type l_type;
|
|
712
|
+
Expression::Concrete_Type r_type;
|
|
588
713
|
|
|
589
714
|
// Is one of the operands an interpolant?
|
|
590
|
-
String_Schema_Obj s1 =
|
|
591
|
-
String_Schema_Obj s2 =
|
|
592
|
-
Binary_Expression_Obj b1 =
|
|
593
|
-
Binary_Expression_Obj b2 =
|
|
715
|
+
String_Schema_Obj s1 = Cast<String_Schema>(b->left());
|
|
716
|
+
String_Schema_Obj s2 = Cast<String_Schema>(b->right());
|
|
717
|
+
Binary_Expression_Obj b1 = Cast<Binary_Expression>(b->left());
|
|
718
|
+
Binary_Expression_Obj b2 = Cast<Binary_Expression>(b->right());
|
|
594
719
|
|
|
595
720
|
bool schema_op = false;
|
|
596
721
|
|
|
@@ -604,40 +729,26 @@ namespace Sass {
|
|
|
604
729
|
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 ||
|
|
605
730
|
op_type == Sass_OP::EQ) {
|
|
606
731
|
// If possible upgrade LHS to a number (for number to string compare)
|
|
607
|
-
if (String_Constant_Ptr str =
|
|
732
|
+
if (String_Constant_Ptr str = Cast<String_Constant>(lhs)) {
|
|
608
733
|
std::string value(str->value());
|
|
609
734
|
const char* start = value.c_str();
|
|
610
735
|
if (Prelexer::sequence < Prelexer::dimension, Prelexer::end_of_file >(start) != 0) {
|
|
611
|
-
|
|
612
|
-
lhs = l->perform(this);
|
|
736
|
+
lhs = Parser::lexed_dimension(b->pstate(), str->value());
|
|
613
737
|
}
|
|
614
738
|
}
|
|
615
739
|
// If possible upgrade RHS to a number (for string to number compare)
|
|
616
|
-
if (String_Constant_Ptr str =
|
|
740
|
+
if (String_Constant_Ptr str = Cast<String_Constant>(rhs)) {
|
|
617
741
|
std::string value(str->value());
|
|
618
742
|
const char* start = value.c_str();
|
|
619
743
|
if (Prelexer::sequence < Prelexer::dimension, Prelexer::number >(start) != 0) {
|
|
620
|
-
|
|
621
|
-
rhs = r->perform(this);
|
|
744
|
+
rhs = Parser::lexed_dimension(b->pstate(), str->value());
|
|
622
745
|
}
|
|
623
746
|
}
|
|
624
747
|
}
|
|
625
748
|
|
|
626
749
|
To_Value to_value(ctx);
|
|
627
|
-
Value_Obj v_l =
|
|
628
|
-
Value_Obj v_r =
|
|
629
|
-
l_type = lhs->concrete_type();
|
|
630
|
-
r_type = rhs->concrete_type();
|
|
631
|
-
|
|
632
|
-
if (s2 && s2->has_interpolants() && s2->length()) {
|
|
633
|
-
Textual_Obj front = SASS_MEMORY_CAST(Textual, s2->elements().front());
|
|
634
|
-
if (front && !front->is_interpolant())
|
|
635
|
-
{
|
|
636
|
-
// XXX: this is never hit via spec tests
|
|
637
|
-
schema_op = true;
|
|
638
|
-
rhs = front->perform(this);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
750
|
+
Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
|
|
751
|
+
Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
|
|
641
752
|
|
|
642
753
|
if (force_delay) {
|
|
643
754
|
std::string str("");
|
|
@@ -655,19 +766,20 @@ namespace Sass {
|
|
|
655
766
|
// see if it's a relational expression
|
|
656
767
|
try {
|
|
657
768
|
switch(op_type) {
|
|
658
|
-
case Sass_OP::EQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), eq(lhs, rhs));
|
|
659
|
-
case Sass_OP::NEQ: return SASS_MEMORY_NEW(Boolean, b->pstate(),
|
|
660
|
-
case Sass_OP::GT: return SASS_MEMORY_NEW(Boolean, b->pstate(),
|
|
661
|
-
case Sass_OP::GTE: return SASS_MEMORY_NEW(Boolean, b->pstate(),
|
|
662
|
-
case Sass_OP::LT: return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs
|
|
663
|
-
case Sass_OP::LTE: return SASS_MEMORY_NEW(Boolean, b->pstate(),
|
|
664
|
-
default:
|
|
769
|
+
case Sass_OP::EQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::eq(lhs, rhs));
|
|
770
|
+
case Sass_OP::NEQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::neq(lhs, rhs));
|
|
771
|
+
case Sass_OP::GT: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::gt(lhs, rhs));
|
|
772
|
+
case Sass_OP::GTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::gte(lhs, rhs));
|
|
773
|
+
case Sass_OP::LT: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::lt(lhs, rhs));
|
|
774
|
+
case Sass_OP::LTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), Operators::lte(lhs, rhs));
|
|
775
|
+
default: break;
|
|
665
776
|
}
|
|
666
777
|
}
|
|
667
778
|
catch (Exception::OperationError& err)
|
|
668
779
|
{
|
|
669
780
|
// throw Exception::Base(b->pstate(), err.what());
|
|
670
|
-
|
|
781
|
+
traces.push_back(Backtrace(b->pstate()));
|
|
782
|
+
throw Exception::SassValueError(traces, b->pstate(), err);
|
|
671
783
|
}
|
|
672
784
|
|
|
673
785
|
l_type = lhs->concrete_type();
|
|
@@ -675,53 +787,56 @@ namespace Sass {
|
|
|
675
787
|
|
|
676
788
|
// ToDo: throw error in op functions
|
|
677
789
|
// ToDo: then catch and re-throw them
|
|
678
|
-
Expression_Obj rv
|
|
790
|
+
Expression_Obj rv;
|
|
679
791
|
try {
|
|
680
792
|
ParserState pstate(b->pstate());
|
|
681
793
|
if (l_type == Expression::NUMBER && r_type == Expression::NUMBER) {
|
|
682
|
-
Number_Ptr l_n =
|
|
683
|
-
Number_Ptr r_n =
|
|
684
|
-
|
|
794
|
+
Number_Ptr l_n = Cast<Number>(lhs);
|
|
795
|
+
Number_Ptr r_n = Cast<Number>(rhs);
|
|
796
|
+
l_n->reduce(); r_n->reduce();
|
|
797
|
+
rv = Operators::op_numbers(op_type, *l_n, *r_n, ctx.c_options, pstate);
|
|
685
798
|
}
|
|
686
799
|
else if (l_type == Expression::NUMBER && r_type == Expression::COLOR) {
|
|
687
|
-
Number_Ptr l_n =
|
|
688
|
-
Color_Ptr r_c =
|
|
689
|
-
rv = op_number_color(op_type, *l_n, *r_c, ctx.c_options,
|
|
800
|
+
Number_Ptr l_n = Cast<Number>(lhs);
|
|
801
|
+
Color_Ptr r_c = Cast<Color>(rhs);
|
|
802
|
+
rv = Operators::op_number_color(op_type, *l_n, *r_c, ctx.c_options, pstate);
|
|
690
803
|
}
|
|
691
804
|
else if (l_type == Expression::COLOR && r_type == Expression::NUMBER) {
|
|
692
|
-
Color_Ptr l_c =
|
|
693
|
-
Number_Ptr r_n =
|
|
694
|
-
rv = op_color_number(op_type, *l_c, *r_n, ctx.c_options,
|
|
805
|
+
Color_Ptr l_c = Cast<Color>(lhs);
|
|
806
|
+
Number_Ptr r_n = Cast<Number>(rhs);
|
|
807
|
+
rv = Operators::op_color_number(op_type, *l_c, *r_n, ctx.c_options, pstate);
|
|
695
808
|
}
|
|
696
809
|
else if (l_type == Expression::COLOR && r_type == Expression::COLOR) {
|
|
697
|
-
Color_Ptr l_c =
|
|
698
|
-
Color_Ptr r_c =
|
|
699
|
-
rv = op_colors(op_type, *l_c, *r_c, ctx.c_options,
|
|
810
|
+
Color_Ptr l_c = Cast<Color>(lhs);
|
|
811
|
+
Color_Ptr r_c = Cast<Color>(rhs);
|
|
812
|
+
rv = Operators::op_colors(op_type, *l_c, *r_c, ctx.c_options, pstate);
|
|
700
813
|
}
|
|
701
814
|
else {
|
|
702
815
|
To_Value to_value(ctx);
|
|
703
816
|
// this will leak if perform does not return a value!
|
|
704
|
-
Value_Obj v_l =
|
|
705
|
-
Value_Obj v_r =
|
|
817
|
+
Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
|
|
818
|
+
Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
|
|
706
819
|
bool interpolant = b->is_right_interpolant() ||
|
|
707
820
|
b->is_left_interpolant() ||
|
|
708
821
|
b->is_interpolant();
|
|
709
822
|
if (op_type == Sass_OP::SUB) interpolant = false;
|
|
710
823
|
// if (op_type == Sass_OP::DIV) interpolant = true;
|
|
711
824
|
// check for type violations
|
|
712
|
-
if (l_type == Expression::MAP) {
|
|
713
|
-
|
|
825
|
+
if (l_type == Expression::MAP || l_type == Expression::FUNCTION_VAL) {
|
|
826
|
+
traces.push_back(Backtrace(v_l->pstate()));
|
|
827
|
+
throw Exception::InvalidValue(traces, *v_l);
|
|
714
828
|
}
|
|
715
|
-
if (r_type == Expression::MAP) {
|
|
716
|
-
|
|
829
|
+
if (r_type == Expression::MAP || l_type == Expression::FUNCTION_VAL) {
|
|
830
|
+
traces.push_back(Backtrace(v_r->pstate()));
|
|
831
|
+
throw Exception::InvalidValue(traces, *v_r);
|
|
717
832
|
}
|
|
718
|
-
Value_Ptr ex = op_strings(b->op(), *v_l, *v_r, ctx.c_options,
|
|
719
|
-
if (String_Constant_Ptr str =
|
|
833
|
+
Value_Ptr ex = Operators::op_strings(b->op(), *v_l, *v_r, ctx.c_options, pstate, !interpolant); // pass true to compress
|
|
834
|
+
if (String_Constant_Ptr str = Cast<String_Constant>(ex))
|
|
720
835
|
{
|
|
721
836
|
if (str->concrete_type() == Expression::STRING)
|
|
722
837
|
{
|
|
723
|
-
String_Constant_Ptr lstr =
|
|
724
|
-
String_Constant_Ptr rstr =
|
|
838
|
+
String_Constant_Ptr lstr = Cast<String_Constant>(lhs);
|
|
839
|
+
String_Constant_Ptr rstr = Cast<String_Constant>(rhs);
|
|
725
840
|
if (op_type != Sass_OP::SUB) {
|
|
726
841
|
if (String_Constant_Ptr org = lstr ? lstr : rstr)
|
|
727
842
|
{ str->quote_mark(org->quote_mark()); }
|
|
@@ -734,8 +849,9 @@ namespace Sass {
|
|
|
734
849
|
}
|
|
735
850
|
catch (Exception::OperationError& err)
|
|
736
851
|
{
|
|
852
|
+
traces.push_back(Backtrace(b->pstate()));
|
|
737
853
|
// throw Exception::Base(b->pstate(), err.what());
|
|
738
|
-
throw Exception::SassValueError(b->pstate(), err);
|
|
854
|
+
throw Exception::SassValueError(traces, b->pstate(), err);
|
|
739
855
|
}
|
|
740
856
|
|
|
741
857
|
if (rv) {
|
|
@@ -753,31 +869,36 @@ namespace Sass {
|
|
|
753
869
|
Expression_Ptr Eval::operator()(Unary_Expression_Ptr u)
|
|
754
870
|
{
|
|
755
871
|
Expression_Obj operand = u->operand()->perform(this);
|
|
756
|
-
if (u->
|
|
872
|
+
if (u->optype() == Unary_Expression::NOT) {
|
|
757
873
|
Boolean_Ptr result = SASS_MEMORY_NEW(Boolean, u->pstate(), (bool)*operand);
|
|
758
874
|
result->value(!result->value());
|
|
759
875
|
return result;
|
|
760
876
|
}
|
|
761
|
-
else if (
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
877
|
+
else if (Number_Obj nr = Cast<Number>(operand)) {
|
|
878
|
+
// negate value for minus unary expression
|
|
879
|
+
if (u->optype() == Unary_Expression::MINUS) {
|
|
880
|
+
Number_Obj cpy = SASS_MEMORY_COPY(nr);
|
|
881
|
+
cpy->value( - cpy->value() ); // negate value
|
|
882
|
+
return cpy.detach(); // return the copy
|
|
883
|
+
}
|
|
884
|
+
else if (u->optype() == Unary_Expression::SLASH) {
|
|
885
|
+
std::string str = '/' + nr->to_string(ctx.c_options);
|
|
886
|
+
return SASS_MEMORY_NEW(String_Constant, u->pstate(), str);
|
|
887
|
+
}
|
|
888
|
+
// nothing for positive
|
|
889
|
+
return nr.detach();
|
|
767
890
|
}
|
|
768
891
|
else {
|
|
769
892
|
// Special cases: +/- variables which evaluate to null ouput just +/-,
|
|
770
893
|
// but +/- null itself outputs the string
|
|
771
|
-
if (operand->concrete_type() == Expression::NULL_VAL &&
|
|
894
|
+
if (operand->concrete_type() == Expression::NULL_VAL && Cast<Variable>(u->operand())) {
|
|
772
895
|
u->operand(SASS_MEMORY_NEW(String_Quoted, u->pstate(), ""));
|
|
773
896
|
}
|
|
774
897
|
// Never apply unary opertions on colors @see #2140
|
|
775
|
-
else if (
|
|
776
|
-
Color_Ptr c = dynamic_cast<Color_Ptr>(&operand);
|
|
777
|
-
|
|
898
|
+
else if (Color_Ptr color = Cast<Color>(operand)) {
|
|
778
899
|
// Use the color name if this was eval with one
|
|
779
|
-
if (
|
|
780
|
-
operand = SASS_MEMORY_NEW(String_Constant, operand->pstate(),
|
|
900
|
+
if (color->disp().length() > 0) {
|
|
901
|
+
operand = SASS_MEMORY_NEW(String_Constant, operand->pstate(), color->disp());
|
|
781
902
|
u->operand(operand);
|
|
782
903
|
}
|
|
783
904
|
}
|
|
@@ -785,10 +906,9 @@ namespace Sass {
|
|
|
785
906
|
u->operand(operand);
|
|
786
907
|
}
|
|
787
908
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
return result;
|
|
909
|
+
return SASS_MEMORY_NEW(String_Quoted,
|
|
910
|
+
u->pstate(),
|
|
911
|
+
u->inspect());
|
|
792
912
|
}
|
|
793
913
|
// unreachable
|
|
794
914
|
return u;
|
|
@@ -796,11 +916,11 @@ namespace Sass {
|
|
|
796
916
|
|
|
797
917
|
Expression_Ptr Eval::operator()(Function_Call_Ptr c)
|
|
798
918
|
{
|
|
799
|
-
if (
|
|
919
|
+
if (traces.size() > Constants::MaxCallStack) {
|
|
800
920
|
// XXX: this is never hit via spec tests
|
|
801
921
|
std::ostringstream stm;
|
|
802
922
|
stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
|
|
803
|
-
error(stm.str(), c->pstate(),
|
|
923
|
+
error(stm.str(), c->pstate(), traces);
|
|
804
924
|
}
|
|
805
925
|
std::string name(Util::normalize_underscores(c->name()));
|
|
806
926
|
std::string full_name(name + "[f]");
|
|
@@ -811,17 +931,17 @@ namespace Sass {
|
|
|
811
931
|
if (!env->has(full_name) || (!c->via_call() && Prelexer::re_special_fun(name.c_str()))) {
|
|
812
932
|
if (!env->has("*[f]")) {
|
|
813
933
|
for (Argument_Obj arg : args->elements()) {
|
|
814
|
-
if (List_Obj ls =
|
|
815
|
-
if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate());
|
|
934
|
+
if (List_Obj ls = Cast<List>(arg->value())) {
|
|
935
|
+
if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate(), traces);
|
|
816
936
|
}
|
|
817
937
|
}
|
|
818
|
-
args =
|
|
938
|
+
args = Cast<Arguments>(args->perform(this));
|
|
819
939
|
Function_Call_Obj lit = SASS_MEMORY_NEW(Function_Call,
|
|
820
940
|
c->pstate(),
|
|
821
941
|
c->name(),
|
|
822
|
-
|
|
942
|
+
args);
|
|
823
943
|
if (args->has_named_arguments()) {
|
|
824
|
-
error("Function " + c->name() + " doesn't support keyword arguments", c->pstate());
|
|
944
|
+
error("Function " + c->name() + " doesn't support keyword arguments", c->pstate(), traces);
|
|
825
945
|
}
|
|
826
946
|
String_Quoted_Ptr str = SASS_MEMORY_NEW(String_Quoted,
|
|
827
947
|
c->pstate(),
|
|
@@ -839,9 +959,11 @@ namespace Sass {
|
|
|
839
959
|
args->set_delayed(false); // verified
|
|
840
960
|
}
|
|
841
961
|
if (full_name != "if[f]") {
|
|
842
|
-
args =
|
|
962
|
+
args = Cast<Arguments>(args->perform(this));
|
|
843
963
|
}
|
|
844
|
-
Definition_Ptr def =
|
|
964
|
+
Definition_Ptr def = Cast<Definition>((*env)[full_name]);
|
|
965
|
+
|
|
966
|
+
if (c->func()) def = c->func()->definition();
|
|
845
967
|
|
|
846
968
|
if (def->is_overload_stub()) {
|
|
847
969
|
std::stringstream ss;
|
|
@@ -849,15 +971,15 @@ namespace Sass {
|
|
|
849
971
|
// account for rest arguments
|
|
850
972
|
if (args->has_rest_argument() && args->length() > 0) {
|
|
851
973
|
// get the rest arguments list
|
|
852
|
-
List_Ptr rest =
|
|
974
|
+
List_Ptr rest = Cast<List>(args->last()->value());
|
|
853
975
|
// arguments before rest argument plus rest
|
|
854
976
|
if (rest) L += rest->length() - 1;
|
|
855
977
|
}
|
|
856
978
|
ss << full_name << L;
|
|
857
979
|
full_name = ss.str();
|
|
858
980
|
std::string resolved_name(full_name);
|
|
859
|
-
if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate());
|
|
860
|
-
def =
|
|
981
|
+
if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate(), traces);
|
|
982
|
+
def = Cast<Definition>((*env)[resolved_name]);
|
|
861
983
|
}
|
|
862
984
|
|
|
863
985
|
Expression_Obj result = c;
|
|
@@ -865,25 +987,37 @@ namespace Sass {
|
|
|
865
987
|
Native_Function func = def->native_function();
|
|
866
988
|
Sass_Function_Entry c_function = def->c_function();
|
|
867
989
|
|
|
990
|
+
if (c->is_css()) return result.detach();
|
|
991
|
+
|
|
868
992
|
Parameters_Obj params = def->parameters();
|
|
869
993
|
Env fn_env(def->environment());
|
|
870
994
|
exp.env_stack.push_back(&fn_env);
|
|
871
995
|
|
|
872
996
|
if (func || body) {
|
|
873
997
|
bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this);
|
|
874
|
-
|
|
875
|
-
|
|
998
|
+
std::string msg(", in function `" + c->name() + "`");
|
|
999
|
+
traces.push_back(Backtrace(c->pstate(), msg));
|
|
1000
|
+
ctx.callee_stack.push_back({
|
|
1001
|
+
c->name().c_str(),
|
|
1002
|
+
c->pstate().path,
|
|
1003
|
+
c->pstate().line + 1,
|
|
1004
|
+
c->pstate().column + 1,
|
|
1005
|
+
SASS_CALLEE_FUNCTION,
|
|
1006
|
+
{ env }
|
|
1007
|
+
});
|
|
1008
|
+
|
|
876
1009
|
// eval the body if user-defined or special, invoke underlying CPP function if native
|
|
877
1010
|
if (body /* && !Prelexer::re_special_fun(name.c_str()) */) {
|
|
878
1011
|
result = body->perform(this);
|
|
879
1012
|
}
|
|
880
1013
|
else if (func) {
|
|
881
|
-
result = func(fn_env, *env, ctx, def->signature(), c->pstate(),
|
|
1014
|
+
result = func(fn_env, *env, ctx, def->signature(), c->pstate(), traces, exp.selector_stack);
|
|
882
1015
|
}
|
|
883
1016
|
if (!result) {
|
|
884
|
-
error(std::string("Function ") + c->name() + "
|
|
1017
|
+
error(std::string("Function ") + c->name() + " finished without @return", c->pstate(), traces);
|
|
885
1018
|
}
|
|
886
|
-
|
|
1019
|
+
ctx.callee_stack.pop_back();
|
|
1020
|
+
traces.pop_back();
|
|
887
1021
|
}
|
|
888
1022
|
|
|
889
1023
|
// else if it's a user-defined c function
|
|
@@ -893,36 +1027,44 @@ namespace Sass {
|
|
|
893
1027
|
if (full_name == "*[f]") {
|
|
894
1028
|
String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, c->pstate(), c->name());
|
|
895
1029
|
Arguments_Obj new_args = SASS_MEMORY_NEW(Arguments, c->pstate());
|
|
896
|
-
new_args->append(SASS_MEMORY_NEW(Argument, c->pstate(),
|
|
897
|
-
new_args->concat(
|
|
1030
|
+
new_args->append(SASS_MEMORY_NEW(Argument, c->pstate(), str));
|
|
1031
|
+
new_args->concat(args);
|
|
898
1032
|
args = new_args;
|
|
899
1033
|
}
|
|
900
1034
|
|
|
901
1035
|
// populates env with default values for params
|
|
902
1036
|
std::string ff(c->name());
|
|
903
1037
|
bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this);
|
|
904
|
-
|
|
905
|
-
Backtrace
|
|
906
|
-
|
|
1038
|
+
std::string msg(", in function `" + c->name() + "`");
|
|
1039
|
+
traces.push_back(Backtrace(c->pstate(), msg));
|
|
1040
|
+
ctx.callee_stack.push_back({
|
|
1041
|
+
c->name().c_str(),
|
|
1042
|
+
c->pstate().path,
|
|
1043
|
+
c->pstate().line + 1,
|
|
1044
|
+
c->pstate().column + 1,
|
|
1045
|
+
SASS_CALLEE_C_FUNCTION,
|
|
1046
|
+
{ env }
|
|
1047
|
+
});
|
|
907
1048
|
|
|
908
1049
|
To_C to_c;
|
|
909
|
-
union Sass_Value* c_args = sass_make_list(params->length(), SASS_COMMA);
|
|
1050
|
+
union Sass_Value* c_args = sass_make_list(params->length(), SASS_COMMA, false);
|
|
910
1051
|
for(size_t i = 0; i < params->length(); i++) {
|
|
911
1052
|
Parameter_Obj param = params->at(i);
|
|
912
1053
|
std::string key = param->name();
|
|
913
1054
|
AST_Node_Obj node = fn_env.get_local(key);
|
|
914
|
-
Expression_Obj arg =
|
|
1055
|
+
Expression_Obj arg = Cast<Expression>(node);
|
|
915
1056
|
sass_list_set_value(c_args, i, arg->perform(&to_c));
|
|
916
1057
|
}
|
|
917
1058
|
union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
|
|
918
1059
|
if (sass_value_get_tag(c_val) == SASS_ERROR) {
|
|
919
|
-
error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(),
|
|
1060
|
+
error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), traces);
|
|
920
1061
|
} else if (sass_value_get_tag(c_val) == SASS_WARNING) {
|
|
921
|
-
error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->pstate(),
|
|
1062
|
+
error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->pstate(), traces);
|
|
922
1063
|
}
|
|
923
|
-
result = cval_to_astnode(c_val,
|
|
1064
|
+
result = cval_to_astnode(c_val, traces, c->pstate());
|
|
924
1065
|
|
|
925
|
-
|
|
1066
|
+
ctx.callee_stack.pop_back();
|
|
1067
|
+
traces.pop_back();
|
|
926
1068
|
sass_delete_value(c_args);
|
|
927
1069
|
if (c_val != c_args)
|
|
928
1070
|
sass_delete_value(c_val);
|
|
@@ -951,104 +1093,22 @@ namespace Sass {
|
|
|
951
1093
|
|
|
952
1094
|
Expression_Ptr Eval::operator()(Variable_Ptr v)
|
|
953
1095
|
{
|
|
954
|
-
std::string name(v->name());
|
|
955
1096
|
Expression_Obj value = 0;
|
|
956
1097
|
Env* env = environment();
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
else error("Undefined variable: \"" + v->name() + "\".", v->pstate());
|
|
961
|
-
if (
|
|
962
|
-
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
// behave according to as ruby sass (add leading zero)
|
|
966
|
-
if (Number_Ptr nr = SASS_MEMORY_CAST(Number, value)) {
|
|
967
|
-
nr->zero(true);
|
|
968
|
-
}
|
|
969
|
-
|
|
1098
|
+
const std::string& name(v->name());
|
|
1099
|
+
EnvResult rv(env->find(name));
|
|
1100
|
+
if (rv.found) value = static_cast<Expression*>(rv.it->second.ptr());
|
|
1101
|
+
else error("Undefined variable: \"" + v->name() + "\".", v->pstate(), traces);
|
|
1102
|
+
if (Argument_Ptr arg = Cast<Argument>(value)) value = arg->value();
|
|
1103
|
+
if (Number_Ptr nr = Cast<Number>(value)) nr->zero(true); // force flag
|
|
970
1104
|
value->is_interpolant(v->is_interpolant());
|
|
971
1105
|
if (force) value->is_expanded(false);
|
|
972
1106
|
value->set_delayed(false); // verified
|
|
973
1107
|
value = value->perform(this);
|
|
974
|
-
if(!force)
|
|
1108
|
+
if(!force) rv.it->second = value;
|
|
975
1109
|
return value.detach();
|
|
976
1110
|
}
|
|
977
1111
|
|
|
978
|
-
Expression_Ptr Eval::operator()(Textual_Ptr t)
|
|
979
|
-
{
|
|
980
|
-
using Prelexer::number;
|
|
981
|
-
Expression_Obj result = 0;
|
|
982
|
-
size_t L = t->value().length();
|
|
983
|
-
bool zero = !( (L > 0 && t->value().substr(0, 1) == ".") ||
|
|
984
|
-
(L > 1 && t->value().substr(0, 2) == "0.") ||
|
|
985
|
-
(L > 1 && t->value().substr(0, 2) == "-.") ||
|
|
986
|
-
(L > 2 && t->value().substr(0, 3) == "-0.")
|
|
987
|
-
);
|
|
988
|
-
|
|
989
|
-
const std::string& text = t->value();
|
|
990
|
-
size_t num_pos = text.find_first_not_of(" \n\r\t");
|
|
991
|
-
if (num_pos == std::string::npos) num_pos = text.length();
|
|
992
|
-
size_t unit_pos = text.find_first_not_of("-+0123456789.", num_pos);
|
|
993
|
-
if (unit_pos == std::string::npos) unit_pos = text.length();
|
|
994
|
-
const std::string& num = text.substr(num_pos, unit_pos - num_pos);
|
|
995
|
-
|
|
996
|
-
switch (t->type())
|
|
997
|
-
{
|
|
998
|
-
case Textual::NUMBER:
|
|
999
|
-
result = SASS_MEMORY_NEW(Number,
|
|
1000
|
-
t->pstate(),
|
|
1001
|
-
sass_atof(num.c_str()),
|
|
1002
|
-
"",
|
|
1003
|
-
zero);
|
|
1004
|
-
break;
|
|
1005
|
-
case Textual::PERCENTAGE:
|
|
1006
|
-
result = SASS_MEMORY_NEW(Number,
|
|
1007
|
-
t->pstate(),
|
|
1008
|
-
sass_atof(num.c_str()),
|
|
1009
|
-
"%",
|
|
1010
|
-
true);
|
|
1011
|
-
break;
|
|
1012
|
-
case Textual::DIMENSION:
|
|
1013
|
-
result = SASS_MEMORY_NEW(Number,
|
|
1014
|
-
t->pstate(),
|
|
1015
|
-
sass_atof(num.c_str()),
|
|
1016
|
-
Token(number(text.c_str())),
|
|
1017
|
-
zero);
|
|
1018
|
-
break;
|
|
1019
|
-
case Textual::HEX: {
|
|
1020
|
-
if (t->value().substr(0, 1) != "#") {
|
|
1021
|
-
result = SASS_MEMORY_NEW(String_Quoted, t->pstate(), t->value());
|
|
1022
|
-
break;
|
|
1023
|
-
}
|
|
1024
|
-
std::string hext(t->value().substr(1)); // chop off the '#'
|
|
1025
|
-
if (hext.length() == 6) {
|
|
1026
|
-
std::string r(hext.substr(0,2));
|
|
1027
|
-
std::string g(hext.substr(2,2));
|
|
1028
|
-
std::string b(hext.substr(4,2));
|
|
1029
|
-
result = SASS_MEMORY_NEW(Color,
|
|
1030
|
-
t->pstate(),
|
|
1031
|
-
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
|
1032
|
-
static_cast<double>(strtol(g.c_str(), NULL, 16)),
|
|
1033
|
-
static_cast<double>(strtol(b.c_str(), NULL, 16)),
|
|
1034
|
-
1, // alpha channel
|
|
1035
|
-
t->value());
|
|
1036
|
-
}
|
|
1037
|
-
else {
|
|
1038
|
-
result = SASS_MEMORY_NEW(Color,
|
|
1039
|
-
t->pstate(),
|
|
1040
|
-
static_cast<double>(strtol(std::string(2,hext[0]).c_str(), NULL, 16)),
|
|
1041
|
-
static_cast<double>(strtol(std::string(2,hext[1]).c_str(), NULL, 16)),
|
|
1042
|
-
static_cast<double>(strtol(std::string(2,hext[2]).c_str(), NULL, 16)),
|
|
1043
|
-
1, // alpha channel
|
|
1044
|
-
t->value());
|
|
1045
|
-
}
|
|
1046
|
-
} break;
|
|
1047
|
-
}
|
|
1048
|
-
result->is_interpolant(t->is_interpolant());
|
|
1049
|
-
return result.detach();
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
1112
|
Expression_Ptr Eval::operator()(Color_Ptr c)
|
|
1053
1113
|
{
|
|
1054
1114
|
return c;
|
|
@@ -1068,7 +1128,7 @@ namespace Sass {
|
|
|
1068
1128
|
|
|
1069
1129
|
bool needs_closing_brace = false;
|
|
1070
1130
|
|
|
1071
|
-
if (Arguments_Ptr args =
|
|
1131
|
+
if (Arguments_Ptr args = Cast<Arguments>(ex)) {
|
|
1072
1132
|
List_Ptr ll = SASS_MEMORY_NEW(List, args->pstate(), 0, SASS_COMMA);
|
|
1073
1133
|
for(auto arg : args->elements()) {
|
|
1074
1134
|
ll->append(arg->value());
|
|
@@ -1078,15 +1138,18 @@ namespace Sass {
|
|
|
1078
1138
|
res += "(";
|
|
1079
1139
|
ex = ll;
|
|
1080
1140
|
}
|
|
1081
|
-
if (Number_Ptr nr =
|
|
1082
|
-
|
|
1083
|
-
|
|
1141
|
+
if (Number_Ptr nr = Cast<Number>(ex)) {
|
|
1142
|
+
Number reduced(nr);
|
|
1143
|
+
reduced.reduce();
|
|
1144
|
+
if (!reduced.is_valid_css_unit()) {
|
|
1145
|
+
traces.push_back(Backtrace(nr->pstate()));
|
|
1146
|
+
throw Exception::InvalidValue(traces, *nr);
|
|
1084
1147
|
}
|
|
1085
1148
|
}
|
|
1086
|
-
if (Argument_Ptr arg =
|
|
1087
|
-
ex =
|
|
1149
|
+
if (Argument_Ptr arg = Cast<Argument>(ex)) {
|
|
1150
|
+
ex = arg->value();
|
|
1088
1151
|
}
|
|
1089
|
-
if (String_Quoted_Ptr sq =
|
|
1152
|
+
if (String_Quoted_Ptr sq = Cast<String_Quoted>(ex)) {
|
|
1090
1153
|
if (was_itpl) {
|
|
1091
1154
|
bool was_interpolant = ex->is_interpolant();
|
|
1092
1155
|
ex = SASS_MEMORY_NEW(String_Constant, sq->pstate(), sq->value());
|
|
@@ -1094,22 +1157,22 @@ namespace Sass {
|
|
|
1094
1157
|
}
|
|
1095
1158
|
}
|
|
1096
1159
|
|
|
1097
|
-
if (
|
|
1160
|
+
if (Cast<Null>(ex)) { return; }
|
|
1098
1161
|
|
|
1099
1162
|
// parent selector needs another go
|
|
1100
|
-
if (
|
|
1163
|
+
if (Cast<Parent_Selector>(ex)) {
|
|
1101
1164
|
// XXX: this is never hit via spec tests
|
|
1102
1165
|
ex = ex->perform(this);
|
|
1103
1166
|
}
|
|
1104
1167
|
|
|
1105
|
-
if (List_Ptr l =
|
|
1168
|
+
if (List_Ptr l = Cast<List>(ex)) {
|
|
1106
1169
|
List_Obj ll = SASS_MEMORY_NEW(List, l->pstate(), 0, l->separator());
|
|
1107
1170
|
// this fixes an issue with bourbon sample, not really sure why
|
|
1108
|
-
// if (l->size() &&
|
|
1171
|
+
// if (l->size() && Cast<Null>((*l)[0])) { res += ""; }
|
|
1109
1172
|
for(Expression_Obj item : *l) {
|
|
1110
1173
|
item->is_interpolant(l->is_interpolant());
|
|
1111
|
-
std::string rl(""); interpolation(ctx, rl,
|
|
1112
|
-
bool is_null =
|
|
1174
|
+
std::string rl(""); interpolation(ctx, rl, item, into_quotes, l->is_interpolant());
|
|
1175
|
+
bool is_null = Cast<Null>(item) != 0; // rl != ""
|
|
1113
1176
|
if (!is_null) ll->append(SASS_MEMORY_NEW(String_Quoted, item->pstate(), rl));
|
|
1114
1177
|
}
|
|
1115
1178
|
// Check indicates that we probably should not get a list
|
|
@@ -1117,6 +1180,7 @@ namespace Sass {
|
|
|
1117
1180
|
if (l->size() > 1) {
|
|
1118
1181
|
// string_to_output would fail "#{'_\a' '_\a'}";
|
|
1119
1182
|
std::string str(ll->to_string(ctx.c_options));
|
|
1183
|
+
str = read_hex_escapes(str); // read escapes
|
|
1120
1184
|
newline_to_space(str); // replace directly
|
|
1121
1185
|
res += str; // append to result string
|
|
1122
1186
|
} else {
|
|
@@ -1126,7 +1190,6 @@ namespace Sass {
|
|
|
1126
1190
|
}
|
|
1127
1191
|
|
|
1128
1192
|
// Value
|
|
1129
|
-
// Textual
|
|
1130
1193
|
// Function_Call
|
|
1131
1194
|
// Selector_List
|
|
1132
1195
|
// String_Quoted
|
|
@@ -1138,7 +1201,9 @@ namespace Sass {
|
|
|
1138
1201
|
if (into_quotes && ex->is_interpolant()) {
|
|
1139
1202
|
res += evacuate_escapes(ex ? ex->to_string(ctx.c_options) : "");
|
|
1140
1203
|
} else {
|
|
1141
|
-
|
|
1204
|
+
std::string str(ex ? ex->to_string(ctx.c_options) : "");
|
|
1205
|
+
if (into_quotes) str = read_hex_escapes(str);
|
|
1206
|
+
res += str; // append to result string
|
|
1142
1207
|
}
|
|
1143
1208
|
}
|
|
1144
1209
|
|
|
@@ -1151,9 +1216,9 @@ namespace Sass {
|
|
|
1151
1216
|
size_t L = s->length();
|
|
1152
1217
|
bool into_quotes = false;
|
|
1153
1218
|
if (L > 1) {
|
|
1154
|
-
if (!
|
|
1155
|
-
if (String_Constant_Ptr l =
|
|
1156
|
-
if (String_Constant_Ptr r =
|
|
1219
|
+
if (!Cast<String_Quoted>((*s)[0]) && !Cast<String_Quoted>((*s)[L - 1])) {
|
|
1220
|
+
if (String_Constant_Ptr l = Cast<String_Constant>((*s)[0])) {
|
|
1221
|
+
if (String_Constant_Ptr r = Cast<String_Constant>((*s)[L - 1])) {
|
|
1157
1222
|
if (r->value().size() > 0) {
|
|
1158
1223
|
if (l->value()[0] == '"' && r->value()[r->value().size() - 1] == '"') into_quotes = true;
|
|
1159
1224
|
if (l->value()[0] == '\'' && r->value()[r->value().size() - 1] == '\'') into_quotes = true;
|
|
@@ -1166,21 +1231,21 @@ namespace Sass {
|
|
|
1166
1231
|
bool was_interpolant = false;
|
|
1167
1232
|
std::string res("");
|
|
1168
1233
|
for (size_t i = 0; i < L; ++i) {
|
|
1169
|
-
bool is_quoted =
|
|
1234
|
+
bool is_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
|
|
1170
1235
|
if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
|
1171
1236
|
else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
|
1172
1237
|
Expression_Obj ex = (*s)[i]->perform(this);
|
|
1173
1238
|
interpolation(ctx, res, ex, into_quotes, ex->is_interpolant());
|
|
1174
|
-
was_quoted =
|
|
1239
|
+
was_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
|
|
1175
1240
|
was_interpolant = (*s)[i]->is_interpolant();
|
|
1176
1241
|
|
|
1177
1242
|
}
|
|
1178
1243
|
if (!s->is_interpolant()) {
|
|
1179
1244
|
if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(Null, s->pstate());
|
|
1180
|
-
return SASS_MEMORY_NEW(String_Constant, s->pstate(), res);
|
|
1245
|
+
return SASS_MEMORY_NEW(String_Constant, s->pstate(), res, s->css());
|
|
1181
1246
|
}
|
|
1182
1247
|
// string schema seems to have a special unquoting behavior (also handles "nested" quotes)
|
|
1183
|
-
String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), res, 0, false, false, false);
|
|
1248
|
+
String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), res, 0, false, false, false, s->css());
|
|
1184
1249
|
// if (s->is_interpolant()) str->quote_mark(0);
|
|
1185
1250
|
// String_Constant_Ptr str = SASS_MEMORY_NEW(String_Constant, s->pstate(), res);
|
|
1186
1251
|
if (str->quote_mark()) str->quote_mark('*');
|
|
@@ -1192,13 +1257,6 @@ namespace Sass {
|
|
|
1192
1257
|
|
|
1193
1258
|
Expression_Ptr Eval::operator()(String_Constant_Ptr s)
|
|
1194
1259
|
{
|
|
1195
|
-
if (!s->is_delayed() && name_to_color(s->value())) {
|
|
1196
|
-
Color_Ptr c = SASS_MEMORY_COPY(name_to_color(s->value())); // copy
|
|
1197
|
-
c->pstate(s->pstate());
|
|
1198
|
-
c->disp(s->value());
|
|
1199
|
-
c->is_delayed(true);
|
|
1200
|
-
return c;
|
|
1201
|
-
}
|
|
1202
1260
|
return s;
|
|
1203
1261
|
}
|
|
1204
1262
|
|
|
@@ -1217,8 +1275,8 @@ namespace Sass {
|
|
|
1217
1275
|
Expression_Ptr right = c->right()->perform(this);
|
|
1218
1276
|
Supports_Operator_Ptr cc = SASS_MEMORY_NEW(Supports_Operator,
|
|
1219
1277
|
c->pstate(),
|
|
1220
|
-
|
|
1221
|
-
|
|
1278
|
+
Cast<Supports_Condition>(left),
|
|
1279
|
+
Cast<Supports_Condition>(right),
|
|
1222
1280
|
c->operand());
|
|
1223
1281
|
return cc;
|
|
1224
1282
|
}
|
|
@@ -1228,7 +1286,7 @@ namespace Sass {
|
|
|
1228
1286
|
Expression_Ptr condition = c->condition()->perform(this);
|
|
1229
1287
|
Supports_Negation_Ptr cc = SASS_MEMORY_NEW(Supports_Negation,
|
|
1230
1288
|
c->pstate(),
|
|
1231
|
-
|
|
1289
|
+
Cast<Supports_Condition>(condition));
|
|
1232
1290
|
return cc;
|
|
1233
1291
|
}
|
|
1234
1292
|
|
|
@@ -1260,18 +1318,18 @@ namespace Sass {
|
|
|
1260
1318
|
value = (value ? value->perform(this) : 0);
|
|
1261
1319
|
Expression_Ptr ee = SASS_MEMORY_NEW(At_Root_Query,
|
|
1262
1320
|
e->pstate(),
|
|
1263
|
-
|
|
1321
|
+
Cast<String>(feature),
|
|
1264
1322
|
value);
|
|
1265
1323
|
return ee;
|
|
1266
1324
|
}
|
|
1267
1325
|
|
|
1268
|
-
|
|
1326
|
+
Media_Query_Ptr Eval::operator()(Media_Query_Ptr q)
|
|
1269
1327
|
{
|
|
1270
1328
|
String_Obj t = q->media_type();
|
|
1271
|
-
t = static_cast<String_Ptr>(
|
|
1329
|
+
t = static_cast<String_Ptr>(t.isNull() ? 0 : t->perform(this));
|
|
1272
1330
|
Media_Query_Obj qq = SASS_MEMORY_NEW(Media_Query,
|
|
1273
1331
|
q->pstate(),
|
|
1274
|
-
|
|
1332
|
+
t,
|
|
1275
1333
|
q->length(),
|
|
1276
1334
|
q->is_negated(),
|
|
1277
1335
|
q->is_restricted());
|
|
@@ -1285,18 +1343,18 @@ namespace Sass {
|
|
|
1285
1343
|
{
|
|
1286
1344
|
Expression_Obj feature = e->feature();
|
|
1287
1345
|
feature = (feature ? feature->perform(this) : 0);
|
|
1288
|
-
if (feature &&
|
|
1346
|
+
if (feature && Cast<String_Quoted>(feature)) {
|
|
1289
1347
|
feature = SASS_MEMORY_NEW(String_Quoted,
|
|
1290
1348
|
feature->pstate(),
|
|
1291
|
-
|
|
1349
|
+
Cast<String_Quoted>(feature)->value());
|
|
1292
1350
|
}
|
|
1293
1351
|
Expression_Obj value = e->value();
|
|
1294
1352
|
value = (value ? value->perform(this) : 0);
|
|
1295
|
-
if (value &&
|
|
1353
|
+
if (value && Cast<String_Quoted>(value)) {
|
|
1296
1354
|
// XXX: this is never hit via spec tests
|
|
1297
1355
|
value = SASS_MEMORY_NEW(String_Quoted,
|
|
1298
1356
|
value->pstate(),
|
|
1299
|
-
|
|
1357
|
+
Cast<String_Quoted>(value)->value());
|
|
1300
1358
|
}
|
|
1301
1359
|
return SASS_MEMORY_NEW(Media_Query_Expression,
|
|
1302
1360
|
e->pstate(),
|
|
@@ -1328,7 +1386,7 @@ namespace Sass {
|
|
|
1328
1386
|
SASS_COMMA,
|
|
1329
1387
|
true);
|
|
1330
1388
|
wrapper->append(val);
|
|
1331
|
-
val =
|
|
1389
|
+
val = wrapper;
|
|
1332
1390
|
}
|
|
1333
1391
|
}
|
|
1334
1392
|
return SASS_MEMORY_NEW(Argument,
|
|
@@ -1345,7 +1403,7 @@ namespace Sass {
|
|
|
1345
1403
|
if (a->length() == 0) return aa.detach();
|
|
1346
1404
|
for (size_t i = 0, L = a->length(); i < L; ++i) {
|
|
1347
1405
|
Expression_Obj rv = (*a)[i]->perform(this);
|
|
1348
|
-
Argument_Ptr arg =
|
|
1406
|
+
Argument_Ptr arg = Cast<Argument>(rv);
|
|
1349
1407
|
if (!(arg->is_rest_argument() || arg->is_keyword_argument())) {
|
|
1350
1408
|
aa->append(arg);
|
|
1351
1409
|
}
|
|
@@ -1353,11 +1411,11 @@ namespace Sass {
|
|
|
1353
1411
|
|
|
1354
1412
|
if (a->has_rest_argument()) {
|
|
1355
1413
|
Expression_Obj rest = a->get_rest_argument()->perform(this);
|
|
1356
|
-
Expression_Obj splat =
|
|
1414
|
+
Expression_Obj splat = Cast<Argument>(rest)->value()->perform(this);
|
|
1357
1415
|
|
|
1358
1416
|
Sass_Separator separator = SASS_COMMA;
|
|
1359
|
-
List_Ptr ls =
|
|
1360
|
-
Map_Ptr ms =
|
|
1417
|
+
List_Ptr ls = Cast<List>(splat);
|
|
1418
|
+
Map_Ptr ms = Cast<Map>(splat);
|
|
1361
1419
|
|
|
1362
1420
|
List_Obj arglist = SASS_MEMORY_NEW(List,
|
|
1363
1421
|
splat->pstate(),
|
|
@@ -1375,13 +1433,13 @@ namespace Sass {
|
|
|
1375
1433
|
arglist->append(splat);
|
|
1376
1434
|
}
|
|
1377
1435
|
if (arglist->length()) {
|
|
1378
|
-
aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(),
|
|
1436
|
+
aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), arglist, "", true));
|
|
1379
1437
|
}
|
|
1380
1438
|
}
|
|
1381
1439
|
|
|
1382
1440
|
if (a->has_keyword_argument()) {
|
|
1383
1441
|
Expression_Obj rv = a->get_keyword_argument()->perform(this);
|
|
1384
|
-
Argument_Ptr rvarg =
|
|
1442
|
+
Argument_Ptr rvarg = Cast<Argument>(rv);
|
|
1385
1443
|
Expression_Obj kwarg = rvarg->value()->perform(this);
|
|
1386
1444
|
|
|
1387
1445
|
aa->append(SASS_MEMORY_NEW(Argument, kwarg->pstate(), kwarg, "", false, true));
|
|
@@ -1401,191 +1459,7 @@ namespace Sass {
|
|
|
1401
1459
|
|
|
1402
1460
|
// All the binary helpers.
|
|
1403
1461
|
|
|
1404
|
-
|
|
1405
|
-
{
|
|
1406
|
-
// use compare operator from ast node
|
|
1407
|
-
return lhs && rhs && *lhs == *rhs;
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
bool Eval::lt(Expression_Obj lhs, Expression_Obj rhs, std::string op)
|
|
1411
|
-
{
|
|
1412
|
-
Number_Obj l = SASS_MEMORY_CAST(Number, lhs);
|
|
1413
|
-
Number_Obj r = SASS_MEMORY_CAST(Number, rhs);
|
|
1414
|
-
// use compare operator from ast node
|
|
1415
|
-
if (!l || !r) throw Exception::UndefinedOperation(&lhs, &rhs, op);
|
|
1416
|
-
// use compare operator from ast node
|
|
1417
|
-
return *l < *r;
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
Value_Ptr Eval::op_numbers(enum Sass_OP op, const Number& l, const Number& r, struct Sass_Inspect_Options opt, ParserState* pstate)
|
|
1421
|
-
{
|
|
1422
|
-
double lv = l.value();
|
|
1423
|
-
double rv = r.value();
|
|
1424
|
-
if (op == Sass_OP::DIV && rv == 0) {
|
|
1425
|
-
// XXX: this is never hit via spec tests
|
|
1426
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate ? *pstate : l.pstate(), lv ? "Infinity" : "NaN");
|
|
1427
|
-
}
|
|
1428
|
-
if (op == Sass_OP::MOD && !rv) {
|
|
1429
|
-
// XXX: this is never hit via spec tests
|
|
1430
|
-
throw Exception::ZeroDivisionError(l, r);
|
|
1431
|
-
}
|
|
1432
|
-
|
|
1433
|
-
Number tmp(&r); // copy
|
|
1434
|
-
bool strict = op != Sass_OP::MUL && op != Sass_OP::DIV;
|
|
1435
|
-
tmp.normalize(l.find_convertible_unit(), strict);
|
|
1436
|
-
std::string l_unit(l.unit());
|
|
1437
|
-
std::string r_unit(tmp.unit());
|
|
1438
|
-
Number_Obj v = SASS_MEMORY_COPY(&l); // copy
|
|
1439
|
-
v->pstate(pstate ? *pstate : l.pstate());
|
|
1440
|
-
if (l_unit.empty() && (op == Sass_OP::ADD || op == Sass_OP::SUB || op == Sass_OP::MOD)) {
|
|
1441
|
-
v->numerator_units() = r.numerator_units();
|
|
1442
|
-
v->denominator_units() = r.denominator_units();
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
if (op == Sass_OP::MUL) {
|
|
1446
|
-
v->value(ops[op](lv, rv));
|
|
1447
|
-
for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) {
|
|
1448
|
-
v->numerator_units().push_back(r.numerator_units()[i]);
|
|
1449
|
-
}
|
|
1450
|
-
for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) {
|
|
1451
|
-
v->denominator_units().push_back(r.denominator_units()[i]);
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
else if (op == Sass_OP::DIV) {
|
|
1455
|
-
v->value(ops[op](lv, rv));
|
|
1456
|
-
for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) {
|
|
1457
|
-
v->denominator_units().push_back(r.numerator_units()[i]);
|
|
1458
|
-
}
|
|
1459
|
-
for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) {
|
|
1460
|
-
v->numerator_units().push_back(r.denominator_units()[i]);
|
|
1461
|
-
}
|
|
1462
|
-
} else {
|
|
1463
|
-
v->value(ops[op](lv, r.value() * r.convert_factor(l)));
|
|
1464
|
-
// v->normalize();
|
|
1465
|
-
return v.detach();
|
|
1466
|
-
|
|
1467
|
-
v->value(ops[op](lv, tmp.value()));
|
|
1468
|
-
}
|
|
1469
|
-
v->normalize();
|
|
1470
|
-
return v.detach();
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
|
-
Value_Ptr Eval::op_number_color(enum Sass_OP op, const Number& l, const Color& r, struct Sass_Inspect_Options opt, ParserState* pstate)
|
|
1474
|
-
{
|
|
1475
|
-
double lv = l.value();
|
|
1476
|
-
switch (op) {
|
|
1477
|
-
case Sass_OP::ADD:
|
|
1478
|
-
case Sass_OP::MUL: {
|
|
1479
|
-
return SASS_MEMORY_NEW(Color,
|
|
1480
|
-
pstate ? *pstate : l.pstate(),
|
|
1481
|
-
ops[op](lv, r.r()),
|
|
1482
|
-
ops[op](lv, r.g()),
|
|
1483
|
-
ops[op](lv, r.b()),
|
|
1484
|
-
r.a());
|
|
1485
|
-
} break;
|
|
1486
|
-
case Sass_OP::SUB:
|
|
1487
|
-
case Sass_OP::DIV: {
|
|
1488
|
-
std::string sep(op == Sass_OP::SUB ? "-" : "/");
|
|
1489
|
-
std::string color(r.to_string(opt));
|
|
1490
|
-
return SASS_MEMORY_NEW(String_Quoted,
|
|
1491
|
-
pstate ? *pstate : l.pstate(),
|
|
1492
|
-
l.to_string(opt)
|
|
1493
|
-
+ sep
|
|
1494
|
-
+ color);
|
|
1495
|
-
} break;
|
|
1496
|
-
case Sass_OP::MOD: {
|
|
1497
|
-
throw Exception::UndefinedOperation(&l, &r, sass_op_to_name(op));
|
|
1498
|
-
} break;
|
|
1499
|
-
default: break; // caller should ensure that we don't get here
|
|
1500
|
-
}
|
|
1501
|
-
// unreachable
|
|
1502
|
-
return NULL;
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
Value_Ptr Eval::op_color_number(enum Sass_OP op, const Color& l, const Number& r, struct Sass_Inspect_Options opt, ParserState* pstate)
|
|
1506
|
-
{
|
|
1507
|
-
double rv = r.value();
|
|
1508
|
-
if (op == Sass_OP::DIV && !rv) {
|
|
1509
|
-
// comparison of Fixnum with Float failed?
|
|
1510
|
-
throw Exception::ZeroDivisionError(l, r);
|
|
1511
|
-
}
|
|
1512
|
-
return SASS_MEMORY_NEW(Color,
|
|
1513
|
-
pstate ? *pstate : l.pstate(),
|
|
1514
|
-
ops[op](l.r(), rv),
|
|
1515
|
-
ops[op](l.g(), rv),
|
|
1516
|
-
ops[op](l.b(), rv),
|
|
1517
|
-
l.a());
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
Value_Ptr Eval::op_colors(enum Sass_OP op, const Color& l, const Color& r, struct Sass_Inspect_Options opt, ParserState* pstate)
|
|
1521
|
-
{
|
|
1522
|
-
if (l.a() != r.a()) {
|
|
1523
|
-
throw Exception::AlphaChannelsNotEqual(&l, &r, "+");
|
|
1524
|
-
}
|
|
1525
|
-
if (op == Sass_OP::DIV && (!r.r() || !r.g() ||!r.b())) {
|
|
1526
|
-
// comparison of Fixnum with Float failed?
|
|
1527
|
-
throw Exception::ZeroDivisionError(l, r);
|
|
1528
|
-
}
|
|
1529
|
-
return SASS_MEMORY_NEW(Color,
|
|
1530
|
-
pstate ? *pstate : l.pstate(),
|
|
1531
|
-
ops[op](l.r(), r.r()),
|
|
1532
|
-
ops[op](l.g(), r.g()),
|
|
1533
|
-
ops[op](l.b(), r.b()),
|
|
1534
|
-
l.a());
|
|
1535
|
-
}
|
|
1536
|
-
|
|
1537
|
-
Value_Ptr Eval::op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, ParserState* pstate, bool delayed)
|
|
1538
|
-
{
|
|
1539
|
-
Expression::Concrete_Type ltype = lhs.concrete_type();
|
|
1540
|
-
Expression::Concrete_Type rtype = rhs.concrete_type();
|
|
1541
|
-
enum Sass_OP op = operand.operand;
|
|
1542
|
-
|
|
1543
|
-
String_Quoted_Ptr lqstr = dynamic_cast<String_Quoted_Ptr>(&lhs);
|
|
1544
|
-
String_Quoted_Ptr rqstr = dynamic_cast<String_Quoted_Ptr>(&rhs);
|
|
1545
|
-
|
|
1546
|
-
std::string lstr(lqstr ? lqstr->value() : lhs.to_string(opt));
|
|
1547
|
-
std::string rstr(rqstr ? rqstr->value() : rhs.to_string(opt));
|
|
1548
|
-
|
|
1549
|
-
if (ltype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op));
|
|
1550
|
-
if (rtype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op));
|
|
1551
|
-
if (op == Sass_OP::MOD) throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op));
|
|
1552
|
-
if (op == Sass_OP::MUL) throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op));
|
|
1553
|
-
std::string sep;
|
|
1554
|
-
switch (op) {
|
|
1555
|
-
case Sass_OP::SUB: sep = "-"; break;
|
|
1556
|
-
case Sass_OP::DIV: sep = "/"; break;
|
|
1557
|
-
case Sass_OP::MUL: sep = "*"; break;
|
|
1558
|
-
case Sass_OP::MOD: sep = "%"; break;
|
|
1559
|
-
case Sass_OP::EQ: sep = "=="; break;
|
|
1560
|
-
case Sass_OP::NEQ: sep = "!="; break;
|
|
1561
|
-
case Sass_OP::LT: sep = "<"; break;
|
|
1562
|
-
case Sass_OP::GT: sep = ">"; break;
|
|
1563
|
-
case Sass_OP::LTE: sep = "<="; break;
|
|
1564
|
-
case Sass_OP::GTE: sep = ">="; break;
|
|
1565
|
-
default: break;
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
if ( (sep == "") /* &&
|
|
1569
|
-
(sep != "/" || !rqstr || !rqstr->quote_mark()) */
|
|
1570
|
-
) {
|
|
1571
|
-
// create a new string that might be quoted on output (but do not unquote what we pass)
|
|
1572
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate ? *pstate : lhs.pstate(), lstr + rstr, 0, false, true);
|
|
1573
|
-
}
|
|
1574
|
-
|
|
1575
|
-
if (sep != "" && !delayed) {
|
|
1576
|
-
if (operand.ws_before) sep = " " + sep;
|
|
1577
|
-
if (operand.ws_after) sep = sep + " ";
|
|
1578
|
-
}
|
|
1579
|
-
|
|
1580
|
-
if (op == Sass_OP::SUB || op == Sass_OP::DIV) {
|
|
1581
|
-
if (lqstr && lqstr->quote_mark()) lstr = quote(lstr);
|
|
1582
|
-
if (rqstr && rqstr->quote_mark()) rstr = quote(rstr);
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1585
|
-
return SASS_MEMORY_NEW(String_Constant, pstate ? *pstate : lhs.pstate(), lstr + sep + rstr);
|
|
1586
|
-
}
|
|
1587
|
-
|
|
1588
|
-
Expression_Ptr cval_to_astnode(union Sass_Value* v, Backtrace* backtrace, ParserState pstate)
|
|
1462
|
+
Expression_Ptr cval_to_astnode(union Sass_Value* v, Backtraces traces, ParserState pstate)
|
|
1589
1463
|
{
|
|
1590
1464
|
using std::strlen;
|
|
1591
1465
|
using std::strcpy;
|
|
@@ -1610,16 +1484,17 @@ namespace Sass {
|
|
|
1610
1484
|
case SASS_LIST: {
|
|
1611
1485
|
List_Ptr l = SASS_MEMORY_NEW(List, pstate, sass_list_get_length(v), sass_list_get_separator(v));
|
|
1612
1486
|
for (size_t i = 0, L = sass_list_get_length(v); i < L; ++i) {
|
|
1613
|
-
l->append(cval_to_astnode(sass_list_get_value(v, i),
|
|
1487
|
+
l->append(cval_to_astnode(sass_list_get_value(v, i), traces, pstate));
|
|
1614
1488
|
}
|
|
1489
|
+
l->is_bracketed(sass_list_get_is_bracketed(v));
|
|
1615
1490
|
e = l;
|
|
1616
1491
|
} break;
|
|
1617
1492
|
case SASS_MAP: {
|
|
1618
1493
|
Map_Ptr m = SASS_MEMORY_NEW(Map, pstate);
|
|
1619
1494
|
for (size_t i = 0, L = sass_map_get_length(v); i < L; ++i) {
|
|
1620
1495
|
*m << std::make_pair(
|
|
1621
|
-
cval_to_astnode(sass_map_get_key(v, i),
|
|
1622
|
-
cval_to_astnode(sass_map_get_value(v, i),
|
|
1496
|
+
cval_to_astnode(sass_map_get_key(v, i), traces, pstate),
|
|
1497
|
+
cval_to_astnode(sass_map_get_value(v, i), traces, pstate));
|
|
1623
1498
|
}
|
|
1624
1499
|
e = m;
|
|
1625
1500
|
} break;
|
|
@@ -1627,11 +1502,12 @@ namespace Sass {
|
|
|
1627
1502
|
e = SASS_MEMORY_NEW(Null, pstate);
|
|
1628
1503
|
} break;
|
|
1629
1504
|
case SASS_ERROR: {
|
|
1630
|
-
error("Error in C function: " + std::string(sass_error_get_message(v)), pstate,
|
|
1505
|
+
error("Error in C function: " + std::string(sass_error_get_message(v)), pstate, traces);
|
|
1631
1506
|
} break;
|
|
1632
1507
|
case SASS_WARNING: {
|
|
1633
|
-
error("Warning in C function: " + std::string(sass_warning_get_message(v)), pstate,
|
|
1508
|
+
error("Warning in C function: " + std::string(sass_warning_get_message(v)), pstate, traces);
|
|
1634
1509
|
} break;
|
|
1510
|
+
default: break;
|
|
1635
1511
|
}
|
|
1636
1512
|
return e;
|
|
1637
1513
|
}
|
|
@@ -1644,7 +1520,7 @@ namespace Sass {
|
|
|
1644
1520
|
sl->media_block(s->media_block());
|
|
1645
1521
|
sl->is_optional(s->is_optional());
|
|
1646
1522
|
for (size_t i = 0, iL = s->length(); i < iL; ++i) {
|
|
1647
|
-
rv.push_back(operator()(
|
|
1523
|
+
rv.push_back(operator()((*s)[i]));
|
|
1648
1524
|
}
|
|
1649
1525
|
|
|
1650
1526
|
// we should actually permutate parent first
|
|
@@ -1672,37 +1548,72 @@ namespace Sass {
|
|
|
1672
1548
|
Selector_List_Ptr Eval::operator()(Complex_Selector_Ptr s)
|
|
1673
1549
|
{
|
|
1674
1550
|
bool implicit_parent = !exp.old_at_root_without_rule;
|
|
1675
|
-
|
|
1551
|
+
if (is_in_selector_schema) exp.selector_stack.push_back(0);
|
|
1552
|
+
Selector_List_Obj resolved = s->resolve_parent_refs(exp.selector_stack, traces, implicit_parent);
|
|
1553
|
+
if (is_in_selector_schema) exp.selector_stack.pop_back();
|
|
1554
|
+
for (size_t i = 0; i < resolved->length(); i++) {
|
|
1555
|
+
Complex_Selector_Ptr is = resolved->at(i)->first();
|
|
1556
|
+
while (is) {
|
|
1557
|
+
if (is->head()) {
|
|
1558
|
+
is->head(operator()(is->head()));
|
|
1559
|
+
}
|
|
1560
|
+
is = is->tail();
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
return resolved.detach();
|
|
1676
1564
|
}
|
|
1677
1565
|
|
|
1678
|
-
|
|
1679
|
-
Attribute_Selector_Ptr Eval::operator()(Attribute_Selector_Ptr s)
|
|
1566
|
+
Compound_Selector_Ptr Eval::operator()(Compound_Selector_Ptr s)
|
|
1680
1567
|
{
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1568
|
+
for (size_t i = 0; i < s->length(); i++) {
|
|
1569
|
+
Simple_Selector_Ptr ss = s->at(i);
|
|
1570
|
+
// skip parents here (called via resolve_parent_refs)
|
|
1571
|
+
if (ss == NULL || Cast<Parent_Selector>(ss)) continue;
|
|
1572
|
+
s->at(i) = Cast<Simple_Selector>(ss->perform(this));
|
|
1573
|
+
}
|
|
1574
|
+
return s;
|
|
1686
1575
|
}
|
|
1687
1576
|
|
|
1688
1577
|
Selector_List_Ptr Eval::operator()(Selector_Schema_Ptr s)
|
|
1689
1578
|
{
|
|
1579
|
+
LOCAL_FLAG(is_in_selector_schema, true);
|
|
1690
1580
|
// the parser will look for a brace to end the selector
|
|
1581
|
+
ctx.c_options.in_selector = true; // do not compress colors
|
|
1691
1582
|
Expression_Obj sel = s->contents()->perform(this);
|
|
1692
1583
|
std::string result_str(sel->to_string(ctx.c_options));
|
|
1693
|
-
|
|
1694
|
-
|
|
1584
|
+
ctx.c_options.in_selector = false; // flag temporary only
|
|
1585
|
+
result_str = unquote(Util::rtrim(result_str));
|
|
1586
|
+
char* temp_cstr = sass_copy_c_string(result_str.c_str());
|
|
1587
|
+
ctx.strings.push_back(temp_cstr); // attach to context
|
|
1588
|
+
Parser p = Parser::from_c_str(temp_cstr, ctx, traces, s->pstate());
|
|
1695
1589
|
p.last_media_block = s->media_block();
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1590
|
+
// a selector schema may or may not connect to parent?
|
|
1591
|
+
bool chroot = s->connect_parent() == false;
|
|
1592
|
+
Selector_List_Obj sl = p.parse_selector_list(chroot);
|
|
1593
|
+
auto vec_str_rend = ctx.strings.rend();
|
|
1594
|
+
auto vec_str_rbegin = ctx.strings.rbegin();
|
|
1595
|
+
// remove the first item searching from the back
|
|
1596
|
+
// we cannot assume our item is still the last one
|
|
1597
|
+
// order is not important, so we can optimize this
|
|
1598
|
+
auto it = std::find(vec_str_rbegin, vec_str_rend, temp_cstr);
|
|
1599
|
+
// undefined behavior if not found!
|
|
1600
|
+
if (it != vec_str_rend) {
|
|
1601
|
+
// overwrite with last item
|
|
1602
|
+
*it = ctx.strings.back();
|
|
1603
|
+
// remove last one from vector
|
|
1604
|
+
ctx.strings.pop_back();
|
|
1605
|
+
// free temporary copy
|
|
1606
|
+
free(temp_cstr);
|
|
1607
|
+
}
|
|
1608
|
+
flag_is_in_selector_schema.reset();
|
|
1609
|
+
return operator()(sl);
|
|
1699
1610
|
}
|
|
1700
1611
|
|
|
1701
1612
|
Expression_Ptr Eval::operator()(Parent_Selector_Ptr p)
|
|
1702
1613
|
{
|
|
1703
1614
|
if (Selector_List_Obj pr = selector()) {
|
|
1704
1615
|
exp.selector_stack.pop_back();
|
|
1705
|
-
Selector_List_Obj rv = operator()(
|
|
1616
|
+
Selector_List_Obj rv = operator()(pr);
|
|
1706
1617
|
exp.selector_stack.push_back(rv);
|
|
1707
1618
|
return rv.detach();
|
|
1708
1619
|
} else {
|
|
@@ -1710,4 +1621,43 @@ namespace Sass {
|
|
|
1710
1621
|
}
|
|
1711
1622
|
}
|
|
1712
1623
|
|
|
1624
|
+
Simple_Selector_Ptr Eval::operator()(Simple_Selector_Ptr s)
|
|
1625
|
+
{
|
|
1626
|
+
return s;
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
// hotfix to avoid invalid nested `:not` selectors
|
|
1630
|
+
// probably the wrong place, but this should ultimately
|
|
1631
|
+
// be fixed by implement superselector correctly for `:not`
|
|
1632
|
+
// first use of "find" (ATM only implemented for selectors)
|
|
1633
|
+
bool hasNotSelector(AST_Node_Obj obj) {
|
|
1634
|
+
if (Wrapped_Selector_Ptr w = Cast<Wrapped_Selector>(obj)) {
|
|
1635
|
+
return w->name() == ":not";
|
|
1636
|
+
}
|
|
1637
|
+
return false;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
Wrapped_Selector_Ptr Eval::operator()(Wrapped_Selector_Ptr s)
|
|
1641
|
+
{
|
|
1642
|
+
|
|
1643
|
+
if (s->name() == ":not") {
|
|
1644
|
+
if (exp.selector_stack.back()) {
|
|
1645
|
+
if (s->selector()->find(hasNotSelector)) {
|
|
1646
|
+
s->selector()->clear();
|
|
1647
|
+
s->name(" ");
|
|
1648
|
+
} else if (s->selector()->length() == 1) {
|
|
1649
|
+
Complex_Selector_Ptr cs = s->selector()->at(0);
|
|
1650
|
+
if (cs->tail()) {
|
|
1651
|
+
s->selector()->clear();
|
|
1652
|
+
s->name(" ");
|
|
1653
|
+
}
|
|
1654
|
+
} else if (s->selector()->length() > 1) {
|
|
1655
|
+
s->selector()->clear();
|
|
1656
|
+
s->name(" ");
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
return s;
|
|
1661
|
+
};
|
|
1662
|
+
|
|
1713
1663
|
}
|