sassc 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/ext/libsass/.gitignore +13 -6
  4. data/ext/libsass/Makefile +42 -26
  5. data/ext/libsass/Makefile.am +43 -30
  6. data/ext/libsass/Readme.md +4 -2
  7. data/ext/libsass/appveyor.yml +10 -14
  8. data/ext/libsass/ast.cpp +54 -44
  9. data/ext/libsass/ast.hpp +404 -236
  10. data/ext/libsass/ast_def_macros.hpp +5 -0
  11. data/ext/libsass/ast_factory.hpp +6 -3
  12. data/ext/libsass/ast_fwd_decl.hpp +12 -0
  13. data/ext/libsass/b64/encode.h +2 -2
  14. data/ext/libsass/backtrace.hpp +13 -17
  15. data/ext/libsass/base64vlq.hpp +4 -1
  16. data/ext/libsass/bind.cpp +12 -15
  17. data/ext/libsass/bind.hpp +6 -6
  18. data/ext/libsass/color_names.hpp +4 -1
  19. data/ext/libsass/configure.ac +7 -21
  20. data/ext/libsass/constants.cpp +6 -4
  21. data/ext/libsass/constants.hpp +10 -4
  22. data/ext/libsass/context.cpp +89 -58
  23. data/ext/libsass/context.hpp +28 -35
  24. data/ext/libsass/contextualize.cpp +20 -10
  25. data/ext/libsass/contextualize.hpp +8 -23
  26. data/ext/libsass/contrib/libsass.spec +66 -0
  27. data/ext/libsass/cssize.cpp +547 -0
  28. data/ext/libsass/cssize.hpp +82 -0
  29. data/ext/libsass/debug.hpp +3 -3
  30. data/ext/libsass/debugger.hpp +358 -0
  31. data/ext/libsass/emitter.cpp +255 -0
  32. data/ext/libsass/emitter.hpp +83 -0
  33. data/ext/libsass/environment.hpp +7 -3
  34. data/ext/libsass/error_handling.cpp +11 -14
  35. data/ext/libsass/error_handling.hpp +9 -7
  36. data/ext/libsass/eval.cpp +253 -161
  37. data/ext/libsass/eval.hpp +13 -13
  38. data/ext/libsass/expand.cpp +135 -64
  39. data/ext/libsass/expand.hpp +11 -13
  40. data/ext/libsass/extend.cpp +66 -20
  41. data/ext/libsass/extend.hpp +6 -11
  42. data/ext/libsass/file.cpp +31 -26
  43. data/ext/libsass/file.hpp +6 -1
  44. data/ext/libsass/functions.cpp +270 -287
  45. data/ext/libsass/functions.hpp +8 -11
  46. data/ext/libsass/inspect.cpp +385 -255
  47. data/ext/libsass/inspect.hpp +15 -26
  48. data/ext/libsass/kwd_arg_macros.hpp +5 -0
  49. data/ext/libsass/mapping.hpp +4 -3
  50. data/ext/libsass/memory_manager.hpp +5 -2
  51. data/ext/libsass/node.cpp +50 -50
  52. data/ext/libsass/node.hpp +26 -27
  53. data/ext/libsass/operation.hpp +15 -4
  54. data/ext/libsass/output.cpp +401 -0
  55. data/ext/libsass/output.hpp +56 -0
  56. data/ext/libsass/parser.cpp +573 -399
  57. data/ext/libsass/parser.hpp +122 -88
  58. data/ext/libsass/paths.hpp +7 -2
  59. data/ext/libsass/plugins.cpp +155 -0
  60. data/ext/libsass/plugins.hpp +56 -0
  61. data/ext/libsass/position.cpp +128 -0
  62. data/ext/libsass/position.hpp +108 -11
  63. data/ext/libsass/prelexer.cpp +184 -110
  64. data/ext/libsass/prelexer.hpp +131 -24
  65. data/ext/libsass/remove_placeholders.cpp +1 -1
  66. data/ext/libsass/remove_placeholders.hpp +6 -6
  67. data/ext/libsass/sass.cpp +3 -3
  68. data/ext/libsass/sass.h +12 -4
  69. data/ext/libsass/sass2scss.cpp +3 -2
  70. data/ext/libsass/sass2scss.h +5 -0
  71. data/ext/libsass/sass_context.cpp +136 -37
  72. data/ext/libsass/sass_context.h +19 -10
  73. data/ext/libsass/sass_functions.cpp +29 -2
  74. data/ext/libsass/sass_functions.h +8 -2
  75. data/ext/libsass/sass_interface.cpp +32 -23
  76. data/ext/libsass/sass_interface.h +9 -4
  77. data/ext/libsass/sass_util.cpp +19 -23
  78. data/ext/libsass/sass_util.hpp +28 -27
  79. data/ext/libsass/sass_values.cpp +6 -4
  80. data/ext/libsass/sass_values.h +3 -3
  81. data/ext/libsass/script/ci-build-libsass +13 -1
  82. data/ext/libsass/script/ci-report-coverage +2 -1
  83. data/ext/libsass/source_map.cpp +79 -28
  84. data/ext/libsass/source_map.hpp +35 -16
  85. data/ext/libsass/subset_map.hpp +6 -4
  86. data/ext/libsass/to_c.hpp +4 -4
  87. data/ext/libsass/to_string.cpp +13 -8
  88. data/ext/libsass/to_string.hpp +6 -4
  89. data/ext/libsass/units.cpp +2 -1
  90. data/ext/libsass/units.hpp +6 -1
  91. data/ext/libsass/utf8_string.cpp +0 -5
  92. data/ext/libsass/utf8_string.hpp +3 -2
  93. data/ext/libsass/util.cpp +461 -49
  94. data/ext/libsass/util.hpp +34 -13
  95. data/ext/libsass/version.sh +10 -0
  96. data/ext/libsass/win/libsass.filters +20 -11
  97. data/ext/libsass/win/libsass.vcxproj +11 -8
  98. data/lib/sassc/importer.rb +1 -8
  99. data/lib/sassc/native.rb +7 -0
  100. data/lib/sassc/native/native_context_api.rb +5 -5
  101. data/lib/sassc/version.rb +1 -1
  102. data/test/native_test.rb +1 -1
  103. metadata +14 -10
  104. data/ext/libsass/copy_c_str.cpp +0 -13
  105. data/ext/libsass/copy_c_str.hpp +0 -5
  106. data/ext/libsass/output_compressed.cpp +0 -401
  107. data/ext/libsass/output_compressed.hpp +0 -95
  108. data/ext/libsass/output_nested.cpp +0 -364
  109. data/ext/libsass/output_nested.hpp +0 -108
  110. data/ext/libsass/test-driver +0 -127
  111. 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
@@ -1,10 +1,12 @@
1
- #define SASS_ENVIRONMENT
1
+ #ifndef SASS_ENVIRONMENT_H
2
+ #define SASS_ENVIRONMENT_H
2
3
 
3
- #include <string>
4
4
  #include <map>
5
- #include "ast_def_macros.hpp"
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, string path, Position position, string message)
11
- : type(type), path(path), position(position), message(message)
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, string path, Position position)
15
- { throw Sass_Error(Sass_Error::syntax, path, position, msg); }
11
+ void error(string msg, ParserState pstate)
12
+ { throw Sass_Error(Sass_Error::syntax, pstate, msg); }
16
13
 
17
- void error(string msg, string path, Position position, Backtrace* bt)
14
+ void error(string msg, ParserState pstate, Backtrace* bt)
18
15
  {
19
- if (!path.empty() && Prelexer::string_constant(path.c_str()))
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, path, position, "");
19
+ Backtrace top(bt, pstate, "");
23
20
  msg += top.to_string();
24
21
 
25
- throw Sass_Error(Sass_Error::syntax, path, position, msg);
22
+ throw Sass_Error(Sass_Error::syntax, pstate, msg);
26
23
  }
27
24
 
28
25
  }
@@ -1,9 +1,9 @@
1
- #define SASS_ERROR_HANDLING
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
- Position position;
18
+ ParserState pstate;
19
19
  string message;
20
20
 
21
- Sass_Error(Type type, string path, Position position, string message);
21
+ Sass_Error(Type type, ParserState pstate, string message);
22
22
 
23
23
  };
24
24
 
25
- void error(string msg, string path, Position position);
26
- void error(string msg, string path, Position position, Backtrace* bt);
25
+ void error(string msg, ParserState pstate);
26
+ void error(string msg, ParserState pstate, Backtrace* bt);
27
27
 
28
28
  }
29
+
30
+ #endif
@@ -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->path(), low->position());
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->path(), high->position());
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->path(), low->position(), start);
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->path(), low->position(), ++i)) {
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->path(), low->position(), --i)) {
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->path(), expr->position(), 1, List::COMMA);
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->path(), map->position(), 2, List::SPACE);
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]->path(), (*list)[i]->position(), 1, List::COMMA);
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->path(), expr->position());
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->path(), w->position(), "");
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->path(), e->position(), "");
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->path(), cwd, cwd));
291
- cerr << rel_path << ":" << d->position().line << ":" << " DEBUG: " << result;
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->path(),
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->path(),
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->path(), b->position(), eq(lhs, rhs, ctx));
361
- case Binary_Expression::NEQ: return new (ctx.mem) Boolean(b->path(), b->position(), !eq(lhs, rhs, ctx));
362
- case Binary_Expression::GT: return new (ctx.mem) Boolean(b->path(), b->position(), !lt(lhs, rhs, ctx) && !eq(lhs, rhs, ctx));
363
- case Binary_Expression::GTE: return new (ctx.mem) Boolean(b->path(), b->position(), !lt(lhs, rhs, ctx));
364
- case Binary_Expression::LT: return new (ctx.mem) Boolean(b->path(), b->position(), lt(lhs, rhs, ctx));
365
- case Binary_Expression::LTE: return new (ctx.mem) Boolean(b->path(), b->position(), lt(lhs, rhs, ctx) || eq(lhs, rhs, ctx));
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
- return op_strings(ctx, op_type, lhs, rhs);
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->path(), u->position(), (bool)*operand);
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->path(), u->position(), ""));
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->path(),
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->path(),
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->path(),
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->path(), c->position(), ", in function `" + c->name() + "`");
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->path(), c->position());
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->path(), c->position(), ", in function `" + c->name() + "`");
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->path(), c->position(), backtrace);
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->path(), c->position(), c->name());
506
- Arguments* new_args = new (ctx.mem) Arguments(c->path(), c->position());
507
- *new_args << new (ctx.mem) Argument(c->path(), c->position(), str);
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->path(), c->position(), ", in function `" + c->name() + "`");
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->path(), c->position(), backtrace);
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->path(), c->position(), backtrace);
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->path(), c->position());
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->path(), c->position());
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->path(), c->position(), ", in function `" + c->name() + "`");
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->path(), c->position(), backtrace);
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
- result->position(c->position());
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->path(), s->position(), 2);
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("unbound variable " + v->name(), v->path(), v->position());
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
- Number* n = static_cast<Number*>(value);
594
- value = new (ctx.mem) Number(n->path(),
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
- String_Constant* s = static_cast<String_Constant*>(value);
602
- value = new (ctx.mem) String_Constant(s->path(),
603
- s->position(),
604
- s->value());
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->path(),
629
- t->position(),
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->path(),
636
- t->position(),
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->path(),
643
- t->position(),
644
- atof(num.c_str()),
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->path(),
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->path(),
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->path(),
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
- string chunk((*s)[i]->perform(this)->perform(&to_string));
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
- return new (ctx.mem) String_Constant(s->path(),
719
- s->position(),
720
- acc);
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->path(s->path());
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->path(),
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->path(),
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->path(),
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->path(),
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->path(),
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->path(),
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->path(), a->position());
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->path(), lhs->position());
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->path(), l->position());
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->path(), b->position(), "Infinity");
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->path(), r->position());
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("cannot add or subtract numbers with incompatible units", l->path(), l->position());
1049
+ error("Incompatible units: '"+r_unit+"' and '"+l_unit+"'.", l->pstate());
950
1050
  }
951
1051
  Number* v = new (ctx.mem) Number(*l);
952
- v->position(b->position());
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->path(),
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() ? r->perform(&to_string) :
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->path(),
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->path(), r->position());
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->path(), r->position());
1025
- return new (ctx.mem) Color(l->path(),
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->path(), r->position());
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->path(), r->position());
1140
+ error("division by zero", r->pstate());
1043
1141
  }
1044
- return new (ctx.mem) Color(l->path(),
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)->needs_unquoting();
1062
- bool r_str_quoted = ((Sass::String*)rhs) && ((Sass::String*)rhs)->needs_unquoting();
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->path(), lhs->position());
1084
- if (op == Binary_Expression::MOD) error("invalid operands for modulo", lhs->path(), lhs->position());
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->path(), lhs->position());
1092
- if (rtype == Expression::NULL_VAL) error("invalid null operation: \""+quote(unquote(lstr), '"')+" plus null\".", lhs->path(), lhs->position());
1093
- char q = '\0';
1094
- if (lstr[0] == '"' || lstr[0] == '\'') q = lstr[0];
1095
- else if (rstr[0] == '"' || rstr[0] == '\'') q = rstr[0];
1096
- string result(unquote(lstr) + sep + unquote(rstr));
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, string path, Position position)
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(path, position, !!sass_boolean_get_value(v));
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(path, position, sass_number_get_value(v), sass_number_get_unit(v));
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(path, position, sass_color_get_r(v), sass_color_get_g(v), sass_color_get_b(v), sass_color_get_a(v));
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(path, position, sass_string_get_value(v));
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(path, position, sass_list_get_length(v), sass_list_get_separator(v) == SASS_COMMA ? List::COMMA : List::SPACE);
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, path, position);
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(path, position);
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, path, position),
1132
- cval_to_astnode(sass_map_get_value(v, i), ctx, backtrace, path, position));
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(path, position);
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)), path, position, backtrace);
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)), path, position, backtrace);
1235
+ error("Warning in C function: " + string(sass_warning_get_message(v)), pstate, backtrace);
1144
1236
  } break;
1145
1237
  }
1146
1238
  return e;