sassc 0.0.9 → 0.0.10
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 +4 -4
- data/Rakefile +1 -1
- data/ext/libsass/.gitignore +13 -6
- data/ext/libsass/Makefile +42 -26
- data/ext/libsass/Makefile.am +43 -30
- data/ext/libsass/Readme.md +4 -2
- data/ext/libsass/appveyor.yml +10 -14
- data/ext/libsass/ast.cpp +54 -44
- data/ext/libsass/ast.hpp +404 -236
- data/ext/libsass/ast_def_macros.hpp +5 -0
- data/ext/libsass/ast_factory.hpp +6 -3
- data/ext/libsass/ast_fwd_decl.hpp +12 -0
- data/ext/libsass/b64/encode.h +2 -2
- data/ext/libsass/backtrace.hpp +13 -17
- data/ext/libsass/base64vlq.hpp +4 -1
- data/ext/libsass/bind.cpp +12 -15
- data/ext/libsass/bind.hpp +6 -6
- data/ext/libsass/color_names.hpp +4 -1
- data/ext/libsass/configure.ac +7 -21
- data/ext/libsass/constants.cpp +6 -4
- data/ext/libsass/constants.hpp +10 -4
- data/ext/libsass/context.cpp +89 -58
- data/ext/libsass/context.hpp +28 -35
- data/ext/libsass/contextualize.cpp +20 -10
- data/ext/libsass/contextualize.hpp +8 -23
- data/ext/libsass/contrib/libsass.spec +66 -0
- data/ext/libsass/cssize.cpp +547 -0
- data/ext/libsass/cssize.hpp +82 -0
- data/ext/libsass/debug.hpp +3 -3
- data/ext/libsass/debugger.hpp +358 -0
- data/ext/libsass/emitter.cpp +255 -0
- data/ext/libsass/emitter.hpp +83 -0
- data/ext/libsass/environment.hpp +7 -3
- data/ext/libsass/error_handling.cpp +11 -14
- data/ext/libsass/error_handling.hpp +9 -7
- data/ext/libsass/eval.cpp +253 -161
- data/ext/libsass/eval.hpp +13 -13
- data/ext/libsass/expand.cpp +135 -64
- data/ext/libsass/expand.hpp +11 -13
- data/ext/libsass/extend.cpp +66 -20
- data/ext/libsass/extend.hpp +6 -11
- data/ext/libsass/file.cpp +31 -26
- data/ext/libsass/file.hpp +6 -1
- data/ext/libsass/functions.cpp +270 -287
- data/ext/libsass/functions.hpp +8 -11
- data/ext/libsass/inspect.cpp +385 -255
- data/ext/libsass/inspect.hpp +15 -26
- data/ext/libsass/kwd_arg_macros.hpp +5 -0
- data/ext/libsass/mapping.hpp +4 -3
- data/ext/libsass/memory_manager.hpp +5 -2
- data/ext/libsass/node.cpp +50 -50
- data/ext/libsass/node.hpp +26 -27
- data/ext/libsass/operation.hpp +15 -4
- data/ext/libsass/output.cpp +401 -0
- data/ext/libsass/output.hpp +56 -0
- data/ext/libsass/parser.cpp +573 -399
- data/ext/libsass/parser.hpp +122 -88
- data/ext/libsass/paths.hpp +7 -2
- data/ext/libsass/plugins.cpp +155 -0
- data/ext/libsass/plugins.hpp +56 -0
- data/ext/libsass/position.cpp +128 -0
- data/ext/libsass/position.hpp +108 -11
- data/ext/libsass/prelexer.cpp +184 -110
- data/ext/libsass/prelexer.hpp +131 -24
- data/ext/libsass/remove_placeholders.cpp +1 -1
- data/ext/libsass/remove_placeholders.hpp +6 -6
- data/ext/libsass/sass.cpp +3 -3
- data/ext/libsass/sass.h +12 -4
- data/ext/libsass/sass2scss.cpp +3 -2
- data/ext/libsass/sass2scss.h +5 -0
- data/ext/libsass/sass_context.cpp +136 -37
- data/ext/libsass/sass_context.h +19 -10
- data/ext/libsass/sass_functions.cpp +29 -2
- data/ext/libsass/sass_functions.h +8 -2
- data/ext/libsass/sass_interface.cpp +32 -23
- data/ext/libsass/sass_interface.h +9 -4
- data/ext/libsass/sass_util.cpp +19 -23
- data/ext/libsass/sass_util.hpp +28 -27
- data/ext/libsass/sass_values.cpp +6 -4
- data/ext/libsass/sass_values.h +3 -3
- data/ext/libsass/script/ci-build-libsass +13 -1
- data/ext/libsass/script/ci-report-coverage +2 -1
- data/ext/libsass/source_map.cpp +79 -28
- data/ext/libsass/source_map.hpp +35 -16
- data/ext/libsass/subset_map.hpp +6 -4
- data/ext/libsass/to_c.hpp +4 -4
- data/ext/libsass/to_string.cpp +13 -8
- data/ext/libsass/to_string.hpp +6 -4
- data/ext/libsass/units.cpp +2 -1
- data/ext/libsass/units.hpp +6 -1
- data/ext/libsass/utf8_string.cpp +0 -5
- data/ext/libsass/utf8_string.hpp +3 -2
- data/ext/libsass/util.cpp +461 -49
- data/ext/libsass/util.hpp +34 -13
- data/ext/libsass/version.sh +10 -0
- data/ext/libsass/win/libsass.filters +20 -11
- data/ext/libsass/win/libsass.vcxproj +11 -8
- data/lib/sassc/importer.rb +1 -8
- data/lib/sassc/native.rb +7 -0
- data/lib/sassc/native/native_context_api.rb +5 -5
- data/lib/sassc/version.rb +1 -1
- data/test/native_test.rb +1 -1
- metadata +14 -10
- data/ext/libsass/copy_c_str.cpp +0 -13
- data/ext/libsass/copy_c_str.hpp +0 -5
- data/ext/libsass/output_compressed.cpp +0 -401
- data/ext/libsass/output_compressed.hpp +0 -95
- data/ext/libsass/output_nested.cpp +0 -364
- data/ext/libsass/output_nested.hpp +0 -108
- data/ext/libsass/test-driver +0 -127
- data/ext/libsass/token.hpp +0 -32
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
#include "util.hpp"
|
|
2
|
+
#include "context.hpp"
|
|
3
|
+
#include "output.hpp"
|
|
4
|
+
#include "emitter.hpp"
|
|
5
|
+
#include "utf8_string.hpp"
|
|
6
|
+
|
|
7
|
+
namespace Sass {
|
|
8
|
+
using namespace std;
|
|
9
|
+
|
|
10
|
+
Emitter::Emitter(Context* ctx)
|
|
11
|
+
: wbuf(),
|
|
12
|
+
ctx(ctx),
|
|
13
|
+
indentation(0),
|
|
14
|
+
scheduled_space(0),
|
|
15
|
+
scheduled_linefeed(0),
|
|
16
|
+
scheduled_delimiter(false),
|
|
17
|
+
in_comment(false),
|
|
18
|
+
in_at_rule(false),
|
|
19
|
+
in_media_block(false),
|
|
20
|
+
in_declaration(false),
|
|
21
|
+
in_declaration_list(false)
|
|
22
|
+
{ }
|
|
23
|
+
|
|
24
|
+
// return buffer as string
|
|
25
|
+
string Emitter::get_buffer(void)
|
|
26
|
+
{
|
|
27
|
+
return wbuf.buffer;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
Output_Style Emitter::output_style(void)
|
|
31
|
+
{
|
|
32
|
+
return ctx ? ctx->output_style : COMPRESSED;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// PROXY METHODS FOR SOURCE MAPS
|
|
36
|
+
|
|
37
|
+
void Emitter::add_source_index(size_t idx)
|
|
38
|
+
{ wbuf.smap.source_index.push_back(idx); }
|
|
39
|
+
|
|
40
|
+
string Emitter::generate_source_map(Context &ctx)
|
|
41
|
+
{ return wbuf.smap.generate_source_map(ctx); }
|
|
42
|
+
|
|
43
|
+
void Emitter::set_filename(const string& str)
|
|
44
|
+
{ wbuf.smap.file = str; }
|
|
45
|
+
|
|
46
|
+
void Emitter::add_open_mapping(AST_Node* node)
|
|
47
|
+
{ wbuf.smap.add_open_mapping(node); }
|
|
48
|
+
void Emitter::add_close_mapping(AST_Node* node)
|
|
49
|
+
{ wbuf.smap.add_close_mapping(node); }
|
|
50
|
+
ParserState Emitter::remap(const ParserState& pstate)
|
|
51
|
+
{ return wbuf.smap.remap(pstate); }
|
|
52
|
+
|
|
53
|
+
// MAIN BUFFER MANIPULATION
|
|
54
|
+
|
|
55
|
+
// add outstanding delimiter
|
|
56
|
+
void Emitter::finalize(void)
|
|
57
|
+
{
|
|
58
|
+
scheduled_space = 0;
|
|
59
|
+
if (scheduled_linefeed)
|
|
60
|
+
scheduled_linefeed = 1;
|
|
61
|
+
flush_schedules();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// flush scheduled space/linefeed
|
|
65
|
+
void Emitter::flush_schedules(void)
|
|
66
|
+
{
|
|
67
|
+
// check the schedule
|
|
68
|
+
if (scheduled_linefeed) {
|
|
69
|
+
string linefeeds = "";
|
|
70
|
+
|
|
71
|
+
for (size_t i = 0; i < scheduled_linefeed; i++)
|
|
72
|
+
linefeeds += ctx ? ctx->linefeed : "\n";
|
|
73
|
+
scheduled_space = 0;
|
|
74
|
+
scheduled_linefeed = 0;
|
|
75
|
+
append_string(linefeeds);
|
|
76
|
+
|
|
77
|
+
} else if (scheduled_space) {
|
|
78
|
+
string spaces(scheduled_space, ' ');
|
|
79
|
+
scheduled_space = 0;
|
|
80
|
+
append_string(spaces);
|
|
81
|
+
}
|
|
82
|
+
if (scheduled_delimiter) {
|
|
83
|
+
scheduled_delimiter = false;
|
|
84
|
+
append_string(";");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// prepend some text or token to the buffer
|
|
89
|
+
void Emitter::prepend_output(const OutputBuffer& output)
|
|
90
|
+
{
|
|
91
|
+
wbuf.smap.prepend(output);
|
|
92
|
+
wbuf.buffer = output.buffer + wbuf.buffer;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// prepend some text or token to the buffer
|
|
96
|
+
void Emitter::prepend_string(const string& text)
|
|
97
|
+
{
|
|
98
|
+
wbuf.smap.prepend(Offset(text));
|
|
99
|
+
wbuf.buffer = text + wbuf.buffer;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// append some text or token to the buffer
|
|
103
|
+
void Emitter::append_string(const string& text)
|
|
104
|
+
{
|
|
105
|
+
// write space/lf
|
|
106
|
+
flush_schedules();
|
|
107
|
+
|
|
108
|
+
if (in_comment && output_style() == COMPACT) {
|
|
109
|
+
// unescape comment nodes
|
|
110
|
+
string out = comment_to_string(text);
|
|
111
|
+
// add to buffer
|
|
112
|
+
wbuf.buffer += out;
|
|
113
|
+
// account for data in source-maps
|
|
114
|
+
wbuf.smap.append(Offset(out));
|
|
115
|
+
} else {
|
|
116
|
+
// add to buffer
|
|
117
|
+
wbuf.buffer += text;
|
|
118
|
+
// account for data in source-maps
|
|
119
|
+
wbuf.smap.append(Offset(text));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// append some white-space only text
|
|
124
|
+
void Emitter::append_wspace(const string& text)
|
|
125
|
+
{
|
|
126
|
+
if (text.empty()) return;
|
|
127
|
+
if (peek_linefeed(text.c_str())) {
|
|
128
|
+
scheduled_space = 0;
|
|
129
|
+
append_mandatory_linefeed();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// append some text or token to the buffer
|
|
134
|
+
// this adds source-mappings for node start and end
|
|
135
|
+
void Emitter::append_token(const string& text, AST_Node* node)
|
|
136
|
+
{
|
|
137
|
+
flush_schedules();
|
|
138
|
+
add_open_mapping(node);
|
|
139
|
+
append_string(text);
|
|
140
|
+
add_close_mapping(node);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// HELPER METHODS
|
|
144
|
+
|
|
145
|
+
void Emitter::append_indentation()
|
|
146
|
+
{
|
|
147
|
+
if (output_style() == COMPRESSED) return;
|
|
148
|
+
if (output_style() == COMPACT) return;
|
|
149
|
+
if (scheduled_linefeed && indentation)
|
|
150
|
+
scheduled_linefeed = 1;
|
|
151
|
+
string indent = "";
|
|
152
|
+
for (size_t i = 0; i < indentation; i++)
|
|
153
|
+
indent += ctx ? ctx->indent : " ";
|
|
154
|
+
append_string(indent);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
void Emitter::append_delimiter()
|
|
158
|
+
{
|
|
159
|
+
scheduled_delimiter = true;
|
|
160
|
+
if (output_style() == COMPACT) {
|
|
161
|
+
if (indentation == 0) {
|
|
162
|
+
append_mandatory_linefeed();
|
|
163
|
+
} else {
|
|
164
|
+
append_mandatory_space();
|
|
165
|
+
}
|
|
166
|
+
} else if (output_style() != COMPRESSED) {
|
|
167
|
+
append_optional_linefeed();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
void Emitter::append_comma_separator()
|
|
172
|
+
{
|
|
173
|
+
scheduled_space = 0;
|
|
174
|
+
append_string(",");
|
|
175
|
+
append_optional_space();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
void Emitter::append_colon_separator()
|
|
179
|
+
{
|
|
180
|
+
scheduled_space = 0;
|
|
181
|
+
append_string(":");
|
|
182
|
+
append_optional_space();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
void Emitter::append_mandatory_space()
|
|
186
|
+
{
|
|
187
|
+
scheduled_space = 1;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
void Emitter::append_optional_space()
|
|
191
|
+
{
|
|
192
|
+
if (output_style() != COMPRESSED && buffer().size()) {
|
|
193
|
+
char lst = buffer().at(buffer().length() - 1);
|
|
194
|
+
if (!isspace(lst)) append_mandatory_space();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
void Emitter::append_special_linefeed()
|
|
199
|
+
{
|
|
200
|
+
if (output_style() == COMPACT) {
|
|
201
|
+
append_mandatory_linefeed();
|
|
202
|
+
for (size_t p = 0; p < indentation; p++)
|
|
203
|
+
append_string(ctx ? ctx->indent : " ");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
void Emitter::append_optional_linefeed()
|
|
208
|
+
{
|
|
209
|
+
if (output_style() == COMPACT) {
|
|
210
|
+
append_mandatory_space();
|
|
211
|
+
} else {
|
|
212
|
+
append_mandatory_linefeed();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
void Emitter::append_mandatory_linefeed()
|
|
217
|
+
{
|
|
218
|
+
if (output_style() != COMPRESSED) {
|
|
219
|
+
scheduled_linefeed = 1;
|
|
220
|
+
scheduled_space = 0;
|
|
221
|
+
// flush_schedules();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
void Emitter::append_scope_opener(AST_Node* node)
|
|
226
|
+
{
|
|
227
|
+
append_optional_space();
|
|
228
|
+
flush_schedules();
|
|
229
|
+
if (node) add_open_mapping(node);
|
|
230
|
+
append_string("{");
|
|
231
|
+
append_optional_linefeed();
|
|
232
|
+
// append_optional_space();
|
|
233
|
+
++ indentation;
|
|
234
|
+
}
|
|
235
|
+
void Emitter::append_scope_closer(AST_Node* node)
|
|
236
|
+
{
|
|
237
|
+
-- indentation;
|
|
238
|
+
scheduled_linefeed = 0;
|
|
239
|
+
if (output_style() == COMPRESSED)
|
|
240
|
+
scheduled_delimiter = false;
|
|
241
|
+
if (output_style() == EXPANDED) {
|
|
242
|
+
append_optional_linefeed();
|
|
243
|
+
append_indentation();
|
|
244
|
+
} else {
|
|
245
|
+
append_optional_space();
|
|
246
|
+
}
|
|
247
|
+
append_string("}");
|
|
248
|
+
if (node) add_close_mapping(node);
|
|
249
|
+
append_optional_linefeed();
|
|
250
|
+
if (indentation != 0) return;
|
|
251
|
+
if (output_style() != COMPRESSED)
|
|
252
|
+
scheduled_linefeed = 2;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#ifndef SASS_EMITTER_H
|
|
2
|
+
#define SASS_EMITTER_H
|
|
3
|
+
|
|
4
|
+
#include <string>
|
|
5
|
+
#include "source_map.hpp"
|
|
6
|
+
#include "ast_fwd_decl.hpp"
|
|
7
|
+
|
|
8
|
+
namespace Sass {
|
|
9
|
+
class Context;
|
|
10
|
+
using namespace std;
|
|
11
|
+
|
|
12
|
+
class Emitter {
|
|
13
|
+
|
|
14
|
+
public:
|
|
15
|
+
Emitter(Context* ctx);
|
|
16
|
+
virtual ~Emitter() { };
|
|
17
|
+
|
|
18
|
+
protected:
|
|
19
|
+
OutputBuffer wbuf;
|
|
20
|
+
public:
|
|
21
|
+
const string buffer(void) { return wbuf.buffer; }
|
|
22
|
+
const SourceMap smap(void) { return wbuf.smap; }
|
|
23
|
+
const OutputBuffer output(void) { return wbuf; }
|
|
24
|
+
// proxy methods for source maps
|
|
25
|
+
void add_source_index(size_t idx);
|
|
26
|
+
void set_filename(const string& str);
|
|
27
|
+
void add_open_mapping(AST_Node* node);
|
|
28
|
+
void add_close_mapping(AST_Node* node);
|
|
29
|
+
string generate_source_map(Context &ctx);
|
|
30
|
+
ParserState remap(const ParserState& pstate);
|
|
31
|
+
|
|
32
|
+
public:
|
|
33
|
+
Context* ctx;
|
|
34
|
+
size_t indentation;
|
|
35
|
+
size_t scheduled_space;
|
|
36
|
+
size_t scheduled_linefeed;
|
|
37
|
+
bool scheduled_delimiter;
|
|
38
|
+
|
|
39
|
+
public:
|
|
40
|
+
bool in_comment;
|
|
41
|
+
bool in_at_rule;
|
|
42
|
+
bool in_media_block;
|
|
43
|
+
bool in_declaration;
|
|
44
|
+
bool in_declaration_list;
|
|
45
|
+
|
|
46
|
+
public:
|
|
47
|
+
// return buffer as string
|
|
48
|
+
string get_buffer(void);
|
|
49
|
+
// flush scheduled space/linefeed
|
|
50
|
+
Output_Style output_style(void);
|
|
51
|
+
// add outstanding linefeed
|
|
52
|
+
void finalize(void);
|
|
53
|
+
// flush scheduled space/linefeed
|
|
54
|
+
void flush_schedules(void);
|
|
55
|
+
// prepend some text or token to the buffer
|
|
56
|
+
void prepend_string(const string& text);
|
|
57
|
+
void prepend_output(const OutputBuffer& out);
|
|
58
|
+
// append some text or token to the buffer
|
|
59
|
+
void append_string(const string& text);
|
|
60
|
+
// append some white-space only text
|
|
61
|
+
void append_wspace(const string& text);
|
|
62
|
+
// append some text or token to the buffer
|
|
63
|
+
// this adds source-mappings for node start and end
|
|
64
|
+
void append_token(const string& text, AST_Node* node);
|
|
65
|
+
|
|
66
|
+
public: // syntax sugar
|
|
67
|
+
void append_indentation();
|
|
68
|
+
void append_optional_space(void);
|
|
69
|
+
void append_mandatory_space(void);
|
|
70
|
+
void append_special_linefeed(void);
|
|
71
|
+
void append_optional_linefeed(void);
|
|
72
|
+
void append_mandatory_linefeed(void);
|
|
73
|
+
void append_scope_opener(AST_Node* node = 0);
|
|
74
|
+
void append_scope_closer(AST_Node* node = 0);
|
|
75
|
+
void append_comma_separator(void);
|
|
76
|
+
void append_colon_separator(void);
|
|
77
|
+
void append_delimiter(void);
|
|
78
|
+
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#endif
|
data/ext/libsass/environment.hpp
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
#ifndef SASS_ENVIRONMENT_H
|
|
2
|
+
#define SASS_ENVIRONMENT_H
|
|
2
3
|
|
|
3
|
-
#include <string>
|
|
4
4
|
#include <map>
|
|
5
|
-
#include
|
|
5
|
+
#include <string>
|
|
6
6
|
#include <iostream>
|
|
7
7
|
|
|
8
|
+
#include "ast_def_macros.hpp"
|
|
9
|
+
|
|
8
10
|
namespace Sass {
|
|
9
11
|
using std::string;
|
|
10
12
|
using std::map;
|
|
@@ -73,3 +75,5 @@ namespace Sass {
|
|
|
73
75
|
}
|
|
74
76
|
};
|
|
75
77
|
}
|
|
78
|
+
|
|
79
|
+
#endif
|
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
#ifndef SASS_ERROR_HANDLING
|
|
2
|
-
#include "error_handling.hpp"
|
|
3
|
-
#endif
|
|
4
|
-
|
|
5
|
-
#include "backtrace.hpp"
|
|
6
1
|
#include "prelexer.hpp"
|
|
2
|
+
#include "backtrace.hpp"
|
|
3
|
+
#include "error_handling.hpp"
|
|
7
4
|
|
|
8
5
|
namespace Sass {
|
|
9
6
|
|
|
10
|
-
Sass_Error::Sass_Error(Type type,
|
|
11
|
-
: type(type),
|
|
7
|
+
Sass_Error::Sass_Error(Type type, ParserState pstate, string message)
|
|
8
|
+
: type(type), pstate(pstate), message(message)
|
|
12
9
|
{ }
|
|
13
10
|
|
|
14
|
-
void error(string msg,
|
|
15
|
-
{ throw Sass_Error(Sass_Error::syntax,
|
|
11
|
+
void error(string msg, ParserState pstate)
|
|
12
|
+
{ throw Sass_Error(Sass_Error::syntax, pstate, msg); }
|
|
16
13
|
|
|
17
|
-
void error(string msg,
|
|
14
|
+
void error(string msg, ParserState pstate, Backtrace* bt)
|
|
18
15
|
{
|
|
19
|
-
if (!path.empty() && Prelexer::
|
|
20
|
-
path = path.substr(1, path.size() - 1);
|
|
16
|
+
if (!pstate.path.empty() && Prelexer::quoted_string(pstate.path.c_str()))
|
|
17
|
+
pstate.path = pstate.path.substr(1, pstate.path.size() - 1);
|
|
21
18
|
|
|
22
|
-
Backtrace top(bt,
|
|
19
|
+
Backtrace top(bt, pstate, "");
|
|
23
20
|
msg += top.to_string();
|
|
24
21
|
|
|
25
|
-
throw Sass_Error(Sass_Error::syntax,
|
|
22
|
+
throw Sass_Error(Sass_Error::syntax, pstate, msg);
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
#ifndef SASS_ERROR_HANDLING_H
|
|
2
|
+
#define SASS_ERROR_HANDLING_H
|
|
3
|
+
|
|
2
4
|
#include <string>
|
|
3
5
|
|
|
4
|
-
#ifndef SASS_POSITION
|
|
5
6
|
#include "position.hpp"
|
|
6
|
-
#endif
|
|
7
7
|
|
|
8
8
|
namespace Sass {
|
|
9
9
|
using namespace std;
|
|
@@ -15,14 +15,16 @@ namespace Sass {
|
|
|
15
15
|
|
|
16
16
|
Type type;
|
|
17
17
|
string path;
|
|
18
|
-
|
|
18
|
+
ParserState pstate;
|
|
19
19
|
string message;
|
|
20
20
|
|
|
21
|
-
Sass_Error(Type type,
|
|
21
|
+
Sass_Error(Type type, ParserState pstate, string message);
|
|
22
22
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
void error(string msg,
|
|
26
|
-
void error(string msg,
|
|
25
|
+
void error(string msg, ParserState pstate);
|
|
26
|
+
void error(string msg, ParserState pstate, Backtrace* bt);
|
|
27
27
|
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
#endif
|
data/ext/libsass/eval.cpp
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#include "context.hpp"
|
|
10
10
|
#include "backtrace.hpp"
|
|
11
11
|
#include "prelexer.hpp"
|
|
12
|
+
#include "parser.hpp"
|
|
12
13
|
|
|
13
14
|
#include <cstdlib>
|
|
14
15
|
#include <cmath>
|
|
@@ -81,16 +82,16 @@ namespace Sass {
|
|
|
81
82
|
string variable(f->variable());
|
|
82
83
|
Expression* low = f->lower_bound()->perform(this);
|
|
83
84
|
if (low->concrete_type() != Expression::NUMBER) {
|
|
84
|
-
error("lower bound of `@for` directive must be numeric", low->
|
|
85
|
+
error("lower bound of `@for` directive must be numeric", low->pstate());
|
|
85
86
|
}
|
|
86
87
|
Expression* high = f->upper_bound()->perform(this);
|
|
87
88
|
if (high->concrete_type() != Expression::NUMBER) {
|
|
88
|
-
error("upper bound of `@for` directive must be numeric", high->
|
|
89
|
+
error("upper bound of `@for` directive must be numeric", high->pstate());
|
|
89
90
|
}
|
|
90
91
|
double start = static_cast<Number*>(low)->value();
|
|
91
92
|
double end = static_cast<Number*>(high)->value();
|
|
92
93
|
Env new_env;
|
|
93
|
-
new_env[variable] = new (ctx.mem) Number(low->
|
|
94
|
+
new_env[variable] = new (ctx.mem) Number(low->pstate(), start);
|
|
94
95
|
new_env.link(env);
|
|
95
96
|
env = &new_env;
|
|
96
97
|
Block* body = f->block();
|
|
@@ -99,7 +100,7 @@ namespace Sass {
|
|
|
99
100
|
if (f->is_inclusive()) ++end;
|
|
100
101
|
for (double i = start;
|
|
101
102
|
i < end;
|
|
102
|
-
(*env)[variable] = new (ctx.mem) Number(low->
|
|
103
|
+
(*env)[variable] = new (ctx.mem) Number(low->pstate(), ++i)) {
|
|
103
104
|
val = body->perform(this);
|
|
104
105
|
if (val) break;
|
|
105
106
|
}
|
|
@@ -107,7 +108,7 @@ namespace Sass {
|
|
|
107
108
|
if (f->is_inclusive()) --end;
|
|
108
109
|
for (double i = start;
|
|
109
110
|
i > end;
|
|
110
|
-
(*env)[variable] = new (ctx.mem) Number(low->
|
|
111
|
+
(*env)[variable] = new (ctx.mem) Number(low->pstate(), --i)) {
|
|
111
112
|
val = body->perform(this);
|
|
112
113
|
if (val) break;
|
|
113
114
|
}
|
|
@@ -126,7 +127,7 @@ namespace Sass {
|
|
|
126
127
|
map = static_cast<Map*>(expr);
|
|
127
128
|
}
|
|
128
129
|
else if (expr->concrete_type() != Expression::LIST) {
|
|
129
|
-
list = new (ctx.mem) List(expr->
|
|
130
|
+
list = new (ctx.mem) List(expr->pstate(), 1, List::COMMA);
|
|
130
131
|
*list << expr;
|
|
131
132
|
}
|
|
132
133
|
else {
|
|
@@ -144,7 +145,7 @@ namespace Sass {
|
|
|
144
145
|
Expression* value = map->at(key);
|
|
145
146
|
|
|
146
147
|
if (variables.size() == 1) {
|
|
147
|
-
List* variable = new (ctx.mem) List(map->
|
|
148
|
+
List* variable = new (ctx.mem) List(map->pstate(), 2, List::SPACE);
|
|
148
149
|
*variable << key;
|
|
149
150
|
*variable << value;
|
|
150
151
|
(*env)[variables[0]] = variable;
|
|
@@ -161,7 +162,7 @@ namespace Sass {
|
|
|
161
162
|
for (size_t i = 0, L = list->length(); i < L; ++i) {
|
|
162
163
|
List* variable = 0;
|
|
163
164
|
if ((*list)[i]->concrete_type() != Expression::LIST || variables.size() == 1) {
|
|
164
|
-
variable = new (ctx.mem) List((*list)[i]->
|
|
165
|
+
variable = new (ctx.mem) List((*list)[i]->pstate(), 1, List::COMMA);
|
|
165
166
|
*variable << (*list)[i];
|
|
166
167
|
}
|
|
167
168
|
else {
|
|
@@ -172,7 +173,7 @@ namespace Sass {
|
|
|
172
173
|
(*env)[variables[j]] = (*variable)[j];
|
|
173
174
|
}
|
|
174
175
|
else {
|
|
175
|
-
(*env)[variables[j]] = new (ctx.mem) Null(expr->
|
|
176
|
+
(*env)[variables[j]] = new (ctx.mem) Null(expr->pstate());
|
|
176
177
|
}
|
|
177
178
|
val = body->perform(this);
|
|
178
179
|
if (val) break;
|
|
@@ -203,7 +204,7 @@ namespace Sass {
|
|
|
203
204
|
Expression* Eval::operator()(Warning* w)
|
|
204
205
|
{
|
|
205
206
|
Expression* message = w->message()->perform(this);
|
|
206
|
-
To_String to_string;
|
|
207
|
+
To_String to_string(&ctx);
|
|
207
208
|
|
|
208
209
|
// try to use generic function
|
|
209
210
|
if (env->has("@warn[f]")) {
|
|
@@ -224,7 +225,7 @@ namespace Sass {
|
|
|
224
225
|
}
|
|
225
226
|
|
|
226
227
|
string result(unquote(message->perform(&to_string)));
|
|
227
|
-
Backtrace top(backtrace, w->
|
|
228
|
+
Backtrace top(backtrace, w->pstate(), "");
|
|
228
229
|
cerr << "WARNING: " << result;
|
|
229
230
|
cerr << top.to_string(true);
|
|
230
231
|
cerr << endl << endl;
|
|
@@ -234,7 +235,7 @@ namespace Sass {
|
|
|
234
235
|
Expression* Eval::operator()(Error* e)
|
|
235
236
|
{
|
|
236
237
|
Expression* message = e->message()->perform(this);
|
|
237
|
-
To_String to_string;
|
|
238
|
+
To_String to_string(&ctx);
|
|
238
239
|
|
|
239
240
|
// try to use generic function
|
|
240
241
|
if (env->has("@error[f]")) {
|
|
@@ -255,7 +256,7 @@ namespace Sass {
|
|
|
255
256
|
}
|
|
256
257
|
|
|
257
258
|
string result(unquote(message->perform(&to_string)));
|
|
258
|
-
Backtrace top(backtrace, e->
|
|
259
|
+
Backtrace top(backtrace, e->pstate(), "");
|
|
259
260
|
cerr << "Error: " << result;
|
|
260
261
|
cerr << top.to_string(true);
|
|
261
262
|
cerr << endl << endl;
|
|
@@ -265,7 +266,7 @@ namespace Sass {
|
|
|
265
266
|
Expression* Eval::operator()(Debug* d)
|
|
266
267
|
{
|
|
267
268
|
Expression* message = d->value()->perform(this);
|
|
268
|
-
To_String to_string;
|
|
269
|
+
To_String to_string(&ctx);
|
|
269
270
|
|
|
270
271
|
// try to use generic function
|
|
271
272
|
if (env->has("@debug[f]")) {
|
|
@@ -287,8 +288,8 @@ namespace Sass {
|
|
|
287
288
|
|
|
288
289
|
string cwd(ctx.get_cwd());
|
|
289
290
|
string result(unquote(message->perform(&to_string)));
|
|
290
|
-
string rel_path(Sass::File::resolve_relative_path(d->
|
|
291
|
-
cerr << rel_path << ":" << d->
|
|
291
|
+
string rel_path(Sass::File::resolve_relative_path(d->pstate().path, cwd, cwd));
|
|
292
|
+
cerr << rel_path << ":" << d->pstate().line << ":" << " DEBUG: " << result;
|
|
292
293
|
cerr << endl;
|
|
293
294
|
return 0;
|
|
294
295
|
}
|
|
@@ -296,8 +297,7 @@ namespace Sass {
|
|
|
296
297
|
Expression* Eval::operator()(List* l)
|
|
297
298
|
{
|
|
298
299
|
if (l->is_expanded()) return l;
|
|
299
|
-
List* ll = new (ctx.mem) List(l->
|
|
300
|
-
l->position(),
|
|
300
|
+
List* ll = new (ctx.mem) List(l->pstate(),
|
|
301
301
|
l->length(),
|
|
302
302
|
l->separator(),
|
|
303
303
|
l->is_arglist());
|
|
@@ -311,8 +311,7 @@ namespace Sass {
|
|
|
311
311
|
Expression* Eval::operator()(Map* m)
|
|
312
312
|
{
|
|
313
313
|
if (m->is_expanded()) return m;
|
|
314
|
-
Map* mm = new (ctx.mem) Map(m->
|
|
315
|
-
m->position(),
|
|
314
|
+
Map* mm = new (ctx.mem) Map(m->pstate(),
|
|
316
315
|
m->length());
|
|
317
316
|
for (auto key : m->keys()) {
|
|
318
317
|
*mm << std::make_pair(key->perform(this), m->at(key)->perform(this));
|
|
@@ -337,9 +336,10 @@ namespace Sass {
|
|
|
337
336
|
// don't eval delayed expressions (the '/' when used as a separator)
|
|
338
337
|
if (op_type == Binary_Expression::DIV && b->is_delayed()) return b;
|
|
339
338
|
// if one of the operands is a '/' then make sure it's evaluated
|
|
340
|
-
if (typeid(*b->left()) == typeid(Binary_Expression)) b->left()->is_delayed(false);
|
|
341
|
-
// the logical connectives need to short-circuit
|
|
342
339
|
Expression* lhs = b->left()->perform(this);
|
|
340
|
+
lhs->is_delayed(false);
|
|
341
|
+
while (typeid(*lhs) == typeid(Binary_Expression)) lhs = lhs->perform(this);
|
|
342
|
+
|
|
343
343
|
switch (op_type) {
|
|
344
344
|
case Binary_Expression::AND:
|
|
345
345
|
return *lhs ? b->right()->perform(this) : lhs;
|
|
@@ -354,15 +354,17 @@ namespace Sass {
|
|
|
354
354
|
}
|
|
355
355
|
// not a logical connective, so go ahead and eval the rhs
|
|
356
356
|
Expression* rhs = b->right()->perform(this);
|
|
357
|
+
rhs->is_delayed(false);
|
|
358
|
+
while (typeid(*rhs) == typeid(Binary_Expression)) rhs = rhs->perform(this);
|
|
357
359
|
|
|
358
360
|
// see if it's a relational expression
|
|
359
361
|
switch(op_type) {
|
|
360
|
-
case Binary_Expression::EQ: return new (ctx.mem) Boolean(b->
|
|
361
|
-
case Binary_Expression::NEQ: return new (ctx.mem) Boolean(b->
|
|
362
|
-
case Binary_Expression::GT: return new (ctx.mem) Boolean(b->
|
|
363
|
-
case Binary_Expression::GTE: return new (ctx.mem) Boolean(b->
|
|
364
|
-
case Binary_Expression::LT: return new (ctx.mem) Boolean(b->
|
|
365
|
-
case Binary_Expression::LTE: return new (ctx.mem) Boolean(b->
|
|
362
|
+
case Binary_Expression::EQ: return new (ctx.mem) Boolean(b->pstate(), eq(lhs, rhs, ctx));
|
|
363
|
+
case Binary_Expression::NEQ: return new (ctx.mem) Boolean(b->pstate(), !eq(lhs, rhs, ctx));
|
|
364
|
+
case Binary_Expression::GT: return new (ctx.mem) Boolean(b->pstate(), !lt(lhs, rhs, ctx) && !eq(lhs, rhs, ctx));
|
|
365
|
+
case Binary_Expression::GTE: return new (ctx.mem) Boolean(b->pstate(), !lt(lhs, rhs, ctx));
|
|
366
|
+
case Binary_Expression::LT: return new (ctx.mem) Boolean(b->pstate(), lt(lhs, rhs, ctx));
|
|
367
|
+
case Binary_Expression::LTE: return new (ctx.mem) Boolean(b->pstate(), lt(lhs, rhs, ctx) || eq(lhs, rhs, ctx));
|
|
366
368
|
|
|
367
369
|
default: break;
|
|
368
370
|
}
|
|
@@ -382,14 +384,25 @@ namespace Sass {
|
|
|
382
384
|
if (l_type == Expression::COLOR && r_type == Expression::COLOR) {
|
|
383
385
|
return op_colors(ctx, op_type, lhs, rhs);
|
|
384
386
|
}
|
|
385
|
-
|
|
387
|
+
|
|
388
|
+
Expression* ex = op_strings(ctx, op_type, lhs, rhs);
|
|
389
|
+
if (String_Constant* str = (String_Constant*) ex)
|
|
390
|
+
{
|
|
391
|
+
if (str->concrete_type() != Expression::STRING) return ex;
|
|
392
|
+
String_Constant* lstr = dynamic_cast<String_Constant*>(lhs);
|
|
393
|
+
String_Constant* rstr = dynamic_cast<String_Constant*>(rhs);
|
|
394
|
+
if (String_Constant* org = lstr ? lstr : rstr)
|
|
395
|
+
{ str->quote_mark(org->quote_mark()); }
|
|
396
|
+
}
|
|
397
|
+
return ex;
|
|
398
|
+
|
|
386
399
|
}
|
|
387
400
|
|
|
388
401
|
Expression* Eval::operator()(Unary_Expression* u)
|
|
389
402
|
{
|
|
390
403
|
Expression* operand = u->operand()->perform(this);
|
|
391
404
|
if (u->type() == Unary_Expression::NOT) {
|
|
392
|
-
Boolean* result = new (ctx.mem) Boolean(u->
|
|
405
|
+
Boolean* result = new (ctx.mem) Boolean(u->pstate(), (bool)*operand);
|
|
393
406
|
result->value(!result->value());
|
|
394
407
|
return result;
|
|
395
408
|
}
|
|
@@ -401,15 +414,14 @@ namespace Sass {
|
|
|
401
414
|
return result;
|
|
402
415
|
}
|
|
403
416
|
else {
|
|
404
|
-
To_String to_string;
|
|
417
|
+
To_String to_string(&ctx);
|
|
405
418
|
// Special cases: +/- variables which evaluate to null ouput just +/-,
|
|
406
419
|
// but +/- null itself outputs the string
|
|
407
420
|
if (operand->concrete_type() == Expression::NULL_VAL && typeid(*(u->operand())) == typeid(Variable)) {
|
|
408
|
-
u->operand(new (ctx.mem) String_Constant(u->
|
|
421
|
+
u->operand(new (ctx.mem) String_Constant(u->pstate(), ""));
|
|
409
422
|
}
|
|
410
423
|
else u->operand(operand);
|
|
411
|
-
String_Constant* result = new (ctx.mem) String_Constant(u->
|
|
412
|
-
u->position(),
|
|
424
|
+
String_Constant* result = new (ctx.mem) String_Constant(u->pstate(),
|
|
413
425
|
u->perform(&to_string));
|
|
414
426
|
return result;
|
|
415
427
|
}
|
|
@@ -434,13 +446,11 @@ namespace Sass {
|
|
|
434
446
|
|
|
435
447
|
// if it doesn't exist, just pass it through as a literal
|
|
436
448
|
if (!env->has(full_name)) {
|
|
437
|
-
Function_Call* lit = new (ctx.mem) Function_Call(c->
|
|
438
|
-
c->position(),
|
|
449
|
+
Function_Call* lit = new (ctx.mem) Function_Call(c->pstate(),
|
|
439
450
|
c->name(),
|
|
440
451
|
args);
|
|
441
|
-
To_String to_string;
|
|
442
|
-
return new (ctx.mem) String_Constant(c->
|
|
443
|
-
c->position(),
|
|
452
|
+
To_String to_string(&ctx);
|
|
453
|
+
return new (ctx.mem) String_Constant(c->pstate(),
|
|
444
454
|
lit->perform(&to_string));
|
|
445
455
|
}
|
|
446
456
|
|
|
@@ -473,12 +483,12 @@ namespace Sass {
|
|
|
473
483
|
Env* old_env = env;
|
|
474
484
|
env = &new_env;
|
|
475
485
|
|
|
476
|
-
Backtrace here(backtrace, c->
|
|
486
|
+
Backtrace here(backtrace, c->pstate(), ", in function `" + c->name() + "`");
|
|
477
487
|
backtrace = &here;
|
|
478
488
|
|
|
479
489
|
result = body->perform(this);
|
|
480
490
|
if (!result) {
|
|
481
|
-
error(string("function ") + c->name() + " did not return a value", c->
|
|
491
|
+
error(string("function ") + c->name() + " did not return a value", c->pstate());
|
|
482
492
|
}
|
|
483
493
|
backtrace = here.parent;
|
|
484
494
|
env = old_env;
|
|
@@ -490,10 +500,10 @@ namespace Sass {
|
|
|
490
500
|
Env* old_env = env;
|
|
491
501
|
env = &new_env;
|
|
492
502
|
|
|
493
|
-
Backtrace here(backtrace, c->
|
|
503
|
+
Backtrace here(backtrace, c->pstate(), ", in function `" + c->name() + "`");
|
|
494
504
|
backtrace = &here;
|
|
495
505
|
|
|
496
|
-
result = func(*env, *old_env, ctx, def->signature(), c->
|
|
506
|
+
result = func(*env, *old_env, ctx, def->signature(), c->pstate(), backtrace);
|
|
497
507
|
|
|
498
508
|
backtrace = here.parent;
|
|
499
509
|
env = old_env;
|
|
@@ -502,9 +512,9 @@ namespace Sass {
|
|
|
502
512
|
else if (c_func) {
|
|
503
513
|
|
|
504
514
|
if (full_name == "*[f]") {
|
|
505
|
-
String_Constant *str = new (ctx.mem) String_Constant(c->
|
|
506
|
-
Arguments* new_args = new (ctx.mem) Arguments(c->
|
|
507
|
-
*new_args << new (ctx.mem) Argument(c->
|
|
515
|
+
String_Constant *str = new (ctx.mem) String_Constant(c->pstate(), c->name());
|
|
516
|
+
Arguments* new_args = new (ctx.mem) Arguments(c->pstate());
|
|
517
|
+
*new_args << new (ctx.mem) Argument(c->pstate(), str);
|
|
508
518
|
*new_args += args;
|
|
509
519
|
args = new_args;
|
|
510
520
|
}
|
|
@@ -514,7 +524,7 @@ namespace Sass {
|
|
|
514
524
|
Env* old_env = env;
|
|
515
525
|
env = &new_env;
|
|
516
526
|
|
|
517
|
-
Backtrace here(backtrace, c->
|
|
527
|
+
Backtrace here(backtrace, c->pstate(), ", in function `" + c->name() + "`");
|
|
518
528
|
backtrace = &here;
|
|
519
529
|
|
|
520
530
|
To_C to_c;
|
|
@@ -527,11 +537,11 @@ namespace Sass {
|
|
|
527
537
|
}
|
|
528
538
|
Sass_Value* c_val = c_func(c_args, def->cookie());
|
|
529
539
|
if (sass_value_get_tag(c_val) == SASS_ERROR) {
|
|
530
|
-
error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->
|
|
540
|
+
error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), backtrace);
|
|
531
541
|
} else if (sass_value_get_tag(c_val) == SASS_WARNING) {
|
|
532
|
-
error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->
|
|
542
|
+
error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->pstate(), backtrace);
|
|
533
543
|
}
|
|
534
|
-
result = cval_to_astnode(c_val, ctx, backtrace, c->
|
|
544
|
+
result = cval_to_astnode(c_val, ctx, backtrace, c->pstate());
|
|
535
545
|
|
|
536
546
|
backtrace = here.parent;
|
|
537
547
|
sass_delete_value(c_args);
|
|
@@ -545,7 +555,7 @@ namespace Sass {
|
|
|
545
555
|
stringstream ss;
|
|
546
556
|
ss << full_name << arity;
|
|
547
557
|
string resolved_name(ss.str());
|
|
548
|
-
if (!env->has(resolved_name)) error("overloaded function `" + string(c->name()) + "` given wrong number of arguments", c->
|
|
558
|
+
if (!env->has(resolved_name)) error("overloaded function `" + string(c->name()) + "` given wrong number of arguments", c->pstate());
|
|
549
559
|
Definition* resolved_def = static_cast<Definition*>((*env)[resolved_name]);
|
|
550
560
|
params = resolved_def->parameters();
|
|
551
561
|
Env newer_env;
|
|
@@ -554,10 +564,10 @@ namespace Sass {
|
|
|
554
564
|
Env* old_env = env;
|
|
555
565
|
env = &newer_env;
|
|
556
566
|
|
|
557
|
-
Backtrace here(backtrace, c->
|
|
567
|
+
Backtrace here(backtrace, c->pstate(), ", in function `" + c->name() + "`");
|
|
558
568
|
backtrace = &here;
|
|
559
569
|
|
|
560
|
-
result = resolved_def->native_function()(*env, *old_env, ctx, resolved_def->signature(), c->
|
|
570
|
+
result = resolved_def->native_function()(*env, *old_env, ctx, resolved_def->signature(), c->pstate(), backtrace);
|
|
561
571
|
|
|
562
572
|
backtrace = here.parent;
|
|
563
573
|
env = old_env;
|
|
@@ -565,7 +575,17 @@ namespace Sass {
|
|
|
565
575
|
|
|
566
576
|
// backtrace = here.parent;
|
|
567
577
|
// env = old_env;
|
|
568
|
-
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
// link back to function definition
|
|
581
|
+
// only do this for custom functions
|
|
582
|
+
if (result->pstate().file == string::npos)
|
|
583
|
+
result->pstate(c->pstate());
|
|
584
|
+
|
|
585
|
+
do {
|
|
586
|
+
result->is_delayed(result->concrete_type() == Expression::STRING);
|
|
587
|
+
result = result->perform(this);
|
|
588
|
+
} while (result->concrete_type() == Expression::NONE);
|
|
569
589
|
return result;
|
|
570
590
|
}
|
|
571
591
|
|
|
@@ -573,35 +593,47 @@ namespace Sass {
|
|
|
573
593
|
{
|
|
574
594
|
Expression* evaluated_name = s->name()->perform(this);
|
|
575
595
|
Expression* evaluated_args = s->arguments()->perform(this);
|
|
576
|
-
String_Schema* ss = new (ctx.mem) String_Schema(s->
|
|
596
|
+
String_Schema* ss = new (ctx.mem) String_Schema(s->pstate(), 2);
|
|
577
597
|
(*ss) << evaluated_name << evaluated_args;
|
|
578
598
|
return ss->perform(this);
|
|
579
599
|
}
|
|
580
600
|
|
|
581
601
|
Expression* Eval::operator()(Variable* v)
|
|
582
602
|
{
|
|
583
|
-
To_String to_string;
|
|
603
|
+
To_String to_string(&ctx);
|
|
584
604
|
string name(v->name());
|
|
585
605
|
Expression* value = 0;
|
|
586
606
|
if (env->has(name)) value = static_cast<Expression*>((*env)[name]);
|
|
587
|
-
else error("
|
|
607
|
+
else error("Undefined variable: \"" + v->name() + "\".", v->pstate());
|
|
588
608
|
// cerr << "name: " << v->name() << "; type: " << typeid(*value).name() << "; value: " << value->perform(&to_string) << endl;
|
|
589
609
|
if (typeid(*value) == typeid(Argument)) value = static_cast<Argument*>(value)->value();
|
|
590
610
|
|
|
591
611
|
// behave according to as ruby sass (add leading zero)
|
|
592
612
|
if (value->concrete_type() == Expression::NUMBER) {
|
|
593
|
-
|
|
594
|
-
value
|
|
595
|
-
n->position(),
|
|
596
|
-
n->value(),
|
|
597
|
-
n->unit(),
|
|
598
|
-
true);
|
|
613
|
+
value = new (ctx.mem) Number(*static_cast<Number*>(value));
|
|
614
|
+
static_cast<Number*>(value)->zero(true);
|
|
599
615
|
}
|
|
600
616
|
else if (value->concrete_type() == Expression::STRING) {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
617
|
+
if (auto str = dynamic_cast<String_Quoted*>(value)) {
|
|
618
|
+
value = new (ctx.mem) String_Quoted(*str);
|
|
619
|
+
} else if (auto str = dynamic_cast<String_Constant*>(value)) {
|
|
620
|
+
value = new (ctx.mem) String_Constant(*str);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
else if (value->concrete_type() == Expression::LIST) {
|
|
624
|
+
value = new (ctx.mem) List(*static_cast<List*>(value));
|
|
625
|
+
}
|
|
626
|
+
else if (value->concrete_type() == Expression::MAP) {
|
|
627
|
+
value = new (ctx.mem) Map(*static_cast<Map*>(value));
|
|
628
|
+
}
|
|
629
|
+
else if (value->concrete_type() == Expression::BOOLEAN) {
|
|
630
|
+
value = new (ctx.mem) Boolean(*static_cast<Boolean*>(value));
|
|
631
|
+
}
|
|
632
|
+
else if (value->concrete_type() == Expression::COLOR) {
|
|
633
|
+
value = new (ctx.mem) Color(*static_cast<Color*>(value));
|
|
634
|
+
}
|
|
635
|
+
else if (value->concrete_type() == Expression::NULL_VAL) {
|
|
636
|
+
value = new (ctx.mem) Null(value->pstate());
|
|
605
637
|
}
|
|
606
638
|
|
|
607
639
|
// cerr << "\ttype is now: " << typeid(*value).name() << endl << endl;
|
|
@@ -625,24 +657,21 @@ namespace Sass {
|
|
|
625
657
|
switch (t->type())
|
|
626
658
|
{
|
|
627
659
|
case Textual::NUMBER:
|
|
628
|
-
result = new (ctx.mem) Number(t->
|
|
629
|
-
|
|
630
|
-
atof(num.c_str()),
|
|
660
|
+
result = new (ctx.mem) Number(t->pstate(),
|
|
661
|
+
sass_atof(num.c_str()),
|
|
631
662
|
"",
|
|
632
663
|
zero);
|
|
633
664
|
break;
|
|
634
665
|
case Textual::PERCENTAGE:
|
|
635
|
-
result = new (ctx.mem) Number(t->
|
|
636
|
-
|
|
637
|
-
atof(num.c_str()),
|
|
666
|
+
result = new (ctx.mem) Number(t->pstate(),
|
|
667
|
+
sass_atof(num.c_str()),
|
|
638
668
|
"%",
|
|
639
669
|
zero);
|
|
640
670
|
break;
|
|
641
671
|
case Textual::DIMENSION:
|
|
642
|
-
result = new (ctx.mem) Number(t->
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
Token(number(text.c_str())),
|
|
672
|
+
result = new (ctx.mem) Number(t->pstate(),
|
|
673
|
+
sass_atof(num.c_str()),
|
|
674
|
+
Token(number(text.c_str()), t->pstate()),
|
|
646
675
|
zero);
|
|
647
676
|
break;
|
|
648
677
|
case Textual::HEX: {
|
|
@@ -651,8 +680,7 @@ namespace Sass {
|
|
|
651
680
|
string r(hext.substr(0,2));
|
|
652
681
|
string g(hext.substr(2,2));
|
|
653
682
|
string b(hext.substr(4,2));
|
|
654
|
-
result = new (ctx.mem) Color(t->
|
|
655
|
-
t->position(),
|
|
683
|
+
result = new (ctx.mem) Color(t->pstate(),
|
|
656
684
|
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
|
657
685
|
static_cast<double>(strtol(g.c_str(), NULL, 16)),
|
|
658
686
|
static_cast<double>(strtol(b.c_str(), NULL, 16)),
|
|
@@ -660,8 +688,7 @@ namespace Sass {
|
|
|
660
688
|
t->value());
|
|
661
689
|
}
|
|
662
690
|
else {
|
|
663
|
-
result = new (ctx.mem) Color(t->
|
|
664
|
-
t->position(),
|
|
691
|
+
result = new (ctx.mem) Color(t->pstate(),
|
|
665
692
|
static_cast<double>(strtol(string(2,hext[0]).c_str(), NULL, 16)),
|
|
666
693
|
static_cast<double>(strtol(string(2,hext[1]).c_str(), NULL, 16)),
|
|
667
694
|
static_cast<double>(strtol(string(2,hext[2]).c_str(), NULL, 16)),
|
|
@@ -676,8 +703,7 @@ namespace Sass {
|
|
|
676
703
|
Expression* Eval::operator()(Number* n)
|
|
677
704
|
{
|
|
678
705
|
// behave according to as ruby sass (add leading zero)
|
|
679
|
-
return new (ctx.mem) Number(n->
|
|
680
|
-
n->position(),
|
|
706
|
+
return new (ctx.mem) Number(n->pstate(),
|
|
681
707
|
n->value(),
|
|
682
708
|
n->unit(),
|
|
683
709
|
true);
|
|
@@ -700,32 +726,93 @@ namespace Sass {
|
|
|
700
726
|
}
|
|
701
727
|
}
|
|
702
728
|
|
|
729
|
+
string Eval::interpolation(Expression* s) {
|
|
730
|
+
|
|
731
|
+
if (String_Quoted* str_quoted = dynamic_cast<String_Quoted*>(s)) {
|
|
732
|
+
|
|
733
|
+
if (str_quoted->quote_mark()) {
|
|
734
|
+
return string_escape(str_quoted->value());
|
|
735
|
+
} else {
|
|
736
|
+
return evacuate_escapes(str_quoted->value());
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
} else if (String_Constant* str_constant = dynamic_cast<String_Constant*>(s)) {
|
|
740
|
+
|
|
741
|
+
return evacuate_escapes(str_constant->value());
|
|
742
|
+
|
|
743
|
+
} else if (String_Schema* str_schema = dynamic_cast<String_Schema*>(s)) {
|
|
744
|
+
|
|
745
|
+
string res = "";
|
|
746
|
+
for(auto i : str_schema->elements())
|
|
747
|
+
res += (interpolation(i));
|
|
748
|
+
//ToDo: do this in one step
|
|
749
|
+
auto esc = evacuate_escapes(res);
|
|
750
|
+
auto unq = unquote(esc);
|
|
751
|
+
if (unq == esc) {
|
|
752
|
+
return string_to_output(res);
|
|
753
|
+
} else {
|
|
754
|
+
return evacuate_quotes(unq);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
} else if (List* list = dynamic_cast<List*>(s)) {
|
|
758
|
+
|
|
759
|
+
string acc = ""; // ToDo: different output styles
|
|
760
|
+
string sep = list->separator() == List::Separator::COMMA ? "," : " ";
|
|
761
|
+
if (ctx.output_style != COMPRESSED && sep == ",") sep += " ";
|
|
762
|
+
bool initial = false;
|
|
763
|
+
for(auto item : list->elements()) {
|
|
764
|
+
if (initial) acc += sep;
|
|
765
|
+
acc += interpolation(item);
|
|
766
|
+
initial = true;
|
|
767
|
+
}
|
|
768
|
+
return evacuate_quotes(acc);
|
|
769
|
+
|
|
770
|
+
} else if (Variable* var = dynamic_cast<Variable*>(s)) {
|
|
771
|
+
|
|
772
|
+
string name(var->name());
|
|
773
|
+
if (!env->has(name)) error("Undefined variable: \"" + var->name() + "\".", var->pstate());
|
|
774
|
+
Expression* value = static_cast<Expression*>((*env)[name]);
|
|
775
|
+
return evacuate_quotes(interpolation(value));
|
|
776
|
+
|
|
777
|
+
} else if (Binary_Expression* var = dynamic_cast<Binary_Expression*>(s)) {
|
|
778
|
+
|
|
779
|
+
Expression* ex = operator()(var);
|
|
780
|
+
return evacuate_quotes(interpolation(ex));
|
|
781
|
+
|
|
782
|
+
} else if (Function_Call* var = dynamic_cast<Function_Call*>(s)) {
|
|
783
|
+
|
|
784
|
+
Expression* ex = operator()(var);
|
|
785
|
+
return evacuate_quotes(interpolation(ex));
|
|
786
|
+
|
|
787
|
+
} else {
|
|
788
|
+
|
|
789
|
+
To_String to_string(&ctx);
|
|
790
|
+
// to_string.in_decl_list = true;
|
|
791
|
+
return evacuate_quotes(s->perform(&to_string));
|
|
792
|
+
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
703
796
|
Expression* Eval::operator()(String_Schema* s)
|
|
704
797
|
{
|
|
705
798
|
string acc;
|
|
706
|
-
ctx._skip_source_map_update = true;
|
|
707
|
-
To_String to_string(&ctx);
|
|
708
|
-
ctx._skip_source_map_update = false;
|
|
709
799
|
for (size_t i = 0, L = s->length(); i < L; ++i) {
|
|
710
|
-
|
|
711
|
-
if (((s->quote_mark() && is_quoted(chunk)) || !s->quote_mark()) && (*s)[i]->is_interpolant()) { // some redundancy in that test
|
|
712
|
-
acc += unquote(chunk);
|
|
713
|
-
}
|
|
714
|
-
else {
|
|
715
|
-
acc += chunk;
|
|
716
|
-
}
|
|
800
|
+
acc += interpolation((*s)[i]);
|
|
717
801
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
802
|
+
String_Quoted* str = new (ctx.mem) String_Quoted(s->pstate(), acc);
|
|
803
|
+
if (!str->quote_mark()) {
|
|
804
|
+
str->value(string_unescape(str->value()));
|
|
805
|
+
} else if (str->quote_mark()) {
|
|
806
|
+
str->quote_mark('*');
|
|
807
|
+
}
|
|
808
|
+
return str;
|
|
721
809
|
}
|
|
722
810
|
|
|
723
811
|
Expression* Eval::operator()(String_Constant* s)
|
|
724
812
|
{
|
|
725
|
-
if (!s->is_delayed() && ctx.names_to_colors.count(s->value())) {
|
|
813
|
+
if (!s->quote_mark() && !s->is_delayed() && ctx.names_to_colors.count(s->value())) {
|
|
726
814
|
Color* c = new (ctx.mem) Color(*ctx.names_to_colors[s->value()]);
|
|
727
|
-
c->
|
|
728
|
-
c->position(s->position());
|
|
815
|
+
c->pstate(s->pstate());
|
|
729
816
|
c->disp(s->value());
|
|
730
817
|
return c;
|
|
731
818
|
}
|
|
@@ -734,8 +821,7 @@ namespace Sass {
|
|
|
734
821
|
|
|
735
822
|
Expression* Eval::operator()(Feature_Query* q)
|
|
736
823
|
{
|
|
737
|
-
Feature_Query* qq = new (ctx.mem) Feature_Query(q->
|
|
738
|
-
q->position(),
|
|
824
|
+
Feature_Query* qq = new (ctx.mem) Feature_Query(q->pstate(),
|
|
739
825
|
q->length());
|
|
740
826
|
for (size_t i = 0, L = q->length(); i < L; ++i) {
|
|
741
827
|
*qq << static_cast<Feature_Query_Condition*>((*q)[i]->perform(this));
|
|
@@ -748,8 +834,7 @@ namespace Sass {
|
|
|
748
834
|
String* feature = c->feature();
|
|
749
835
|
Expression* value = c->value();
|
|
750
836
|
value = (value ? value->perform(this) : 0);
|
|
751
|
-
Feature_Query_Condition* cc = new (ctx.mem) Feature_Query_Condition(c->
|
|
752
|
-
c->position(),
|
|
837
|
+
Feature_Query_Condition* cc = new (ctx.mem) Feature_Query_Condition(c->pstate(),
|
|
753
838
|
c->length(),
|
|
754
839
|
feature,
|
|
755
840
|
value,
|
|
@@ -761,12 +846,25 @@ namespace Sass {
|
|
|
761
846
|
return cc;
|
|
762
847
|
}
|
|
763
848
|
|
|
849
|
+
Expression* Eval::operator()(At_Root_Expression* e)
|
|
850
|
+
{
|
|
851
|
+
Expression* feature = e->feature();
|
|
852
|
+
feature = (feature ? feature->perform(this) : 0);
|
|
853
|
+
Expression* value = e->value();
|
|
854
|
+
value = (value ? value->perform(this) : 0);
|
|
855
|
+
Expression* ee = new (ctx.mem) At_Root_Expression(e->pstate(),
|
|
856
|
+
static_cast<String*>(feature),
|
|
857
|
+
value,
|
|
858
|
+
e->is_interpolated());
|
|
859
|
+
return ee;
|
|
860
|
+
}
|
|
861
|
+
|
|
764
862
|
Expression* Eval::operator()(Media_Query* q)
|
|
765
863
|
{
|
|
864
|
+
To_String to_string(&ctx);
|
|
766
865
|
String* t = q->media_type();
|
|
767
866
|
t = static_cast<String*>(t ? t->perform(this) : 0);
|
|
768
|
-
Media_Query* qq = new (ctx.mem) Media_Query(q->
|
|
769
|
-
q->position(),
|
|
867
|
+
Media_Query* qq = new (ctx.mem) Media_Query(q->pstate(),
|
|
770
868
|
t,
|
|
771
869
|
q->length(),
|
|
772
870
|
q->is_negated(),
|
|
@@ -783,8 +881,7 @@ namespace Sass {
|
|
|
783
881
|
feature = (feature ? feature->perform(this) : 0);
|
|
784
882
|
Expression* value = e->value();
|
|
785
883
|
value = (value ? value->perform(this) : 0);
|
|
786
|
-
return new (ctx.mem) Media_Query_Expression(e->
|
|
787
|
-
e->position(),
|
|
884
|
+
return new (ctx.mem) Media_Query_Expression(e->pstate(),
|
|
788
885
|
feature,
|
|
789
886
|
value,
|
|
790
887
|
e->is_interpolated());
|
|
@@ -812,8 +909,7 @@ namespace Sass {
|
|
|
812
909
|
}
|
|
813
910
|
else
|
|
814
911
|
if(val->concrete_type() != Expression::LIST) {
|
|
815
|
-
List* wrapper = new (ctx.mem) List(val->
|
|
816
|
-
val->position(),
|
|
912
|
+
List* wrapper = new (ctx.mem) List(val->pstate(),
|
|
817
913
|
0,
|
|
818
914
|
List::COMMA,
|
|
819
915
|
true);
|
|
@@ -821,8 +917,7 @@ namespace Sass {
|
|
|
821
917
|
val = wrapper;
|
|
822
918
|
}
|
|
823
919
|
}
|
|
824
|
-
return new (ctx.mem) Argument(a->
|
|
825
|
-
a->position(),
|
|
920
|
+
return new (ctx.mem) Argument(a->pstate(),
|
|
826
921
|
val,
|
|
827
922
|
a->name(),
|
|
828
923
|
is_rest_argument,
|
|
@@ -831,13 +926,18 @@ namespace Sass {
|
|
|
831
926
|
|
|
832
927
|
Expression* Eval::operator()(Arguments* a)
|
|
833
928
|
{
|
|
834
|
-
Arguments* aa = new (ctx.mem) Arguments(a->
|
|
929
|
+
Arguments* aa = new (ctx.mem) Arguments(a->pstate());
|
|
835
930
|
for (size_t i = 0, L = a->length(); i < L; ++i) {
|
|
836
931
|
*aa << static_cast<Argument*>((*a)[i]->perform(this));
|
|
837
932
|
}
|
|
838
933
|
return aa;
|
|
839
934
|
}
|
|
840
935
|
|
|
936
|
+
Expression* Eval::operator()(Comment* c)
|
|
937
|
+
{
|
|
938
|
+
return 0;
|
|
939
|
+
}
|
|
940
|
+
|
|
841
941
|
inline Expression* Eval::fallback_impl(AST_Node* n)
|
|
842
942
|
{
|
|
843
943
|
return static_cast<Expression*>(n);
|
|
@@ -913,7 +1013,7 @@ namespace Sass {
|
|
|
913
1013
|
{
|
|
914
1014
|
if (lhs->concrete_type() != Expression::NUMBER ||
|
|
915
1015
|
rhs->concrete_type() != Expression::NUMBER)
|
|
916
|
-
error("may only compare numbers", lhs->
|
|
1016
|
+
error("may only compare numbers", lhs->pstate());
|
|
917
1017
|
Number* l = static_cast<Number*>(lhs);
|
|
918
1018
|
Number* r = static_cast<Number*>(rhs);
|
|
919
1019
|
Number tmp_r(*r);
|
|
@@ -921,7 +1021,7 @@ namespace Sass {
|
|
|
921
1021
|
string l_unit(l->unit());
|
|
922
1022
|
string r_unit(tmp_r.unit());
|
|
923
1023
|
if (!l_unit.empty() && !r_unit.empty() && l->unit() != tmp_r.unit()) {
|
|
924
|
-
error("cannot compare numbers with incompatible units", l->
|
|
1024
|
+
error("cannot compare numbers with incompatible units", l->pstate());
|
|
925
1025
|
}
|
|
926
1026
|
return l->value() < tmp_r.value();
|
|
927
1027
|
}
|
|
@@ -934,10 +1034,10 @@ namespace Sass {
|
|
|
934
1034
|
double rv = r->value();
|
|
935
1035
|
Binary_Expression::Type op = b->type();
|
|
936
1036
|
if (op == Binary_Expression::DIV && !rv) {
|
|
937
|
-
return new (ctx.mem) String_Constant(l->
|
|
1037
|
+
return new (ctx.mem) String_Constant(l->pstate(), "Infinity");
|
|
938
1038
|
}
|
|
939
1039
|
if (op == Binary_Expression::MOD && !rv) {
|
|
940
|
-
error("division by zero", r->
|
|
1040
|
+
error("division by zero", r->pstate());
|
|
941
1041
|
}
|
|
942
1042
|
|
|
943
1043
|
Number tmp(*r);
|
|
@@ -946,10 +1046,10 @@ namespace Sass {
|
|
|
946
1046
|
string r_unit(tmp.unit());
|
|
947
1047
|
if (l_unit != r_unit && !l_unit.empty() && !r_unit.empty() &&
|
|
948
1048
|
(op == Binary_Expression::ADD || op == Binary_Expression::SUB)) {
|
|
949
|
-
error("
|
|
1049
|
+
error("Incompatible units: '"+r_unit+"' and '"+l_unit+"'.", l->pstate());
|
|
950
1050
|
}
|
|
951
1051
|
Number* v = new (ctx.mem) Number(*l);
|
|
952
|
-
v->
|
|
1052
|
+
v->pstate(b->pstate());
|
|
953
1053
|
if (l_unit.empty() && (op == Binary_Expression::ADD || op == Binary_Expression::SUB || op == Binary_Expression::MOD)) {
|
|
954
1054
|
v->numerator_units() = r->numerator_units();
|
|
955
1055
|
v->denominator_units() = r->denominator_units();
|
|
@@ -988,8 +1088,7 @@ namespace Sass {
|
|
|
988
1088
|
switch (op) {
|
|
989
1089
|
case Binary_Expression::ADD:
|
|
990
1090
|
case Binary_Expression::MUL: {
|
|
991
|
-
return new (ctx.mem) Color(l->
|
|
992
|
-
l->position(),
|
|
1091
|
+
return new (ctx.mem) Color(l->pstate(),
|
|
993
1092
|
ops[op](lv, r->r()),
|
|
994
1093
|
ops[op](lv, r->g()),
|
|
995
1094
|
ops[op](lv, r->b()),
|
|
@@ -998,17 +1097,17 @@ namespace Sass {
|
|
|
998
1097
|
case Binary_Expression::SUB:
|
|
999
1098
|
case Binary_Expression::DIV: {
|
|
1000
1099
|
string sep(op == Binary_Expression::SUB ? "-" : "/");
|
|
1001
|
-
To_String to_string;
|
|
1002
|
-
string color(r->sixtuplet()
|
|
1100
|
+
To_String to_string(&ctx);
|
|
1101
|
+
string color(r->sixtuplet() && (ctx.output_style != COMPRESSED) ?
|
|
1102
|
+
r->perform(&to_string) :
|
|
1003
1103
|
Util::normalize_sixtuplet(r->perform(&to_string)));
|
|
1004
|
-
return new (ctx.mem) String_Constant(l->
|
|
1005
|
-
l->position(),
|
|
1104
|
+
return new (ctx.mem) String_Constant(l->pstate(),
|
|
1006
1105
|
l->perform(&to_string)
|
|
1007
1106
|
+ sep
|
|
1008
1107
|
+ color);
|
|
1009
1108
|
} break;
|
|
1010
1109
|
case Binary_Expression::MOD: {
|
|
1011
|
-
error("cannot divide a number by a color", r->
|
|
1110
|
+
error("cannot divide a number by a color", r->pstate());
|
|
1012
1111
|
} break;
|
|
1013
1112
|
default: break; // caller should ensure that we don't get here
|
|
1014
1113
|
}
|
|
@@ -1021,9 +1120,8 @@ namespace Sass {
|
|
|
1021
1120
|
Color* l = static_cast<Color*>(lhs);
|
|
1022
1121
|
Number* r = static_cast<Number*>(rhs);
|
|
1023
1122
|
double rv = r->value();
|
|
1024
|
-
if (op == Binary_Expression::DIV && !rv) error("division by zero", r->
|
|
1025
|
-
return new (ctx.mem) Color(l->
|
|
1026
|
-
l->position(),
|
|
1123
|
+
if (op == Binary_Expression::DIV && !rv) error("division by zero", r->pstate());
|
|
1124
|
+
return new (ctx.mem) Color(l->pstate(),
|
|
1027
1125
|
ops[op](l->r(), rv),
|
|
1028
1126
|
ops[op](l->g(), rv),
|
|
1029
1127
|
ops[op](l->b(), rv),
|
|
@@ -1035,14 +1133,13 @@ namespace Sass {
|
|
|
1035
1133
|
Color* l = static_cast<Color*>(lhs);
|
|
1036
1134
|
Color* r = static_cast<Color*>(rhs);
|
|
1037
1135
|
if (l->a() != r->a()) {
|
|
1038
|
-
error("alpha channels must be equal when combining colors", r->
|
|
1136
|
+
error("alpha channels must be equal when combining colors", r->pstate());
|
|
1039
1137
|
}
|
|
1040
1138
|
if ((op == Binary_Expression::DIV || op == Binary_Expression::MOD) &&
|
|
1041
1139
|
(!r->r() || !r->g() ||!r->b())) {
|
|
1042
|
-
error("division by zero", r->
|
|
1140
|
+
error("division by zero", r->pstate());
|
|
1043
1141
|
}
|
|
1044
|
-
return new (ctx.mem) Color(l->
|
|
1045
|
-
l->position(),
|
|
1142
|
+
return new (ctx.mem) Color(l->pstate(),
|
|
1046
1143
|
ops[op](l->r(), r->r()),
|
|
1047
1144
|
ops[op](l->g(), r->g()),
|
|
1048
1145
|
ops[op](l->b(), r->b()),
|
|
@@ -1051,20 +1148,18 @@ namespace Sass {
|
|
|
1051
1148
|
|
|
1052
1149
|
Expression* op_strings(Context& ctx, Binary_Expression::Type op, Expression* lhs, Expression*rhs)
|
|
1053
1150
|
{
|
|
1054
|
-
To_String to_string;
|
|
1151
|
+
To_String to_string(&ctx);
|
|
1055
1152
|
Expression::Concrete_Type ltype = lhs->concrete_type();
|
|
1056
1153
|
Expression::Concrete_Type rtype = rhs->concrete_type();
|
|
1057
1154
|
|
|
1058
1155
|
string lstr(lhs->perform(&to_string));
|
|
1059
1156
|
string rstr(rhs->perform(&to_string));
|
|
1060
1157
|
|
|
1061
|
-
bool l_str_quoted = ((Sass::String*)lhs) && ((Sass::String*)lhs)->
|
|
1062
|
-
bool r_str_quoted = ((Sass::String*)rhs) && ((Sass::String*)rhs)->
|
|
1158
|
+
bool l_str_quoted = ((Sass::String*)lhs) && ((Sass::String*)lhs)->sass_fix_1291();
|
|
1159
|
+
bool r_str_quoted = ((Sass::String*)rhs) && ((Sass::String*)rhs)->sass_fix_1291();
|
|
1063
1160
|
bool l_str_color = ltype == Expression::STRING && ctx.names_to_colors.count(lstr) && !l_str_quoted;
|
|
1064
1161
|
bool r_str_color = rtype == Expression::STRING && ctx.names_to_colors.count(rstr) && !r_str_quoted;
|
|
1065
1162
|
|
|
1066
|
-
bool unquoted = false;
|
|
1067
|
-
if (ltype == Expression::STRING && lstr[0] != '"' && lstr[0] != '\'') unquoted = true;
|
|
1068
1163
|
if (l_str_color && r_str_color) {
|
|
1069
1164
|
return op_colors(ctx, op, ctx.names_to_colors[lstr], ctx.names_to_colors[rstr]);
|
|
1070
1165
|
}
|
|
@@ -1080,67 +1175,64 @@ namespace Sass {
|
|
|
1080
1175
|
else if (ltype == Expression::NUMBER && r_str_color) {
|
|
1081
1176
|
return op_number_color(ctx, op, lhs, ctx.names_to_colors[rstr]);
|
|
1082
1177
|
}
|
|
1083
|
-
if (op == Binary_Expression::MUL) error("invalid operands for multiplication", lhs->
|
|
1084
|
-
if (op == Binary_Expression::MOD) error("invalid operands for modulo", lhs->
|
|
1178
|
+
if (op == Binary_Expression::MUL) error("invalid operands for multiplication", lhs->pstate());
|
|
1179
|
+
if (op == Binary_Expression::MOD) error("invalid operands for modulo", lhs->pstate());
|
|
1085
1180
|
string sep;
|
|
1086
1181
|
switch (op) {
|
|
1087
1182
|
case Binary_Expression::SUB: sep = "-"; break;
|
|
1088
1183
|
case Binary_Expression::DIV: sep = "/"; break;
|
|
1089
1184
|
default: break;
|
|
1090
1185
|
}
|
|
1091
|
-
if (ltype == Expression::NULL_VAL) error("invalid null operation: \"null plus "+quote(unquote(rstr), '"')+"\".", lhs->
|
|
1092
|
-
if (rtype == Expression::NULL_VAL) error("invalid null operation: \""+quote(unquote(lstr), '"')+" plus null\".", lhs->
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
return new (ctx.mem) String_Constant(lhs->path(),
|
|
1098
|
-
lhs->position(),
|
|
1099
|
-
unquoted ? result : quote(result, q));
|
|
1186
|
+
if (ltype == Expression::NULL_VAL) error("invalid null operation: \"null plus "+quote(unquote(rstr), '"')+"\".", lhs->pstate());
|
|
1187
|
+
if (rtype == Expression::NULL_VAL) error("invalid null operation: \""+quote(unquote(lstr), '"')+" plus null\".", lhs->pstate());
|
|
1188
|
+
string result((lstr) + sep + (rstr));
|
|
1189
|
+
String_Quoted* str = new (ctx.mem) String_Quoted(lhs->pstate(), result);
|
|
1190
|
+
str->quote_mark(0);
|
|
1191
|
+
return str;
|
|
1100
1192
|
}
|
|
1101
1193
|
|
|
1102
|
-
Expression* cval_to_astnode(Sass_Value* v, Context& ctx, Backtrace* backtrace,
|
|
1194
|
+
Expression* cval_to_astnode(Sass_Value* v, Context& ctx, Backtrace* backtrace, ParserState pstate)
|
|
1103
1195
|
{
|
|
1104
1196
|
using std::strlen;
|
|
1105
1197
|
using std::strcpy;
|
|
1106
1198
|
Expression* e = 0;
|
|
1107
1199
|
switch (sass_value_get_tag(v)) {
|
|
1108
1200
|
case SASS_BOOLEAN: {
|
|
1109
|
-
e = new (ctx.mem) Boolean(
|
|
1201
|
+
e = new (ctx.mem) Boolean(pstate, !!sass_boolean_get_value(v));
|
|
1110
1202
|
} break;
|
|
1111
1203
|
case SASS_NUMBER: {
|
|
1112
|
-
e = new (ctx.mem) Number(
|
|
1204
|
+
e = new (ctx.mem) Number(pstate, sass_number_get_value(v), sass_number_get_unit(v));
|
|
1113
1205
|
} break;
|
|
1114
1206
|
case SASS_COLOR: {
|
|
1115
|
-
e = new (ctx.mem) Color(
|
|
1207
|
+
e = new (ctx.mem) Color(pstate, sass_color_get_r(v), sass_color_get_g(v), sass_color_get_b(v), sass_color_get_a(v));
|
|
1116
1208
|
} break;
|
|
1117
1209
|
case SASS_STRING: {
|
|
1118
|
-
e = new (ctx.mem) String_Constant(
|
|
1210
|
+
e = new (ctx.mem) String_Constant(pstate, sass_string_get_value(v));
|
|
1119
1211
|
} break;
|
|
1120
1212
|
case SASS_LIST: {
|
|
1121
|
-
List* l = new (ctx.mem) List(
|
|
1213
|
+
List* l = new (ctx.mem) List(pstate, sass_list_get_length(v), sass_list_get_separator(v) == SASS_COMMA ? List::COMMA : List::SPACE);
|
|
1122
1214
|
for (size_t i = 0, L = sass_list_get_length(v); i < L; ++i) {
|
|
1123
|
-
*l << cval_to_astnode(sass_list_get_value(v, i), ctx, backtrace,
|
|
1215
|
+
*l << cval_to_astnode(sass_list_get_value(v, i), ctx, backtrace, pstate);
|
|
1124
1216
|
}
|
|
1125
1217
|
e = l;
|
|
1126
1218
|
} break;
|
|
1127
1219
|
case SASS_MAP: {
|
|
1128
|
-
Map* m = new (ctx.mem) Map(
|
|
1220
|
+
Map* m = new (ctx.mem) Map(pstate);
|
|
1129
1221
|
for (size_t i = 0, L = sass_map_get_length(v); i < L; ++i) {
|
|
1130
1222
|
*m << std::make_pair(
|
|
1131
|
-
cval_to_astnode(sass_map_get_key(v, i), ctx, backtrace,
|
|
1132
|
-
cval_to_astnode(sass_map_get_value(v, i), ctx, backtrace,
|
|
1223
|
+
cval_to_astnode(sass_map_get_key(v, i), ctx, backtrace, pstate),
|
|
1224
|
+
cval_to_astnode(sass_map_get_value(v, i), ctx, backtrace, pstate));
|
|
1133
1225
|
}
|
|
1134
1226
|
e = m;
|
|
1135
1227
|
} break;
|
|
1136
1228
|
case SASS_NULL: {
|
|
1137
|
-
e = new (ctx.mem) Null(
|
|
1229
|
+
e = new (ctx.mem) Null(pstate);
|
|
1138
1230
|
} break;
|
|
1139
1231
|
case SASS_ERROR: {
|
|
1140
|
-
error("Error in C function: " + string(sass_error_get_message(v)),
|
|
1232
|
+
error("Error in C function: " + string(sass_error_get_message(v)), pstate, backtrace);
|
|
1141
1233
|
} break;
|
|
1142
1234
|
case SASS_WARNING: {
|
|
1143
|
-
error("Warning in C function: " + string(sass_warning_get_message(v)),
|
|
1235
|
+
error("Warning in C function: " + string(sass_warning_get_message(v)), pstate, backtrace);
|
|
1144
1236
|
} break;
|
|
1145
1237
|
}
|
|
1146
1238
|
return e;
|