sassc 1.7.1 → 1.8.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/ext/libsass/.gitignore +10 -6
  4. data/ext/libsass/.travis.yml +4 -1
  5. data/ext/libsass/GNUmakefile.am +88 -0
  6. data/ext/libsass/Makefile +157 -76
  7. data/ext/libsass/Makefile.conf +47 -0
  8. data/ext/libsass/Readme.md +13 -14
  9. data/ext/libsass/appveyor.yml +25 -41
  10. data/ext/libsass/configure.ac +20 -7
  11. data/ext/libsass/contrib/plugin.cpp +1 -1
  12. data/ext/libsass/include/sass.h +15 -0
  13. data/ext/libsass/{sass.h → include/sass/base.h} +17 -9
  14. data/ext/libsass/{sass_context.h → include/sass/context.h} +3 -1
  15. data/ext/libsass/{sass_functions.h → include/sass/functions.h} +4 -4
  16. data/ext/libsass/{sass_interface.h → include/sass/interface.h} +5 -2
  17. data/ext/libsass/{sass_values.h → include/sass/values.h} +15 -1
  18. data/ext/libsass/{sass_version.h → include/sass/version.h} +0 -0
  19. data/ext/libsass/{sass_version.h.in → include/sass/version.h.in} +0 -0
  20. data/ext/libsass/{sass2scss.h → include/sass2scss.h} +6 -7
  21. data/ext/libsass/m4/m4-ax_cxx_compile_stdcxx_11.m4 +167 -0
  22. data/ext/libsass/script/ci-build-libsass +67 -23
  23. data/ext/libsass/src/GNUmakefile.am +54 -0
  24. data/ext/libsass/src/ast.cpp +2029 -0
  25. data/ext/libsass/{ast.hpp → src/ast.hpp} +832 -660
  26. data/ext/libsass/src/ast_def_macros.hpp +47 -0
  27. data/ext/libsass/src/ast_factory.hpp +93 -0
  28. data/ext/libsass/{ast_fwd_decl.hpp → src/ast_fwd_decl.hpp} +9 -4
  29. data/ext/libsass/{b64 → src/b64}/cencode.h +1 -1
  30. data/ext/libsass/{b64 → src/b64}/encode.h +0 -0
  31. data/ext/libsass/{backtrace.hpp → src/backtrace.hpp} +9 -10
  32. data/ext/libsass/{base64vlq.cpp → src/base64vlq.cpp} +2 -2
  33. data/ext/libsass/{base64vlq.hpp → src/base64vlq.hpp} +1 -2
  34. data/ext/libsass/{bind.cpp → src/bind.cpp} +96 -59
  35. data/ext/libsass/{bind.hpp → src/bind.hpp} +1 -1
  36. data/ext/libsass/src/c99func.c +54 -0
  37. data/ext/libsass/{cencode.c → src/cencode.c} +5 -5
  38. data/ext/libsass/src/color_maps.cpp +643 -0
  39. data/ext/libsass/src/color_maps.hpp +333 -0
  40. data/ext/libsass/{constants.cpp → src/constants.cpp} +10 -1
  41. data/ext/libsass/{constants.hpp → src/constants.hpp} +7 -0
  42. data/ext/libsass/{context.cpp → src/context.cpp} +152 -122
  43. data/ext/libsass/src/context.hpp +150 -0
  44. data/ext/libsass/{cssize.cpp → src/cssize.cpp} +123 -109
  45. data/ext/libsass/{cssize.hpp → src/cssize.hpp} +9 -13
  46. data/ext/libsass/{debug.hpp → src/debug.hpp} +9 -9
  47. data/ext/libsass/src/debugger.hpp +683 -0
  48. data/ext/libsass/{emitter.cpp → src/emitter.cpp} +13 -13
  49. data/ext/libsass/{emitter.hpp → src/emitter.hpp} +10 -11
  50. data/ext/libsass/src/environment.cpp +184 -0
  51. data/ext/libsass/src/environment.hpp +92 -0
  52. data/ext/libsass/src/error_handling.cpp +46 -0
  53. data/ext/libsass/src/error_handling.hpp +34 -0
  54. data/ext/libsass/src/eval.cpp +1462 -0
  55. data/ext/libsass/src/eval.hpp +107 -0
  56. data/ext/libsass/src/expand.cpp +653 -0
  57. data/ext/libsass/{expand.hpp → src/expand.hpp} +17 -16
  58. data/ext/libsass/{extend.cpp → src/extend.cpp} +198 -139
  59. data/ext/libsass/{extend.hpp → src/extend.hpp} +7 -8
  60. data/ext/libsass/{file.cpp → src/file.cpp} +103 -57
  61. data/ext/libsass/{file.hpp → src/file.hpp} +23 -14
  62. data/ext/libsass/{functions.cpp → src/functions.cpp} +642 -333
  63. data/ext/libsass/{functions.hpp → src/functions.hpp} +17 -4
  64. data/ext/libsass/{inspect.cpp → src/inspect.cpp} +147 -260
  65. data/ext/libsass/{inspect.hpp → src/inspect.hpp} +7 -7
  66. data/ext/libsass/{json.cpp → src/json.cpp} +33 -43
  67. data/ext/libsass/{json.hpp → src/json.hpp} +1 -1
  68. data/ext/libsass/{kwd_arg_macros.hpp → src/kwd_arg_macros.hpp} +0 -0
  69. data/ext/libsass/{lexer.cpp → src/lexer.cpp} +28 -0
  70. data/ext/libsass/{lexer.hpp → src/lexer.hpp} +25 -10
  71. data/ext/libsass/{listize.cpp → src/listize.cpp} +17 -13
  72. data/ext/libsass/{listize.hpp → src/listize.hpp} +0 -2
  73. data/ext/libsass/{mapping.hpp → src/mapping.hpp} +0 -0
  74. data/ext/libsass/src/memory_manager.cpp +76 -0
  75. data/ext/libsass/src/memory_manager.hpp +48 -0
  76. data/ext/libsass/{node.cpp → src/node.cpp} +89 -18
  77. data/ext/libsass/{node.hpp → src/node.hpp} +5 -6
  78. data/ext/libsass/{operation.hpp → src/operation.hpp} +18 -12
  79. data/ext/libsass/{output.cpp → src/output.cpp} +47 -55
  80. data/ext/libsass/{output.hpp → src/output.hpp} +5 -4
  81. data/ext/libsass/src/parser.cpp +2529 -0
  82. data/ext/libsass/{parser.hpp → src/parser.hpp} +84 -60
  83. data/ext/libsass/{paths.hpp → src/paths.hpp} +10 -13
  84. data/ext/libsass/{plugins.cpp → src/plugins.cpp} +14 -17
  85. data/ext/libsass/{plugins.hpp → src/plugins.hpp} +10 -11
  86. data/ext/libsass/{position.cpp → src/position.cpp} +5 -6
  87. data/ext/libsass/{position.hpp → src/position.hpp} +19 -22
  88. data/ext/libsass/{prelexer.cpp → src/prelexer.cpp} +401 -53
  89. data/ext/libsass/{prelexer.hpp → src/prelexer.hpp} +50 -10
  90. data/ext/libsass/{remove_placeholders.cpp → src/remove_placeholders.cpp} +12 -16
  91. data/ext/libsass/{remove_placeholders.hpp → src/remove_placeholders.hpp} +1 -7
  92. data/ext/libsass/{sass.cpp → src/sass.cpp} +3 -5
  93. data/ext/libsass/{sass2scss.cpp → src/sass2scss.cpp} +51 -46
  94. data/ext/libsass/{sass_context.cpp → src/sass_context.cpp} +114 -112
  95. data/ext/libsass/{sass_functions.cpp → src/sass_functions.cpp} +11 -18
  96. data/ext/libsass/{sass_interface.cpp → src/sass_interface.cpp} +44 -81
  97. data/ext/libsass/{sass_util.cpp → src/sass_util.cpp} +26 -8
  98. data/ext/libsass/{sass_util.hpp → src/sass_util.hpp} +14 -18
  99. data/ext/libsass/{sass_values.cpp → src/sass_values.cpp} +91 -20
  100. data/ext/libsass/{source_map.cpp → src/source_map.cpp} +13 -13
  101. data/ext/libsass/{source_map.hpp → src/source_map.hpp} +9 -9
  102. data/ext/libsass/{subset_map.hpp → src/subset_map.hpp} +29 -31
  103. data/ext/libsass/{support → src/support}/libsass.pc.in +0 -0
  104. data/ext/libsass/src/to_c.cpp +73 -0
  105. data/ext/libsass/src/to_c.hpp +41 -0
  106. data/ext/libsass/src/to_string.cpp +47 -0
  107. data/ext/libsass/{to_string.hpp → src/to_string.hpp} +9 -7
  108. data/ext/libsass/src/to_value.cpp +109 -0
  109. data/ext/libsass/src/to_value.hpp +50 -0
  110. data/ext/libsass/{units.cpp → src/units.cpp} +56 -51
  111. data/ext/libsass/{units.hpp → src/units.hpp} +8 -9
  112. data/ext/libsass/{utf8.h → src/utf8.h} +0 -0
  113. data/ext/libsass/{utf8 → src/utf8}/checked.h +0 -0
  114. data/ext/libsass/{utf8 → src/utf8}/core.h +12 -12
  115. data/ext/libsass/{utf8 → src/utf8}/unchecked.h +0 -0
  116. data/ext/libsass/{utf8_string.cpp → src/utf8_string.cpp} +0 -0
  117. data/ext/libsass/{utf8_string.hpp → src/utf8_string.hpp} +6 -6
  118. data/ext/libsass/{util.cpp → src/util.cpp} +144 -86
  119. data/ext/libsass/src/util.hpp +59 -0
  120. data/ext/libsass/src/values.cpp +137 -0
  121. data/ext/libsass/src/values.hpp +12 -0
  122. data/ext/libsass/test/test_node.cpp +33 -33
  123. data/ext/libsass/test/test_paths.cpp +5 -6
  124. data/ext/libsass/test/test_selector_difference.cpp +4 -5
  125. data/ext/libsass/test/test_specificity.cpp +4 -5
  126. data/ext/libsass/test/test_subset_map.cpp +91 -91
  127. data/ext/libsass/test/test_superselector.cpp +11 -11
  128. data/ext/libsass/test/test_unification.cpp +4 -4
  129. data/ext/libsass/win/libsass.targets +101 -0
  130. data/ext/libsass/win/libsass.vcxproj +45 -127
  131. data/ext/libsass/win/libsass.vcxproj.filters +303 -0
  132. data/lib/sassc/import_handler.rb +1 -1
  133. data/lib/sassc/native/native_functions_api.rb +3 -3
  134. data/lib/sassc/version.rb +1 -1
  135. data/test/custom_importer_test.rb +1 -4
  136. data/test/functions_test.rb +3 -2
  137. data/test/native_test.rb +4 -3
  138. metadata +117 -110
  139. data/ext/libsass/Makefile.am +0 -146
  140. data/ext/libsass/ast.cpp +0 -945
  141. data/ext/libsass/ast_def_macros.hpp +0 -21
  142. data/ext/libsass/ast_factory.hpp +0 -92
  143. data/ext/libsass/color_names.hpp +0 -327
  144. data/ext/libsass/context.hpp +0 -157
  145. data/ext/libsass/contextualize.cpp +0 -148
  146. data/ext/libsass/contextualize.hpp +0 -46
  147. data/ext/libsass/contextualize_eval.cpp +0 -93
  148. data/ext/libsass/contextualize_eval.hpp +0 -44
  149. data/ext/libsass/debugger.hpp +0 -558
  150. data/ext/libsass/environment.hpp +0 -163
  151. data/ext/libsass/error_handling.cpp +0 -35
  152. data/ext/libsass/error_handling.hpp +0 -32
  153. data/ext/libsass/eval.cpp +0 -1392
  154. data/ext/libsass/eval.hpp +0 -88
  155. data/ext/libsass/expand.cpp +0 -575
  156. data/ext/libsass/memory_manager.hpp +0 -57
  157. data/ext/libsass/parser.cpp +0 -2403
  158. data/ext/libsass/posix/getopt.c +0 -562
  159. data/ext/libsass/posix/getopt.h +0 -95
  160. data/ext/libsass/to_c.cpp +0 -61
  161. data/ext/libsass/to_c.hpp +0 -44
  162. data/ext/libsass/to_string.cpp +0 -34
  163. data/ext/libsass/util.hpp +0 -54
  164. data/ext/libsass/win/libsass.filters +0 -312
@@ -47,17 +47,27 @@
47
47
  #include "source_map.hpp"
48
48
 
49
49
  #include "sass.h"
50
- #include "sass_values.h"
51
- #include "sass_functions.h"
52
50
 
53
51
  namespace Sass {
54
- using namespace std;
52
+
53
+ const double NUMBER_EPSILON = 0.00000000000001;
54
+
55
+ // from boost (functional/hash):
56
+ // http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html
57
+ // Boost Software License - Version 1.0
58
+ // http://www.boost.org/users/license.html
59
+ template <typename T>
60
+ void hash_combine (std::size_t& seed, const T& val)
61
+ {
62
+ seed ^= std::hash<T>()(val) + 0x9e3779b9
63
+ + (seed<<6) + (seed>>2);
64
+ }
55
65
 
56
66
  //////////////////////////////////////////////////////////
57
67
  // Abstract base class for all abstract syntax tree nodes.
58
68
  //////////////////////////////////////////////////////////
59
- class AST_Node {
60
- ADD_PROPERTY(ParserState, pstate);
69
+ class AST_Node : public Memory_Object {
70
+ ADD_PROPERTY(ParserState, pstate)
61
71
  public:
62
72
  AST_Node(ParserState pstate)
63
73
  : pstate_(pstate)
@@ -65,9 +75,11 @@ namespace Sass {
65
75
  virtual ~AST_Node() = 0;
66
76
  // virtual Block* block() { return 0; }
67
77
  public:
68
- Offset off() { return pstate(); };
69
- Position pos() { return pstate(); };
70
- ATTACH_OPERATIONS();
78
+ void update_pstate(const ParserState& pstate);
79
+ public:
80
+ Offset off() { return pstate(); }
81
+ Position pos() { return pstate(); }
82
+ ATTACH_OPERATIONS()
71
83
  };
72
84
  inline AST_Node::~AST_Node() { }
73
85
 
@@ -89,14 +101,16 @@ namespace Sass {
89
101
  MAP,
90
102
  SELECTOR,
91
103
  NULL_VAL,
104
+ C_WARNING,
105
+ C_ERROR,
92
106
  NUM_TYPES
93
107
  };
94
108
  private:
95
109
  // expressions in some contexts shouldn't be evaluated
96
- ADD_PROPERTY(bool, is_delayed);
97
- ADD_PROPERTY(bool, is_expanded);
98
- ADD_PROPERTY(bool, is_interpolant);
99
- ADD_PROPERTY(Concrete_Type, concrete_type);
110
+ ADD_PROPERTY(bool, is_delayed)
111
+ ADD_PROPERTY(bool, is_expanded)
112
+ ADD_PROPERTY(bool, is_interpolant)
113
+ ADD_PROPERTY(Concrete_Type, concrete_type)
100
114
  public:
101
115
  Expression(ParserState pstate,
102
116
  bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE)
@@ -107,21 +121,33 @@ namespace Sass {
107
121
  concrete_type_(ct)
108
122
  { }
109
123
  virtual operator bool() { return true; }
110
- virtual ~Expression() { };
111
- virtual string type() { return ""; /* TODO: raise an error? */ }
112
- virtual bool is_invisible() { return false; }
113
- static string type_name() { return ""; }
124
+ virtual ~Expression() { }
125
+ virtual std::string type() { return ""; /* TODO: raise an error? */ }
126
+ virtual bool is_invisible() const { return false; }
127
+ static std::string type_name() { return ""; }
114
128
  virtual bool is_false() { return false; }
115
- virtual bool operator==( Expression& rhs) const { return false; }
129
+ virtual bool operator== (const Expression& rhs) const { return false; }
116
130
  virtual void set_delayed(bool delayed) { is_delayed(delayed); }
117
131
  virtual size_t hash() { return 0; }
118
132
  };
119
- }
120
133
 
134
+ //////////////////////////////////////////////////////////////////////
135
+ // base class for values that support operations
136
+ //////////////////////////////////////////////////////////////////////
137
+ class Value : public Expression {
138
+ public:
139
+ Value(ParserState pstate,
140
+ bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE)
141
+ : Expression(pstate, d, e, i, ct)
142
+ { }
143
+ virtual bool operator== (const Expression& rhs) const = 0;
144
+ virtual std::string to_string(bool compressed = false, int precision = 5) const = 0;
145
+ };
146
+ }
121
147
 
122
- /////////////////////////////////////////////////////////////////////////////
123
- // Hash method specializations for unordered_map to work with Sass::Expression
124
- /////////////////////////////////////////////////////////////////////////////
148
+ /////////////////////////////////////////////////////////////////////////////////////
149
+ // Hash method specializations for std::unordered_map to work with Sass::Expression
150
+ /////////////////////////////////////////////////////////////////////////////////////
125
151
 
126
152
  namespace std {
127
153
  template<>
@@ -137,13 +163,12 @@ namespace std {
137
163
  {
138
164
  bool operator()( Sass::Expression* lhs, Sass::Expression* rhs) const
139
165
  {
140
- return *lhs == *rhs;
166
+ return lhs->hash() == rhs->hash();
141
167
  }
142
168
  };
143
169
  }
144
170
 
145
171
  namespace Sass {
146
- using namespace std;
147
172
 
148
173
  /////////////////////////////////////////////////////////////////////////////
149
174
  // Mixin class for AST nodes that should behave like vectors. Uses the
@@ -152,22 +177,24 @@ namespace Sass {
152
177
  /////////////////////////////////////////////////////////////////////////////
153
178
  template <typename T>
154
179
  class Vectorized {
155
- vector<T> elements_;
180
+ std::vector<T> elements_;
156
181
  protected:
157
182
  size_t hash_;
158
183
  void reset_hash() { hash_ = 0; }
159
184
  virtual void adjust_after_pushing(T element) { }
160
185
  public:
161
- Vectorized(size_t s = 0) : elements_(vector<T>())
186
+ Vectorized(size_t s = 0) : elements_(std::vector<T>())
162
187
  { elements_.reserve(s); }
163
188
  virtual ~Vectorized() = 0;
164
189
  size_t length() const { return elements_.size(); }
165
190
  bool empty() const { return elements_.empty(); }
166
191
  T last() { return elements_.back(); }
192
+ T first() { return elements_.front(); }
167
193
  T& operator[](size_t i) { return elements_[i]; }
168
194
  const T& operator[](size_t i) const { return elements_[i]; }
169
195
  Vectorized& operator<<(T element)
170
196
  {
197
+ if (!element) return *this;
171
198
  reset_hash();
172
199
  elements_.push_back(element);
173
200
  adjust_after_pushing(element);
@@ -183,21 +210,29 @@ namespace Sass {
183
210
  elements_.insert(elements_.begin(), element);
184
211
  return *this;
185
212
  }
186
- vector<T>& elements() { return elements_; }
187
- const vector<T>& elements() const { return elements_; }
188
- vector<T>& elements(vector<T>& e) { elements_ = e; return elements_; }
213
+ std::vector<T>& elements() { return elements_; }
214
+ const std::vector<T>& elements() const { return elements_; }
215
+ std::vector<T>& elements(std::vector<T>& e) { elements_ = e; return elements_; }
216
+
217
+ typename std::vector<T>::iterator end() { return elements_.end(); }
218
+ typename std::vector<T>::iterator begin() { return elements_.begin(); }
219
+ typename std::vector<T>::const_iterator end() const { return elements_.end(); }
220
+ typename std::vector<T>::const_iterator begin() const { return elements_.begin(); }
221
+ typename std::vector<T>::iterator erase(typename std::vector<T>::iterator el) { return elements_.erase(el); }
222
+ typename std::vector<T>::const_iterator erase(typename std::vector<T>::const_iterator el) { return elements_.erase(el); }
223
+
189
224
  };
190
225
  template <typename T>
191
226
  inline Vectorized<T>::~Vectorized() { }
192
227
 
193
228
  /////////////////////////////////////////////////////////////////////////////
194
229
  // Mixin class for AST nodes that should behave like a hash table. Uses an
195
- // extra <vector> internally to maintain insertion order for interation.
230
+ // extra <std::vector> internally to maintain insertion order for interation.
196
231
  /////////////////////////////////////////////////////////////////////////////
197
232
  class Hashed {
198
233
  private:
199
- unordered_map<Expression*, Expression*> elements_;
200
- vector<Expression*> list_;
234
+ std::unordered_map<Expression*, Expression*> elements_;
235
+ std::vector<Expression*> list_;
201
236
  protected:
202
237
  size_t hash_;
203
238
  Expression* duplicate_key_;
@@ -205,7 +240,7 @@ namespace Sass {
205
240
  void reset_duplicate_key() { duplicate_key_ = 0; }
206
241
  virtual void adjust_after_pushing(std::pair<Expression*, Expression*> p) { }
207
242
  public:
208
- Hashed(size_t s = 0) : elements_(unordered_map<Expression*, Expression*>(s)), list_(vector<Expression*>())
243
+ Hashed(size_t s = 0) : elements_(std::unordered_map<Expression*, Expression*>(s)), list_(std::vector<Expression*>())
209
244
  { elements_.reserve(s); list_.reserve(s); reset_duplicate_key(); }
210
245
  virtual ~Hashed();
211
246
  size_t length() const { return list_.size(); }
@@ -214,8 +249,8 @@ namespace Sass {
214
249
  Expression* at(Expression* k) const;
215
250
  bool has_duplicate_key() const { return duplicate_key_ != 0; }
216
251
  Expression* get_duplicate_key() const { return duplicate_key_; }
217
- const unordered_map<Expression*, Expression*> elements() { return elements_; }
218
- Hashed& operator<<(pair<Expression*, Expression*> p)
252
+ const std::unordered_map<Expression*, Expression*> elements() { return elements_; }
253
+ Hashed& operator<<(std::pair<Expression*, Expression*> p)
219
254
  {
220
255
  reset_hash();
221
256
 
@@ -236,14 +271,20 @@ namespace Sass {
236
271
  }
237
272
 
238
273
  for (auto key : h->keys()) {
239
- *this << make_pair(key, h->at(key));
274
+ *this << std::make_pair(key, h->at(key));
240
275
  }
241
276
 
242
277
  reset_duplicate_key();
243
278
  return *this;
244
279
  }
245
- const unordered_map<Expression*, Expression*>& pairs() const { return elements_; }
246
- const vector<Expression*>& keys() const { return list_; }
280
+ const std::unordered_map<Expression*, Expression*>& pairs() const { return elements_; }
281
+ const std::vector<Expression*>& keys() const { return list_; }
282
+
283
+ std::unordered_map<Expression*, Expression*>::iterator end() { return elements_.end(); }
284
+ std::unordered_map<Expression*, Expression*>::iterator begin() { return elements_.begin(); }
285
+ std::unordered_map<Expression*, Expression*>::const_iterator end() const { return elements_.end(); }
286
+ std::unordered_map<Expression*, Expression*>::const_iterator begin() const { return elements_.begin(); }
287
+
247
288
  };
248
289
  inline Hashed::~Hashed() { }
249
290
 
@@ -260,16 +301,31 @@ namespace Sass {
260
301
  RULESET,
261
302
  MEDIA,
262
303
  DIRECTIVE,
263
- FEATURE,
304
+ SUPPORTS,
264
305
  ATROOT,
265
306
  BUBBLE,
266
- KEYFRAMERULE
307
+ CONTENT,
308
+ KEYFRAMERULE,
309
+ DECLARATION,
310
+ ASSIGNMENT,
311
+ IMPORT_STUB,
312
+ IMPORT,
313
+ COMMENT,
314
+ WARNING,
315
+ RETURN,
316
+ EXTEND,
317
+ ERROR,
318
+ DEBUGSTMT,
319
+ WHILE,
320
+ EACH,
321
+ FOR,
322
+ IF
267
323
  };
268
324
  private:
269
- ADD_PROPERTY(Block*, block);
270
- ADD_PROPERTY(Statement_Type, statement_type);
271
- ADD_PROPERTY(size_t, tabs);
272
- ADD_PROPERTY(bool, group_end);
325
+ ADD_PROPERTY(Block*, block)
326
+ ADD_PROPERTY(Statement_Type, statement_type)
327
+ ADD_PROPERTY(size_t, tabs)
328
+ ADD_PROPERTY(bool, group_end)
273
329
  public:
274
330
  Statement(ParserState pstate, Statement_Type st = NONE, size_t t = 0)
275
331
  : AST_Node(pstate), statement_type_(st), tabs_(t), group_end_(false)
@@ -277,9 +333,13 @@ namespace Sass {
277
333
  virtual ~Statement() = 0;
278
334
  // needed for rearranging nested rulesets during CSS emission
279
335
  virtual bool is_hoistable() { return false; }
280
- virtual bool is_invisible() { return false; }
336
+ virtual bool is_invisible() const { return false; }
281
337
  virtual bool bubbles() { return false; }
282
338
  virtual Block* block() { return 0; }
339
+ virtual bool has_content()
340
+ {
341
+ return statement_type_ == CONTENT;
342
+ }
283
343
  };
284
344
  inline Statement::~Statement() { }
285
345
 
@@ -287,35 +347,50 @@ namespace Sass {
287
347
  // Blocks of statements.
288
348
  ////////////////////////
289
349
  class Block : public Statement, public Vectorized<Statement*> {
290
- ADD_PROPERTY(bool, is_root);
350
+ ADD_PROPERTY(bool, is_root)
351
+ ADD_PROPERTY(bool, is_at_root);
291
352
  // needed for properly formatted CSS emission
292
- ADD_PROPERTY(bool, has_hoistable);
293
- ADD_PROPERTY(bool, has_non_hoistable);
353
+ ADD_PROPERTY(bool, has_hoistable)
354
+ ADD_PROPERTY(bool, has_non_hoistable)
294
355
  protected:
295
356
  void adjust_after_pushing(Statement* s)
296
357
  {
297
358
  if (s->is_hoistable()) has_hoistable_ = true;
298
359
  else has_non_hoistable_ = true;
299
- };
360
+ }
300
361
  public:
301
362
  Block(ParserState pstate, size_t s = 0, bool r = false)
302
363
  : Statement(pstate),
303
364
  Vectorized<Statement*>(s),
304
- is_root_(r), has_hoistable_(false), has_non_hoistable_(false)
365
+ is_root_(r),
366
+ is_at_root_(false),
367
+ has_hoistable_(false),
368
+ has_non_hoistable_(false)
305
369
  { }
370
+ virtual bool has_content()
371
+ {
372
+ for (size_t i = 0, L = elements().size(); i < L; ++i) {
373
+ if (elements()[i]->has_content()) return true;
374
+ }
375
+ return Statement::has_content();
376
+ }
306
377
  Block* block() { return this; }
307
- ATTACH_OPERATIONS();
378
+ ATTACH_OPERATIONS()
308
379
  };
309
380
 
310
381
  ////////////////////////////////////////////////////////////////////////
311
382
  // Abstract base class for statements that contain blocks of statements.
312
383
  ////////////////////////////////////////////////////////////////////////
313
384
  class Has_Block : public Statement {
314
- ADD_PROPERTY(Block*, block);
385
+ ADD_PROPERTY(Block*, block)
315
386
  public:
316
387
  Has_Block(ParserState pstate, Block* b)
317
388
  : Statement(pstate), block_(b)
318
389
  { }
390
+ virtual bool has_content()
391
+ {
392
+ return (block_ && block_->has_content()) || Statement::has_content();
393
+ }
319
394
  virtual ~Has_Block() = 0;
320
395
  };
321
396
  inline Has_Block::~Has_Block() { }
@@ -325,80 +400,61 @@ namespace Sass {
325
400
  // of style declarations.
326
401
  /////////////////////////////////////////////////////////////////////////////
327
402
  class Ruleset : public Has_Block {
328
- ADD_PROPERTY(Selector*, selector);
403
+ ADD_PROPERTY(Selector*, selector)
404
+ ADD_PROPERTY(bool, at_root);
405
+ ADD_PROPERTY(bool, is_root);
329
406
  public:
330
- Ruleset(ParserState pstate, Selector* s, Block* b)
331
- : Has_Block(pstate, b), selector_(s)
407
+ Ruleset(ParserState pstate, Selector* s = 0, Block* b = 0)
408
+ : Has_Block(pstate, b), selector_(s), at_root_(false), is_root_(false)
332
409
  { statement_type(RULESET); }
333
- bool is_invisible();
410
+ bool is_invisible() const;
334
411
  // nested rulesets need to be hoisted out of their enclosing blocks
335
412
  bool is_hoistable() { return true; }
336
- ATTACH_OPERATIONS();
413
+ ATTACH_OPERATIONS()
337
414
  };
338
415
 
339
416
  /////////////////////////////////////////////////////////
340
417
  // Nested declaration sets (i.e., namespaced properties).
341
418
  /////////////////////////////////////////////////////////
342
419
  class Propset : public Has_Block {
343
- ADD_PROPERTY(String*, property_fragment);
420
+ ADD_PROPERTY(String*, property_fragment)
344
421
  public:
345
422
  Propset(ParserState pstate, String* pf, Block* b = 0)
346
423
  : Has_Block(pstate, b), property_fragment_(pf)
347
424
  { }
348
- ATTACH_OPERATIONS();
425
+ ATTACH_OPERATIONS()
349
426
  };
350
427
 
351
428
  /////////////////
352
429
  // Bubble.
353
430
  /////////////////
354
431
  class Bubble : public Statement {
355
- ADD_PROPERTY(Statement*, node);
356
- ADD_PROPERTY(bool, group_end);
432
+ ADD_PROPERTY(Statement*, node)
433
+ ADD_PROPERTY(bool, group_end)
357
434
  public:
358
435
  Bubble(ParserState pstate, Statement* n, Statement* g = 0, size_t t = 0)
359
436
  : Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == 0)
360
437
  { }
361
438
  bool bubbles() { return true; }
362
- ATTACH_OPERATIONS();
439
+ ATTACH_OPERATIONS()
363
440
  };
364
441
 
365
442
  /////////////////
366
443
  // Media queries.
367
444
  /////////////////
368
445
  class Media_Block : public Has_Block {
369
- ADD_PROPERTY(List*, media_queries);
370
- ADD_PROPERTY(Selector*, selector);
446
+ ADD_PROPERTY(List*, media_queries)
371
447
  public:
372
448
  Media_Block(ParserState pstate, List* mqs, Block* b)
373
- : Has_Block(pstate, b), media_queries_(mqs), selector_(0)
449
+ : Has_Block(pstate, b), media_queries_(mqs)
374
450
  { statement_type(MEDIA); }
375
451
  Media_Block(ParserState pstate, List* mqs, Block* b, Selector* s)
376
- : Has_Block(pstate, b), media_queries_(mqs), selector_(s)
452
+ : Has_Block(pstate, b), media_queries_(mqs)
377
453
  { statement_type(MEDIA); }
378
454
  bool bubbles() { return true; }
379
455
  bool is_hoistable() { return true; }
380
- bool is_invisible() {
381
- bool is_invisible = true;
382
- for (size_t i = 0, L = block()->length(); i < L && is_invisible; i++)
383
- is_invisible &= (*block())[i]->is_invisible();
384
- return is_invisible;
385
- }
386
- ATTACH_OPERATIONS();
387
- };
388
-
389
- ///////////////////
390
- // Feature queries.
391
- ///////////////////
392
- class Feature_Block : public Has_Block {
393
- ADD_PROPERTY(Feature_Query*, feature_queries);
394
- ADD_PROPERTY(Selector*, selector);
395
- public:
396
- Feature_Block(ParserState pstate, Feature_Query* fqs, Block* b)
397
- : Has_Block(pstate, b), feature_queries_(fqs), selector_(0)
398
- { statement_type(FEATURE); }
399
- bool is_hoistable() { return true; }
400
- bool bubbles() { return true; }
401
- ATTACH_OPERATIONS();
456
+ bool is_invisible() const;
457
+ ATTACH_OPERATIONS()
402
458
  };
403
459
 
404
460
  ///////////////////////////////////////////////////////////////////////
@@ -406,12 +462,12 @@ namespace Sass {
406
462
  // optional statement block.
407
463
  ///////////////////////////////////////////////////////////////////////
408
464
  class At_Rule : public Has_Block {
409
- ADD_PROPERTY(string, keyword);
410
- ADD_PROPERTY(Selector*, selector);
411
- ADD_PROPERTY(Expression*, value);
465
+ ADD_PROPERTY(std::string, keyword)
466
+ ADD_PROPERTY(Selector*, selector)
467
+ ADD_PROPERTY(Expression*, value)
412
468
  public:
413
- At_Rule(ParserState pstate, string kwd, Selector* sel = 0, Block* b = 0)
414
- : Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(0) // set value manually if needed
469
+ At_Rule(ParserState pstate, std::string kwd, Selector* sel = 0, Block* b = 0, Expression* val = 0)
470
+ : Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed
415
471
  { statement_type(DIRECTIVE); }
416
472
  bool bubbles() { return is_keyframes() || is_media(); }
417
473
  bool is_media() {
@@ -426,52 +482,53 @@ namespace Sass {
426
482
  keyword_.compare("@-o-keyframes") == 0 ||
427
483
  keyword_.compare("@keyframes") == 0;
428
484
  }
429
- ATTACH_OPERATIONS();
485
+ ATTACH_OPERATIONS()
430
486
  };
431
487
 
432
488
  ///////////////////////////////////////////////////////////////////////
433
489
  // Keyframe-rules -- the child blocks of "@keyframes" nodes.
434
490
  ///////////////////////////////////////////////////////////////////////
435
491
  class Keyframe_Rule : public Has_Block {
436
- ADD_PROPERTY(Selector*, selector);
492
+ ADD_PROPERTY(Selector*, selector)
437
493
  public:
438
494
  Keyframe_Rule(ParserState pstate, Block* b)
439
495
  : Has_Block(pstate, b), selector_(0)
440
496
  { statement_type(KEYFRAMERULE); }
441
- ATTACH_OPERATIONS();
497
+ ATTACH_OPERATIONS()
442
498
  };
443
499
 
444
500
  ////////////////////////////////////////////////////////////////////////
445
501
  // Declarations -- style rules consisting of a property name and values.
446
502
  ////////////////////////////////////////////////////////////////////////
447
503
  class Declaration : public Statement {
448
- ADD_PROPERTY(String*, property);
449
- ADD_PROPERTY(Expression*, value);
450
- ADD_PROPERTY(bool, is_important);
504
+ ADD_PROPERTY(String*, property)
505
+ ADD_PROPERTY(Expression*, value)
506
+ ADD_PROPERTY(bool, is_important)
507
+ ADD_PROPERTY(bool, is_indented)
451
508
  public:
452
509
  Declaration(ParserState pstate,
453
510
  String* prop, Expression* val, bool i = false)
454
- : Statement(pstate), property_(prop), value_(val), is_important_(i)
455
- { }
456
- ATTACH_OPERATIONS();
511
+ : Statement(pstate), property_(prop), value_(val), is_important_(i), is_indented_(false)
512
+ { statement_type(DECLARATION); }
513
+ ATTACH_OPERATIONS()
457
514
  };
458
515
 
459
516
  /////////////////////////////////////
460
517
  // Assignments -- variable and value.
461
518
  /////////////////////////////////////
462
519
  class Assignment : public Statement {
463
- ADD_PROPERTY(string, variable);
464
- ADD_PROPERTY(Expression*, value);
465
- ADD_PROPERTY(bool, is_default);
466
- ADD_PROPERTY(bool, is_global);
520
+ ADD_PROPERTY(std::string, variable)
521
+ ADD_PROPERTY(Expression*, value)
522
+ ADD_PROPERTY(bool, is_default)
523
+ ADD_PROPERTY(bool, is_global)
467
524
  public:
468
525
  Assignment(ParserState pstate,
469
- string var, Expression* val,
526
+ std::string var, Expression* val,
470
527
  bool is_default = false,
471
528
  bool is_global = false)
472
529
  : Statement(pstate), variable_(var), value_(val), is_default_(is_default), is_global_(is_global)
473
- { }
474
- ATTACH_OPERATIONS();
530
+ { statement_type(ASSIGNMENT); }
531
+ ATTACH_OPERATIONS()
475
532
  };
476
533
 
477
534
  ////////////////////////////////////////////////////////////////////////////
@@ -479,154 +536,158 @@ namespace Sass {
479
536
  // necessary to store a list of each in an Import node.
480
537
  ////////////////////////////////////////////////////////////////////////////
481
538
  class Import : public Statement {
482
- vector<string> files_;
483
- vector<Expression*> urls_;
539
+ std::vector<std::string> files_;
540
+ std::vector<Expression*> urls_;
541
+ ADD_PROPERTY(List*, media_queries);
484
542
  public:
485
543
  Import(ParserState pstate)
486
544
  : Statement(pstate),
487
- files_(vector<string>()), urls_(vector<Expression*>())
488
- { }
489
- vector<string>& files() { return files_; }
490
- vector<Expression*>& urls() { return urls_; }
491
- ATTACH_OPERATIONS();
545
+ files_(std::vector<std::string>()),
546
+ urls_(std::vector<Expression*>()),
547
+ media_queries_(0)
548
+ { statement_type(IMPORT); }
549
+ std::vector<std::string>& files() { return files_; }
550
+ std::vector<Expression*>& urls() { return urls_; }
551
+ ATTACH_OPERATIONS()
492
552
  };
493
553
 
494
554
  class Import_Stub : public Statement {
495
- ADD_PROPERTY(string, file_name);
555
+ ADD_PROPERTY(std::string, file_name)
496
556
  public:
497
- Import_Stub(ParserState pstate, string f)
557
+ Import_Stub(ParserState pstate, std::string f)
498
558
  : Statement(pstate), file_name_(f)
499
- { }
500
- ATTACH_OPERATIONS();
559
+ { statement_type(IMPORT_STUB); }
560
+ ATTACH_OPERATIONS()
501
561
  };
502
562
 
503
563
  //////////////////////////////
504
564
  // The Sass `@warn` directive.
505
565
  //////////////////////////////
506
566
  class Warning : public Statement {
507
- ADD_PROPERTY(Expression*, message);
567
+ ADD_PROPERTY(Expression*, message)
508
568
  public:
509
569
  Warning(ParserState pstate, Expression* msg)
510
570
  : Statement(pstate), message_(msg)
511
- { }
512
- ATTACH_OPERATIONS();
571
+ { statement_type(WARNING); }
572
+ ATTACH_OPERATIONS()
513
573
  };
514
574
 
515
575
  ///////////////////////////////
516
576
  // The Sass `@error` directive.
517
577
  ///////////////////////////////
518
578
  class Error : public Statement {
519
- ADD_PROPERTY(Expression*, message);
579
+ ADD_PROPERTY(Expression*, message)
520
580
  public:
521
581
  Error(ParserState pstate, Expression* msg)
522
582
  : Statement(pstate), message_(msg)
523
- { }
524
- ATTACH_OPERATIONS();
583
+ { statement_type(ERROR); }
584
+ ATTACH_OPERATIONS()
525
585
  };
526
586
 
527
587
  ///////////////////////////////
528
588
  // The Sass `@debug` directive.
529
589
  ///////////////////////////////
530
590
  class Debug : public Statement {
531
- ADD_PROPERTY(Expression*, value);
591
+ ADD_PROPERTY(Expression*, value)
532
592
  public:
533
593
  Debug(ParserState pstate, Expression* val)
534
594
  : Statement(pstate), value_(val)
535
- { }
536
- ATTACH_OPERATIONS();
595
+ { statement_type(DEBUGSTMT); }
596
+ ATTACH_OPERATIONS()
537
597
  };
538
598
 
539
599
  ///////////////////////////////////////////
540
600
  // CSS comments. These may be interpolated.
541
601
  ///////////////////////////////////////////
542
602
  class Comment : public Statement {
543
- ADD_PROPERTY(String*, text);
544
- ADD_PROPERTY(bool, is_important);
603
+ ADD_PROPERTY(String*, text)
604
+ ADD_PROPERTY(bool, is_important)
545
605
  public:
546
606
  Comment(ParserState pstate, String* txt, bool is_important)
547
607
  : Statement(pstate), text_(txt), is_important_(is_important)
548
- { }
549
- ATTACH_OPERATIONS();
608
+ { statement_type(COMMENT); }
609
+ virtual bool is_invisible() const
610
+ { return is_important() == false; }
611
+ ATTACH_OPERATIONS()
550
612
  };
551
613
 
552
614
  ////////////////////////////////////
553
615
  // The Sass `@if` control directive.
554
616
  ////////////////////////////////////
555
- class If : public Statement {
556
- ADD_PROPERTY(Expression*, predicate);
557
- ADD_PROPERTY(Block*, consequent);
558
- ADD_PROPERTY(Block*, alternative);
617
+ class If : public Has_Block {
618
+ ADD_PROPERTY(Expression*, predicate)
619
+ ADD_PROPERTY(Block*, alternative)
559
620
  public:
560
621
  If(ParserState pstate, Expression* pred, Block* con, Block* alt = 0)
561
- : Statement(pstate), predicate_(pred), consequent_(con), alternative_(alt)
562
- { }
563
- ATTACH_OPERATIONS();
622
+ : Has_Block(pstate, con), predicate_(pred), alternative_(alt)
623
+ { statement_type(IF); }
624
+ ATTACH_OPERATIONS()
564
625
  };
565
626
 
566
627
  /////////////////////////////////////
567
628
  // The Sass `@for` control directive.
568
629
  /////////////////////////////////////
569
630
  class For : public Has_Block {
570
- ADD_PROPERTY(string, variable);
571
- ADD_PROPERTY(Expression*, lower_bound);
572
- ADD_PROPERTY(Expression*, upper_bound);
573
- ADD_PROPERTY(bool, is_inclusive);
631
+ ADD_PROPERTY(std::string, variable)
632
+ ADD_PROPERTY(Expression*, lower_bound)
633
+ ADD_PROPERTY(Expression*, upper_bound)
634
+ ADD_PROPERTY(bool, is_inclusive)
574
635
  public:
575
636
  For(ParserState pstate,
576
- string var, Expression* lo, Expression* hi, Block* b, bool inc)
637
+ std::string var, Expression* lo, Expression* hi, Block* b, bool inc)
577
638
  : Has_Block(pstate, b),
578
639
  variable_(var), lower_bound_(lo), upper_bound_(hi), is_inclusive_(inc)
579
- { }
580
- ATTACH_OPERATIONS();
640
+ { statement_type(FOR); }
641
+ ATTACH_OPERATIONS()
581
642
  };
582
643
 
583
644
  //////////////////////////////////////
584
645
  // The Sass `@each` control directive.
585
646
  //////////////////////////////////////
586
647
  class Each : public Has_Block {
587
- ADD_PROPERTY(vector<string>, variables);
588
- ADD_PROPERTY(Expression*, list);
648
+ ADD_PROPERTY(std::vector<std::string>, variables)
649
+ ADD_PROPERTY(Expression*, list)
589
650
  public:
590
- Each(ParserState pstate, vector<string> vars, Expression* lst, Block* b)
651
+ Each(ParserState pstate, std::vector<std::string> vars, Expression* lst, Block* b)
591
652
  : Has_Block(pstate, b), variables_(vars), list_(lst)
592
- { }
593
- ATTACH_OPERATIONS();
653
+ { statement_type(EACH); }
654
+ ATTACH_OPERATIONS()
594
655
  };
595
656
 
596
657
  ///////////////////////////////////////
597
658
  // The Sass `@while` control directive.
598
659
  ///////////////////////////////////////
599
660
  class While : public Has_Block {
600
- ADD_PROPERTY(Expression*, predicate);
661
+ ADD_PROPERTY(Expression*, predicate)
601
662
  public:
602
663
  While(ParserState pstate, Expression* pred, Block* b)
603
664
  : Has_Block(pstate, b), predicate_(pred)
604
- { }
605
- ATTACH_OPERATIONS();
665
+ { statement_type(WHILE); }
666
+ ATTACH_OPERATIONS()
606
667
  };
607
668
 
608
669
  /////////////////////////////////////////////////////////////
609
670
  // The @return directive for use inside SassScript functions.
610
671
  /////////////////////////////////////////////////////////////
611
672
  class Return : public Statement {
612
- ADD_PROPERTY(Expression*, value);
673
+ ADD_PROPERTY(Expression*, value)
613
674
  public:
614
675
  Return(ParserState pstate, Expression* val)
615
676
  : Statement(pstate), value_(val)
616
- { }
617
- ATTACH_OPERATIONS();
677
+ { statement_type(RETURN); }
678
+ ATTACH_OPERATIONS()
618
679
  };
619
680
 
620
681
  ////////////////////////////////
621
682
  // The Sass `@extend` directive.
622
683
  ////////////////////////////////
623
684
  class Extension : public Statement {
624
- ADD_PROPERTY(Selector*, selector);
685
+ ADD_PROPERTY(Selector*, selector)
625
686
  public:
626
687
  Extension(ParserState pstate, Selector* s)
627
688
  : Statement(pstate), selector_(s)
628
- { }
629
- ATTACH_OPERATIONS();
689
+ { statement_type(EXTEND); }
690
+ ATTACH_OPERATIONS()
630
691
  };
631
692
 
632
693
  /////////////////////////////////////////////////////////////////////////////
@@ -641,22 +702,20 @@ namespace Sass {
641
702
  class Definition : public Has_Block {
642
703
  public:
643
704
  enum Type { MIXIN, FUNCTION };
644
- ADD_PROPERTY(string, name);
645
- ADD_PROPERTY(Parameters*, parameters);
646
- ADD_PROPERTY(Env*, environment);
647
- ADD_PROPERTY(Type, type);
648
- ADD_PROPERTY(Native_Function, native_function);
649
- ADD_PROPERTY(Sass_Function_Entry, c_function);
650
- ADD_PROPERTY(void*, cookie);
651
- ADD_PROPERTY(Context*, ctx);
652
- ADD_PROPERTY(bool, is_overload_stub);
653
- ADD_PROPERTY(Signature, signature);
705
+ ADD_PROPERTY(std::string, name)
706
+ ADD_PROPERTY(Parameters*, parameters)
707
+ ADD_PROPERTY(Env*, environment)
708
+ ADD_PROPERTY(Type, type)
709
+ ADD_PROPERTY(Native_Function, native_function)
710
+ ADD_PROPERTY(Sass_Function_Entry, c_function)
711
+ ADD_PROPERTY(void*, cookie)
712
+ ADD_PROPERTY(bool, is_overload_stub)
713
+ ADD_PROPERTY(Signature, signature)
654
714
  public:
655
715
  Definition(ParserState pstate,
656
- string n,
716
+ std::string n,
657
717
  Parameters* params,
658
718
  Block* b,
659
- Context* ctx,
660
719
  Type t)
661
720
  : Has_Block(pstate, b),
662
721
  name_(n),
@@ -666,16 +725,14 @@ namespace Sass {
666
725
  native_function_(0),
667
726
  c_function_(0),
668
727
  cookie_(0),
669
- ctx_(ctx),
670
728
  is_overload_stub_(false),
671
729
  signature_(0)
672
730
  { }
673
731
  Definition(ParserState pstate,
674
732
  Signature sig,
675
- string n,
733
+ std::string n,
676
734
  Parameters* params,
677
735
  Native_Function func_ptr,
678
- Context* ctx,
679
736
  bool overload_stub = false)
680
737
  : Has_Block(pstate, 0),
681
738
  name_(n),
@@ -685,16 +742,14 @@ namespace Sass {
685
742
  native_function_(func_ptr),
686
743
  c_function_(0),
687
744
  cookie_(0),
688
- ctx_(ctx),
689
745
  is_overload_stub_(overload_stub),
690
746
  signature_(sig)
691
747
  { }
692
748
  Definition(ParserState pstate,
693
749
  Signature sig,
694
- string n,
750
+ std::string n,
695
751
  Parameters* params,
696
752
  Sass_Function_Entry c_func,
697
- Context* ctx,
698
753
  bool whatever,
699
754
  bool whatever2)
700
755
  : Has_Block(pstate, 0),
@@ -705,24 +760,23 @@ namespace Sass {
705
760
  native_function_(0),
706
761
  c_function_(c_func),
707
762
  cookie_(sass_function_get_cookie(c_func)),
708
- ctx_(ctx),
709
763
  is_overload_stub_(false),
710
764
  signature_(sig)
711
765
  { }
712
- ATTACH_OPERATIONS();
766
+ ATTACH_OPERATIONS()
713
767
  };
714
768
 
715
769
  //////////////////////////////////////
716
770
  // Mixin calls (i.e., `@include ...`).
717
771
  //////////////////////////////////////
718
772
  class Mixin_Call : public Has_Block {
719
- ADD_PROPERTY(string, name);
720
- ADD_PROPERTY(Arguments*, arguments);
773
+ ADD_PROPERTY(std::string, name)
774
+ ADD_PROPERTY(Arguments*, arguments)
721
775
  public:
722
- Mixin_Call(ParserState pstate, string n, Arguments* args, Block* b = 0)
776
+ Mixin_Call(ParserState pstate, std::string n, Arguments* args, Block* b = 0)
723
777
  : Has_Block(pstate, b), name_(n), arguments_(args)
724
778
  { }
725
- ATTACH_OPERATIONS();
779
+ ATTACH_OPERATIONS()
726
780
  };
727
781
 
728
782
  ///////////////////////////////////////////////////
@@ -730,46 +784,45 @@ namespace Sass {
730
784
  ///////////////////////////////////////////////////
731
785
  class Content : public Statement {
732
786
  public:
733
- Content(ParserState pstate) : Statement(pstate) { }
734
- ATTACH_OPERATIONS();
787
+ Content(ParserState pstate) : Statement(pstate)
788
+ { statement_type(CONTENT); }
789
+ ATTACH_OPERATIONS()
735
790
  };
736
791
 
737
792
  ///////////////////////////////////////////////////////////////////////
738
793
  // Lists of values, both comma- and space-separated (distinguished by a
739
794
  // type-tag.) Also used to represent variable-length argument lists.
740
795
  ///////////////////////////////////////////////////////////////////////
741
- class List : public Expression, public Vectorized<Expression*> {
796
+ class List : public Value, public Vectorized<Expression*> {
742
797
  void adjust_after_pushing(Expression* e) { is_expanded(false); }
743
- public:
744
- enum Separator { SPACE, COMMA };
745
798
  private:
746
- ADD_PROPERTY(Separator, separator);
747
- ADD_PROPERTY(bool, is_arglist);
799
+ ADD_PROPERTY(enum Sass_Separator, separator)
800
+ ADD_PROPERTY(bool, is_arglist)
748
801
  public:
749
802
  List(ParserState pstate,
750
- size_t size = 0, Separator sep = SPACE, bool argl = false)
751
- : Expression(pstate),
803
+ size_t size = 0, enum Sass_Separator sep = SASS_SPACE, bool argl = false)
804
+ : Value(pstate),
752
805
  Vectorized<Expression*>(size),
753
806
  separator_(sep), is_arglist_(argl)
754
807
  { concrete_type(LIST); }
755
- string type() { return is_arglist_ ? "arglist" : "list"; }
756
- static string type_name() { return "list"; }
757
- bool is_invisible() { return !length(); }
808
+ std::string type() { return is_arglist_ ? "arglist" : "list"; }
809
+ static std::string type_name() { return "list"; }
810
+ const char* sep_string(bool compressed = false) const {
811
+ return separator() == SASS_COMMA ?
812
+ (compressed ? "," : ", ") : " ";
813
+ }
814
+ bool is_invisible() const { return empty(); }
758
815
  Expression* value_at_index(size_t i);
759
816
 
760
817
  virtual size_t size() const;
761
- virtual bool operator==(Expression& rhs) const;
762
- virtual bool operator==(Expression* rhs) const;
763
818
 
764
819
  virtual size_t hash()
765
820
  {
766
- if (hash_ > 0) return hash_;
767
-
768
- hash_ = std::hash<string>()(separator() == COMMA ? "comma" : "space");
769
-
770
- for (size_t i = 0, L = length(); i < L; ++i)
771
- hash_ ^= (elements()[i])->hash();
772
-
821
+ if (hash_ == 0) {
822
+ hash_ = std::hash<std::string>()(sep_string());
823
+ for (size_t i = 0, L = length(); i < L; ++i)
824
+ hash_combine(hash_, (elements()[i])->hash());
825
+ }
773
826
  return hash_;
774
827
  }
775
828
 
@@ -780,52 +833,43 @@ namespace Sass {
780
833
  is_delayed(delayed);
781
834
  }
782
835
 
783
- ATTACH_OPERATIONS();
836
+ virtual bool operator== (const Expression& rhs) const;
837
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
838
+
839
+ ATTACH_OPERATIONS()
784
840
  };
785
841
 
786
842
  ///////////////////////////////////////////////////////////////////////
787
843
  // Key value paris.
788
844
  ///////////////////////////////////////////////////////////////////////
789
- class Map : public Expression, public Hashed {
845
+ class Map : public Value, public Hashed {
790
846
  void adjust_after_pushing(std::pair<Expression*, Expression*> p) { is_expanded(false); }
791
847
  public:
792
848
  Map(ParserState pstate,
793
849
  size_t size = 0)
794
- : Expression(pstate),
850
+ : Value(pstate),
795
851
  Hashed(size)
796
852
  { concrete_type(MAP); }
797
- string type() { return "map"; }
798
- static string type_name() { return "map"; }
799
- bool is_invisible() { return !length(); }
800
-
801
- virtual bool operator==(Expression& rhs) const
802
- {
803
- try
804
- {
805
- Map& m = dynamic_cast<Map&>(rhs);
806
- if (!(m && length() == m.length())) return false;
807
- for (auto key : keys())
808
- if (!(*at(key) == *m.at(key))) return false;
809
- return true;
810
- }
811
- catch (std::bad_cast&)
812
- {
813
- return false;
814
- }
815
- catch (...) { throw; }
816
- }
853
+ std::string type() { return "map"; }
854
+ static std::string type_name() { return "map"; }
855
+ bool is_invisible() const { return empty(); }
817
856
 
818
857
  virtual size_t hash()
819
858
  {
820
- if (hash_ > 0) return hash_;
821
-
822
- for (auto key : keys())
823
- hash_ ^= key->hash() ^ at(key)->hash();
859
+ if (hash_ == 0) {
860
+ for (auto key : keys()) {
861
+ hash_combine(hash_, key->hash());
862
+ hash_combine(hash_, at(key)->hash());
863
+ }
864
+ }
824
865
 
825
866
  return hash_;
826
867
  }
827
868
 
828
- ATTACH_OPERATIONS();
869
+ virtual bool operator== (const Expression& rhs) const;
870
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
871
+
872
+ ATTACH_OPERATIONS()
829
873
  };
830
874
 
831
875
  //////////////////////////////////////////////////////////////////////////
@@ -834,24 +878,17 @@ namespace Sass {
834
878
  // subclassing.
835
879
  //////////////////////////////////////////////////////////////////////////
836
880
  class Binary_Expression : public Expression {
837
- public:
838
- enum Type {
839
- AND, OR, // logical connectives
840
- EQ, NEQ, GT, GTE, LT, LTE, // arithmetic relations
841
- ADD, SUB, MUL, DIV, MOD, // arithmetic functions
842
- NUM_OPS // so we know how big to make the op table
843
- };
844
881
  private:
845
- ADD_PROPERTY(Type, type);
846
- ADD_PROPERTY(Expression*, left);
847
- ADD_PROPERTY(Expression*, right);
882
+ ADD_PROPERTY(enum Sass_OP, type)
883
+ ADD_PROPERTY(Expression*, left)
884
+ ADD_PROPERTY(Expression*, right)
848
885
  size_t hash_;
849
886
  public:
850
887
  Binary_Expression(ParserState pstate,
851
- Type t, Expression* lhs, Expression* rhs)
888
+ enum Sass_OP t, Expression* lhs, Expression* rhs)
852
889
  : Expression(pstate), type_(t), left_(lhs), right_(rhs), hash_(0)
853
890
  { }
854
- const string type_name() {
891
+ const std::string type_name() {
855
892
  switch (type_) {
856
893
  case AND: return "and"; break;
857
894
  case OR: return "or"; break;
@@ -876,15 +913,15 @@ namespace Sass {
876
913
  left()->set_delayed(delayed);
877
914
  is_delayed(delayed);
878
915
  }
879
- virtual bool operator==(Expression& rhs) const
916
+ virtual bool operator==(const Expression& rhs) const
880
917
  {
881
918
  try
882
919
  {
883
- Binary_Expression& m = dynamic_cast<Binary_Expression&>(rhs);
920
+ const Binary_Expression* m = dynamic_cast<const Binary_Expression*>(&rhs);
884
921
  if (m == 0) return false;
885
- return type() == m.type() &&
886
- left() == m.left() &&
887
- right() == m.right();
922
+ return type() == m->type() &&
923
+ left() == m->left() &&
924
+ right() == m->right();
888
925
  }
889
926
  catch (std::bad_cast&)
890
927
  {
@@ -894,11 +931,14 @@ namespace Sass {
894
931
  }
895
932
  virtual size_t hash()
896
933
  {
897
- if (hash_ > 0) return hash_;
898
- hash_ = left()->hash() ^ right()->hash() ^ std::hash<size_t>()(type_);
934
+ if (hash_ == 0) {
935
+ hash_ = std::hash<size_t>()(type_);
936
+ hash_combine(hash_, left()->hash());
937
+ hash_combine(hash_, right()->hash());
938
+ }
899
939
  return hash_;
900
940
  }
901
- ATTACH_OPERATIONS();
941
+ ATTACH_OPERATIONS()
902
942
  };
903
943
 
904
944
  ////////////////////////////////////////////////////////////////////////////
@@ -908,14 +948,14 @@ namespace Sass {
908
948
  public:
909
949
  enum Type { PLUS, MINUS, NOT };
910
950
  private:
911
- ADD_PROPERTY(Type, type);
912
- ADD_PROPERTY(Expression*, operand);
951
+ ADD_PROPERTY(Type, type)
952
+ ADD_PROPERTY(Expression*, operand)
913
953
  size_t hash_;
914
954
  public:
915
955
  Unary_Expression(ParserState pstate, Type t, Expression* o)
916
956
  : Expression(pstate), type_(t), operand_(o), hash_(0)
917
957
  { }
918
- const string type_name() {
958
+ const std::string type_name() {
919
959
  switch (type_) {
920
960
  case PLUS: return "plus"; break;
921
961
  case MINUS: return "minus"; break;
@@ -923,14 +963,14 @@ namespace Sass {
923
963
  default: return "invalid"; break;
924
964
  }
925
965
  }
926
- virtual bool operator==(Expression& rhs) const
966
+ virtual bool operator==(const Expression& rhs) const
927
967
  {
928
968
  try
929
969
  {
930
- Unary_Expression& m = dynamic_cast<Unary_Expression&>(rhs);
970
+ const Unary_Expression* m = dynamic_cast<const Unary_Expression*>(&rhs);
931
971
  if (m == 0) return false;
932
- return type() == m.type() &&
933
- operand() == m.operand();
972
+ return type() == m->type() &&
973
+ operand() == m->operand();
934
974
  }
935
975
  catch (std::bad_cast&)
936
976
  {
@@ -940,24 +980,26 @@ namespace Sass {
940
980
  }
941
981
  virtual size_t hash()
942
982
  {
943
- if (hash_ > 0) return hash_;
944
- hash_ = operand()->hash() ^ std::hash<size_t>()(type_);
983
+ if (hash_ == 0) {
984
+ hash_ = std::hash<size_t>()(type_);
985
+ hash_combine(hash_, operand()->hash());
986
+ };
945
987
  return hash_;
946
988
  }
947
- ATTACH_OPERATIONS();
989
+ ATTACH_OPERATIONS()
948
990
  };
949
991
 
950
992
  ////////////////////////////////////////////////////////////
951
993
  // Individual argument objects for mixin and function calls.
952
994
  ////////////////////////////////////////////////////////////
953
995
  class Argument : public Expression {
954
- ADD_PROPERTY(Expression*, value);
955
- ADD_PROPERTY(string, name);
956
- ADD_PROPERTY(bool, is_rest_argument);
957
- ADD_PROPERTY(bool, is_keyword_argument);
996
+ ADD_PROPERTY(Expression*, value)
997
+ ADD_PROPERTY(std::string, name)
998
+ ADD_PROPERTY(bool, is_rest_argument)
999
+ ADD_PROPERTY(bool, is_keyword_argument)
958
1000
  size_t hash_;
959
1001
  public:
960
- Argument(ParserState pstate, Expression* val, string n = "", bool rest = false, bool keyword = false)
1002
+ Argument(ParserState pstate, Expression* val, std::string n = "", bool rest = false, bool keyword = false)
961
1003
  : Expression(pstate), value_(val), name_(n), is_rest_argument_(rest), is_keyword_argument_(keyword), hash_(0)
962
1004
  {
963
1005
  if (!name_.empty() && is_rest_argument_) {
@@ -965,13 +1007,13 @@ namespace Sass {
965
1007
  }
966
1008
  }
967
1009
 
968
- virtual bool operator==(Expression& rhs) const
1010
+ virtual bool operator==(const Expression& rhs) const
969
1011
  {
970
1012
  try
971
1013
  {
972
- Argument& m = dynamic_cast<Argument&>(rhs);
973
- if (!(m && name() == m.name())) return false;
974
- return *value() == *m.value();
1014
+ const Argument* m = dynamic_cast<const Argument*>(&rhs);
1015
+ if (!(m && name() == m->name())) return false;
1016
+ return *value() == *m->value();
975
1017
  }
976
1018
  catch (std::bad_cast&)
977
1019
  {
@@ -982,14 +1024,14 @@ namespace Sass {
982
1024
 
983
1025
  virtual size_t hash()
984
1026
  {
985
- if (hash_ > 0) return hash_;
986
-
987
- hash_ = std::hash<string>()(name()) ^ value()->hash();
988
-
1027
+ if (hash_ == 0) {
1028
+ hash_ = std::hash<std::string>()(name());
1029
+ hash_combine(hash_, value()->hash());
1030
+ }
989
1031
  return hash_;
990
1032
  }
991
1033
 
992
- ATTACH_OPERATIONS();
1034
+ ATTACH_OPERATIONS()
993
1035
  };
994
1036
 
995
1037
  ////////////////////////////////////////////////////////////////////////
@@ -998,42 +1040,11 @@ namespace Sass {
998
1040
  // named arguments).
999
1041
  ////////////////////////////////////////////////////////////////////////
1000
1042
  class Arguments : public Expression, public Vectorized<Argument*> {
1001
- ADD_PROPERTY(bool, has_named_arguments);
1002
- ADD_PROPERTY(bool, has_rest_argument);
1003
- ADD_PROPERTY(bool, has_keyword_argument);
1043
+ ADD_PROPERTY(bool, has_named_arguments)
1044
+ ADD_PROPERTY(bool, has_rest_argument)
1045
+ ADD_PROPERTY(bool, has_keyword_argument)
1004
1046
  protected:
1005
- void adjust_after_pushing(Argument* a)
1006
- {
1007
- if (!a->name().empty()) {
1008
- if (has_rest_argument_ || has_keyword_argument_) {
1009
- error("named arguments must precede variable-length argument", a->pstate());
1010
- }
1011
- has_named_arguments_ = true;
1012
- }
1013
- else if (a->is_rest_argument()) {
1014
- if (has_rest_argument_) {
1015
- error("functions and mixins may only be called with one variable-length argument", a->pstate());
1016
- }
1017
- if (has_keyword_argument_) {
1018
- error("only keyword arguments may follow variable arguments", a->pstate());
1019
- }
1020
- has_rest_argument_ = true;
1021
- }
1022
- else if (a->is_keyword_argument()) {
1023
- if (has_keyword_argument_) {
1024
- error("functions and mixins may only be called with one keyword argument", a->pstate());
1025
- }
1026
- has_keyword_argument_ = true;
1027
- }
1028
- else {
1029
- if (has_rest_argument_) {
1030
- error("ordinal arguments must precede variable-length arguments", a->pstate());
1031
- }
1032
- if (has_named_arguments_) {
1033
- error("ordinal arguments must precede named arguments", a->pstate());
1034
- }
1035
- }
1036
- }
1047
+ void adjust_after_pushing(Argument* a);
1037
1048
  public:
1038
1049
  Arguments(ParserState pstate)
1039
1050
  : Expression(pstate),
@@ -1042,34 +1053,34 @@ namespace Sass {
1042
1053
  has_rest_argument_(false),
1043
1054
  has_keyword_argument_(false)
1044
1055
  { }
1045
- ATTACH_OPERATIONS();
1056
+ ATTACH_OPERATIONS()
1046
1057
  };
1047
1058
 
1048
1059
  //////////////////
1049
1060
  // Function calls.
1050
1061
  //////////////////
1051
1062
  class Function_Call : public Expression {
1052
- ADD_PROPERTY(string, name);
1053
- ADD_PROPERTY(Arguments*, arguments);
1054
- ADD_PROPERTY(void*, cookie);
1063
+ ADD_PROPERTY(std::string, name)
1064
+ ADD_PROPERTY(Arguments*, arguments)
1065
+ ADD_PROPERTY(void*, cookie)
1055
1066
  size_t hash_;
1056
1067
  public:
1057
- Function_Call(ParserState pstate, string n, Arguments* args, void* cookie)
1068
+ Function_Call(ParserState pstate, std::string n, Arguments* args, void* cookie)
1058
1069
  : Expression(pstate), name_(n), arguments_(args), cookie_(cookie), hash_(0)
1059
1070
  { concrete_type(STRING); }
1060
- Function_Call(ParserState pstate, string n, Arguments* args)
1071
+ Function_Call(ParserState pstate, std::string n, Arguments* args)
1061
1072
  : Expression(pstate), name_(n), arguments_(args), cookie_(0), hash_(0)
1062
1073
  { concrete_type(STRING); }
1063
1074
 
1064
- virtual bool operator==(Expression& rhs) const
1075
+ virtual bool operator==(const Expression& rhs) const
1065
1076
  {
1066
1077
  try
1067
1078
  {
1068
- Function_Call& m = dynamic_cast<Function_Call&>(rhs);
1069
- if (!(m && name() == m.name())) return false;
1070
- if (!(m && arguments()->length() == m.arguments()->length())) return false;
1079
+ const Function_Call* m = dynamic_cast<const Function_Call*>(&rhs);
1080
+ if (!(m && name() == m->name())) return false;
1081
+ if (!(m && arguments()->length() == m->arguments()->length())) return false;
1071
1082
  for (size_t i =0, L = arguments()->length(); i < L; ++i)
1072
- if (!((*arguments())[i] == (*m.arguments())[i])) return false;
1083
+ if (!((*arguments())[i] == (*m->arguments())[i])) return false;
1073
1084
  return true;
1074
1085
  }
1075
1086
  catch (std::bad_cast&)
@@ -1081,47 +1092,46 @@ namespace Sass {
1081
1092
 
1082
1093
  virtual size_t hash()
1083
1094
  {
1084
- if (hash_ > 0) return hash_;
1085
-
1086
- hash_ = std::hash<string>()(name());
1087
- for (auto argument : arguments()->elements())
1088
- hash_ ^= argument->hash();
1089
-
1095
+ if (hash_ == 0) {
1096
+ hash_ = std::hash<std::string>()(name());
1097
+ for (auto argument : arguments()->elements())
1098
+ hash_combine(hash_, argument->hash());
1099
+ }
1090
1100
  return hash_;
1091
1101
  }
1092
1102
 
1093
- ATTACH_OPERATIONS();
1103
+ ATTACH_OPERATIONS()
1094
1104
  };
1095
1105
 
1096
1106
  /////////////////////////
1097
1107
  // Function call schemas.
1098
1108
  /////////////////////////
1099
1109
  class Function_Call_Schema : public Expression {
1100
- ADD_PROPERTY(String*, name);
1101
- ADD_PROPERTY(Arguments*, arguments);
1110
+ ADD_PROPERTY(String*, name)
1111
+ ADD_PROPERTY(Arguments*, arguments)
1102
1112
  public:
1103
1113
  Function_Call_Schema(ParserState pstate, String* n, Arguments* args)
1104
1114
  : Expression(pstate), name_(n), arguments_(args)
1105
1115
  { concrete_type(STRING); }
1106
- ATTACH_OPERATIONS();
1116
+ ATTACH_OPERATIONS()
1107
1117
  };
1108
1118
 
1109
1119
  ///////////////////////
1110
1120
  // Variable references.
1111
1121
  ///////////////////////
1112
1122
  class Variable : public Expression {
1113
- ADD_PROPERTY(string, name);
1123
+ ADD_PROPERTY(std::string, name)
1114
1124
  public:
1115
- Variable(ParserState pstate, string n)
1125
+ Variable(ParserState pstate, std::string n)
1116
1126
  : Expression(pstate), name_(n)
1117
1127
  { }
1118
1128
 
1119
- virtual bool operator==(Expression& rhs) const
1129
+ virtual bool operator==(const Expression& rhs) const
1120
1130
  {
1121
1131
  try
1122
1132
  {
1123
- Variable& e = dynamic_cast<Variable&>(rhs);
1124
- return e && name() == e.name();
1133
+ const Variable* e = dynamic_cast<const Variable*>(&rhs);
1134
+ return e && name() == e->name();
1125
1135
  }
1126
1136
  catch (std::bad_cast&)
1127
1137
  {
@@ -1132,10 +1142,10 @@ namespace Sass {
1132
1142
 
1133
1143
  virtual size_t hash()
1134
1144
  {
1135
- return std::hash<string>()(name());
1145
+ return std::hash<std::string>()(name());
1136
1146
  }
1137
1147
 
1138
- ATTACH_OPERATIONS();
1148
+ ATTACH_OPERATIONS()
1139
1149
  };
1140
1150
 
1141
1151
  ////////////////////////////////////////////////////////////////////////////
@@ -1146,21 +1156,21 @@ namespace Sass {
1146
1156
  public:
1147
1157
  enum Type { NUMBER, PERCENTAGE, DIMENSION, HEX };
1148
1158
  private:
1149
- ADD_PROPERTY(Type, type);
1150
- ADD_PROPERTY(string, value);
1159
+ ADD_PROPERTY(Type, type)
1160
+ ADD_PROPERTY(std::string, value)
1151
1161
  size_t hash_;
1152
1162
  public:
1153
- Textual(ParserState pstate, Type t, string val)
1163
+ Textual(ParserState pstate, Type t, std::string val)
1154
1164
  : Expression(pstate, true), type_(t), value_(val),
1155
1165
  hash_(0)
1156
1166
  { }
1157
1167
 
1158
- virtual bool operator==(Expression& rhs) const
1168
+ virtual bool operator==(const Expression& rhs) const
1159
1169
  {
1160
1170
  try
1161
1171
  {
1162
- Textual& e = dynamic_cast<Textual&>(rhs);
1163
- return e && value() == e.value() && type() == e.type();
1172
+ const Textual* e = dynamic_cast<const Textual*>(&rhs);
1173
+ return e && value() == e->value() && type() == e->type();
1164
1174
  }
1165
1175
  catch (std::bad_cast&)
1166
1176
  {
@@ -1171,143 +1181,166 @@ namespace Sass {
1171
1181
 
1172
1182
  virtual size_t hash()
1173
1183
  {
1174
- if (hash_ == 0) hash_ = std::hash<string>()(value_) ^ std::hash<int>()(type_);
1184
+ if (hash_ == 0) {
1185
+ hash_ = std::hash<std::string>()(value_);
1186
+ hash_combine(hash_, std::hash<int>()(type_));
1187
+ }
1175
1188
  return hash_;
1176
1189
  }
1177
1190
 
1178
- ATTACH_OPERATIONS();
1191
+ ATTACH_OPERATIONS()
1179
1192
  };
1180
1193
 
1181
1194
  ////////////////////////////////////////////////
1182
1195
  // Numbers, percentages, dimensions, and colors.
1183
1196
  ////////////////////////////////////////////////
1184
- class Number : public Expression {
1185
- ADD_PROPERTY(double, value);
1186
- ADD_PROPERTY(bool, zero);
1187
- vector<string> numerator_units_;
1188
- vector<string> denominator_units_;
1197
+ class Number : public Value {
1198
+ ADD_PROPERTY(double, value)
1199
+ ADD_PROPERTY(bool, zero)
1200
+ std::vector<std::string> numerator_units_;
1201
+ std::vector<std::string> denominator_units_;
1189
1202
  size_t hash_;
1190
1203
  public:
1191
- Number(ParserState pstate, double val, string u = "", bool zero = true);
1204
+ Number(ParserState pstate, double val, std::string u = "", bool zero = true);
1192
1205
  bool zero() { return zero_; }
1193
- vector<string>& numerator_units() { return numerator_units_; }
1194
- vector<string>& denominator_units() { return denominator_units_; }
1195
- string type() { return "number"; }
1196
- static string type_name() { return "number"; }
1197
- string unit() const;
1206
+ std::vector<std::string>& numerator_units() { return numerator_units_; }
1207
+ std::vector<std::string>& denominator_units() { return denominator_units_; }
1208
+ const std::vector<std::string>& numerator_units() const { return numerator_units_; }
1209
+ const std::vector<std::string>& denominator_units() const { return denominator_units_; }
1210
+ std::string type() { return "number"; }
1211
+ static std::string type_name() { return "number"; }
1212
+ std::string unit() const;
1198
1213
 
1199
1214
  bool is_unitless();
1200
- void convert(const string& unit = "");
1201
- void normalize(const string& unit = "");
1215
+ void convert(const std::string& unit = "", bool strict = false);
1216
+ void normalize(const std::string& unit = "", bool strict = false);
1202
1217
  // useful for making one number compatible with another
1203
- string find_convertible_unit() const;
1204
-
1205
- virtual bool operator== (Expression& rhs) const;
1206
- virtual bool operator== (Expression* rhs) const;
1218
+ std::string find_convertible_unit() const;
1207
1219
 
1208
1220
  virtual size_t hash()
1209
1221
  {
1210
- if (hash_ == 0) hash_ = std::hash<double>()(value_);
1222
+ if (hash_ == 0) {
1223
+ hash_ = std::hash<double>()(value_);
1224
+ }
1211
1225
  return hash_;
1212
1226
  }
1213
1227
 
1214
- ATTACH_OPERATIONS();
1228
+ virtual bool operator< (const Number& rhs) const;
1229
+ virtual bool operator== (const Expression& rhs) const;
1230
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
1231
+
1232
+ ATTACH_OPERATIONS()
1215
1233
  };
1216
1234
 
1217
1235
  //////////
1218
1236
  // Colors.
1219
1237
  //////////
1220
- class Color : public Expression {
1221
- ADD_PROPERTY(double, r);
1222
- ADD_PROPERTY(double, g);
1223
- ADD_PROPERTY(double, b);
1224
- ADD_PROPERTY(double, a);
1225
- ADD_PROPERTY(bool, sixtuplet);
1226
- ADD_PROPERTY(string, disp);
1238
+ class Color : public Value {
1239
+ ADD_PROPERTY(double, r)
1240
+ ADD_PROPERTY(double, g)
1241
+ ADD_PROPERTY(double, b)
1242
+ ADD_PROPERTY(double, a)
1243
+ ADD_PROPERTY(bool, sixtuplet)
1244
+ ADD_PROPERTY(std::string, disp)
1227
1245
  size_t hash_;
1228
1246
  public:
1229
- Color(ParserState pstate, double r, double g, double b, double a = 1, bool sixtuplet = true, const string disp = "")
1230
- : Expression(pstate), r_(r), g_(g), b_(b), a_(a), sixtuplet_(sixtuplet), disp_(disp),
1247
+ Color(ParserState pstate, double r, double g, double b, double a = 1, bool sixtuplet = true, const std::string disp = "")
1248
+ : Value(pstate), r_(r), g_(g), b_(b), a_(a), sixtuplet_(sixtuplet), disp_(disp),
1231
1249
  hash_(0)
1232
1250
  { concrete_type(COLOR); }
1233
- string type() { return "color"; }
1234
- static string type_name() { return "color"; }
1235
-
1236
- virtual bool operator==(Expression& rhs) const
1237
- {
1238
- try
1239
- {
1240
- Color& c = (dynamic_cast<Color&>(rhs));
1241
- return c && r() == c.r() && g() == c.g() && b() == c.b() && a() == c.a();
1242
- }
1243
- catch (std::bad_cast&)
1244
- {
1245
- return false;
1246
- }
1247
- catch (...) { throw; }
1248
- }
1251
+ std::string type() { return "color"; }
1252
+ static std::string type_name() { return "color"; }
1249
1253
 
1250
1254
  virtual size_t hash()
1251
1255
  {
1252
- if (hash_ == 0) hash_ = std::hash<double>()(r_) ^ std::hash<double>()(g_) ^ std::hash<double>()(b_) ^ std::hash<double>()(a_);
1256
+ if (hash_ == 0) {
1257
+ hash_ = std::hash<double>()(a_);
1258
+ hash_combine(hash_, std::hash<double>()(r_));
1259
+ hash_combine(hash_, std::hash<double>()(g_));
1260
+ hash_combine(hash_, std::hash<double>()(b_));
1261
+ }
1253
1262
  return hash_;
1254
1263
  }
1255
1264
 
1256
- ATTACH_OPERATIONS();
1265
+ virtual bool operator== (const Expression& rhs) const;
1266
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
1267
+
1268
+ ATTACH_OPERATIONS()
1269
+ };
1270
+
1271
+ //////////////////////////////
1272
+ // Errors from Sass_Values.
1273
+ //////////////////////////////
1274
+ class Custom_Error : public Value {
1275
+ ADD_PROPERTY(std::string, message)
1276
+ public:
1277
+ Custom_Error(ParserState pstate, std::string msg)
1278
+ : Value(pstate), message_(msg)
1279
+ { concrete_type(C_ERROR); }
1280
+ virtual bool operator== (const Expression& rhs) const;
1281
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
1282
+ ATTACH_OPERATIONS()
1283
+ };
1284
+
1285
+ //////////////////////////////
1286
+ // Warnings from Sass_Values.
1287
+ //////////////////////////////
1288
+ class Custom_Warning : public Value {
1289
+ ADD_PROPERTY(std::string, message)
1290
+ public:
1291
+ Custom_Warning(ParserState pstate, std::string msg)
1292
+ : Value(pstate), message_(msg)
1293
+ { concrete_type(C_WARNING); }
1294
+ virtual bool operator== (const Expression& rhs) const;
1295
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
1296
+ ATTACH_OPERATIONS()
1257
1297
  };
1258
1298
 
1259
1299
  ////////////
1260
1300
  // Booleans.
1261
1301
  ////////////
1262
- class Boolean : public Expression {
1263
- ADD_PROPERTY(bool, value);
1302
+ class Boolean : public Value {
1303
+ ADD_PROPERTY(bool, value)
1264
1304
  size_t hash_;
1265
1305
  public:
1266
1306
  Boolean(ParserState pstate, bool val)
1267
- : Expression(pstate), value_(val),
1307
+ : Value(pstate), value_(val),
1268
1308
  hash_(0)
1269
1309
  { concrete_type(BOOLEAN); }
1270
1310
  virtual operator bool() { return value_; }
1271
- string type() { return "bool"; }
1272
- static string type_name() { return "bool"; }
1311
+ std::string type() { return "bool"; }
1312
+ static std::string type_name() { return "bool"; }
1273
1313
  virtual bool is_false() { return !value_; }
1274
1314
 
1275
- virtual bool operator==(Expression& rhs) const
1276
- {
1277
- try
1278
- {
1279
- Boolean& e = dynamic_cast<Boolean&>(rhs);
1280
- return e && value() == e.value();
1281
- }
1282
- catch (std::bad_cast&)
1283
- {
1284
- return false;
1285
- }
1286
- catch (...) { throw; }
1287
- }
1288
-
1289
1315
  virtual size_t hash()
1290
1316
  {
1291
- if (hash_ == 0) hash_ = std::hash<bool>()(value_);
1317
+ if (hash_ == 0) {
1318
+ hash_ = std::hash<bool>()(value_);
1319
+ }
1292
1320
  return hash_;
1293
1321
  }
1294
1322
 
1295
- ATTACH_OPERATIONS();
1323
+ virtual bool operator== (const Expression& rhs) const;
1324
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
1325
+
1326
+ ATTACH_OPERATIONS()
1296
1327
  };
1297
1328
 
1298
1329
  ////////////////////////////////////////////////////////////////////////
1299
1330
  // Abstract base class for Sass string values. Includes interpolated and
1300
1331
  // "flat" strings.
1301
1332
  ////////////////////////////////////////////////////////////////////////
1302
- class String : public Expression {
1303
- ADD_PROPERTY(bool, sass_fix_1291);
1333
+ class String : public Value {
1334
+ ADD_PROPERTY(bool, sass_fix_1291)
1304
1335
  public:
1305
1336
  String(ParserState pstate, bool delayed = false, bool sass_fix_1291 = false)
1306
- : Expression(pstate, delayed), sass_fix_1291_(sass_fix_1291)
1337
+ : Value(pstate, delayed), sass_fix_1291_(sass_fix_1291)
1307
1338
  { concrete_type(STRING); }
1308
- static string type_name() { return "string"; }
1339
+ static std::string type_name() { return "string"; }
1309
1340
  virtual ~String() = 0;
1310
- ATTACH_OPERATIONS();
1341
+ virtual bool operator==(const Expression& rhs) const = 0;
1342
+ virtual std::string to_string(bool compressed = false, int precision = 5) const = 0;
1343
+ ATTACH_OPERATIONS()
1311
1344
  };
1312
1345
  inline String::~String() { };
1313
1346
 
@@ -1316,95 +1349,71 @@ namespace Sass {
1316
1349
  // evaluation phase.
1317
1350
  ///////////////////////////////////////////////////////////////////////
1318
1351
  class String_Schema : public String, public Vectorized<Expression*> {
1319
- ADD_PROPERTY(bool, has_interpolants);
1352
+ ADD_PROPERTY(bool, has_interpolants)
1320
1353
  size_t hash_;
1321
1354
  public:
1322
1355
  String_Schema(ParserState pstate, size_t size = 0, bool has_interpolants = false)
1323
1356
  : String(pstate), Vectorized<Expression*>(size), has_interpolants_(has_interpolants), hash_(0)
1324
- { }
1325
- string type() { return "string"; }
1326
- static string type_name() { return "string"; }
1327
-
1328
- virtual bool operator==(Expression& rhs) const
1329
- {
1330
- try
1331
- {
1332
- String_Schema& e = dynamic_cast<String_Schema&>(rhs);
1333
- if (!(e && length() == e.length())) return false;
1334
- for (size_t i = 0, L = length(); i < L; ++i)
1335
- if (!((*this)[i] == e[i])) return false;
1336
- return true;
1337
- }
1338
- catch (std::bad_cast&)
1339
- {
1340
- return false;
1341
- }
1342
- catch (...) { throw; }
1343
- }
1357
+ { concrete_type(STRING); }
1358
+ std::string type() { return "string"; }
1359
+ static std::string type_name() { return "string"; }
1344
1360
 
1345
1361
  virtual size_t hash()
1346
1362
  {
1347
- if (hash_ > 0) return hash_;
1348
-
1349
- for (auto string : elements())
1350
- hash_ ^= string->hash();
1351
-
1363
+ if (hash_ == 0) {
1364
+ for (auto string : elements())
1365
+ hash_combine(hash_, string->hash());
1366
+ }
1352
1367
  return hash_;
1353
1368
  }
1354
1369
 
1355
- ATTACH_OPERATIONS();
1370
+ virtual bool operator==(const Expression& rhs) const;
1371
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
1372
+
1373
+ ATTACH_OPERATIONS()
1356
1374
  };
1357
1375
 
1358
1376
  ////////////////////////////////////////////////////////
1359
1377
  // Flat strings -- the lowest level of raw textual data.
1360
1378
  ////////////////////////////////////////////////////////
1361
1379
  class String_Constant : public String {
1362
- ADD_PROPERTY(char, quote_mark);
1363
- ADD_PROPERTY(bool, can_compress_whitespace);
1364
- ADD_PROPERTY(string, value);
1380
+ ADD_PROPERTY(char, quote_mark)
1381
+ ADD_PROPERTY(bool, can_compress_whitespace)
1382
+ ADD_PROPERTY(std::string, value)
1365
1383
  protected:
1366
1384
  size_t hash_;
1367
1385
  public:
1368
- String_Constant(ParserState pstate, string val)
1386
+ String_Constant(ParserState pstate, std::string val)
1369
1387
  : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(val)), hash_(0)
1370
1388
  { }
1371
1389
  String_Constant(ParserState pstate, const char* beg)
1372
- : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(string(beg))), hash_(0)
1390
+ : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(beg))), hash_(0)
1373
1391
  { }
1374
1392
  String_Constant(ParserState pstate, const char* beg, const char* end)
1375
- : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(string(beg, end-beg))), hash_(0)
1393
+ : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(beg, end-beg))), hash_(0)
1376
1394
  { }
1377
1395
  String_Constant(ParserState pstate, const Token& tok)
1378
- : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(string(tok.begin, tok.end))), hash_(0)
1396
+ : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(tok.begin, tok.end))), hash_(0)
1379
1397
  { }
1380
- string type() { return "string"; }
1381
- static string type_name() { return "string"; }
1382
-
1383
- virtual bool operator==(Expression& rhs) const
1384
- {
1385
- try
1386
- {
1387
- String_Constant& e = dynamic_cast<String_Constant&>(rhs);
1388
- return e && value_ == e.value_;
1389
- }
1390
- catch (std::bad_cast&)
1391
- {
1392
- return false;
1393
- }
1394
- catch (...) { throw; }
1395
- }
1398
+ std::string type() { return "string"; }
1399
+ static std::string type_name() { return "string"; }
1396
1400
 
1397
1401
  virtual size_t hash()
1398
1402
  {
1399
- if (hash_ == 0) hash_ = std::hash<string>()(value_);
1403
+ if (hash_ == 0) {
1404
+ hash_ = std::hash<std::string>()(value_);
1405
+ }
1400
1406
  return hash_;
1401
1407
  }
1402
1408
 
1409
+ virtual bool operator==(const Expression& rhs) const;
1410
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
1411
+
1403
1412
  // static char auto_quote() { return '*'; }
1404
1413
  static char double_quote() { return '"'; }
1405
1414
  static char single_quote() { return '\''; }
1406
1415
 
1407
- ATTACH_OPERATIONS();
1416
+ ATTACH_OPERATIONS()
1408
1417
  };
1409
1418
 
1410
1419
  ////////////////////////////////////////////////////////
@@ -1412,12 +1421,15 @@ namespace Sass {
1412
1421
  ////////////////////////////////////////////////////////
1413
1422
  class String_Quoted : public String_Constant {
1414
1423
  public:
1415
- String_Quoted(ParserState pstate, string val)
1424
+ String_Quoted(ParserState pstate, std::string val, char q = 0, bool keep_utf8_escapes = false)
1416
1425
  : String_Constant(pstate, val)
1417
1426
  {
1418
- value_ = unquote(value_, &quote_mark_);
1427
+ value_ = unquote(value_, &quote_mark_, keep_utf8_escapes);
1428
+ if (q && quote_mark_) quote_mark_ = q;
1419
1429
  }
1420
- ATTACH_OPERATIONS();
1430
+ virtual bool operator==(const Expression& rhs) const;
1431
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
1432
+ ATTACH_OPERATIONS()
1421
1433
  };
1422
1434
 
1423
1435
  /////////////////
@@ -1425,62 +1437,118 @@ namespace Sass {
1425
1437
  /////////////////
1426
1438
  class Media_Query : public Expression,
1427
1439
  public Vectorized<Media_Query_Expression*> {
1428
- ADD_PROPERTY(String*, media_type);
1429
- ADD_PROPERTY(bool, is_negated);
1430
- ADD_PROPERTY(bool, is_restricted);
1440
+ ADD_PROPERTY(String*, media_type)
1441
+ ADD_PROPERTY(bool, is_negated)
1442
+ ADD_PROPERTY(bool, is_restricted)
1431
1443
  public:
1432
1444
  Media_Query(ParserState pstate,
1433
1445
  String* t = 0, size_t s = 0, bool n = false, bool r = false)
1434
1446
  : Expression(pstate), Vectorized<Media_Query_Expression*>(s),
1435
1447
  media_type_(t), is_negated_(n), is_restricted_(r)
1436
1448
  { }
1437
- ATTACH_OPERATIONS();
1449
+ ATTACH_OPERATIONS()
1438
1450
  };
1439
1451
 
1440
1452
  ////////////////////////////////////////////////////
1441
1453
  // Media expressions (for use inside media queries).
1442
1454
  ////////////////////////////////////////////////////
1443
1455
  class Media_Query_Expression : public Expression {
1444
- ADD_PROPERTY(Expression*, feature);
1445
- ADD_PROPERTY(Expression*, value);
1446
- ADD_PROPERTY(bool, is_interpolated);
1456
+ ADD_PROPERTY(Expression*, feature)
1457
+ ADD_PROPERTY(Expression*, value)
1458
+ ADD_PROPERTY(bool, is_interpolated)
1447
1459
  public:
1448
1460
  Media_Query_Expression(ParserState pstate,
1449
1461
  Expression* f, Expression* v, bool i = false)
1450
1462
  : Expression(pstate), feature_(f), value_(v), is_interpolated_(i)
1451
1463
  { }
1452
- ATTACH_OPERATIONS();
1464
+ ATTACH_OPERATIONS()
1453
1465
  };
1454
1466
 
1455
- ///////////////////
1456
- // Feature queries.
1457
- ///////////////////
1458
- class Feature_Query : public Expression, public Vectorized<Feature_Query_Condition*> {
1467
+ ////////////////////
1468
+ // `@supports` rule.
1469
+ ////////////////////
1470
+ class Supports_Block : public Has_Block {
1471
+ ADD_PROPERTY(Supports_Condition*, condition)
1459
1472
  public:
1460
- Feature_Query(ParserState pstate, size_t s = 0)
1461
- : Expression(pstate), Vectorized<Feature_Query_Condition*>(s)
1473
+ Supports_Block(ParserState pstate, Supports_Condition* condition, Block* block = 0)
1474
+ : Has_Block(pstate, block), condition_(condition)
1475
+ { statement_type(SUPPORTS); }
1476
+ bool is_hoistable() { return true; }
1477
+ bool bubbles() { return true; }
1478
+ ATTACH_OPERATIONS()
1479
+ };
1480
+
1481
+ //////////////////////////////////////////////////////
1482
+ // The abstract superclass of all Supports conditions.
1483
+ //////////////////////////////////////////////////////
1484
+ class Supports_Condition : public Expression {
1485
+ public:
1486
+ Supports_Condition(ParserState pstate)
1487
+ : Expression(pstate)
1462
1488
  { }
1463
- ATTACH_OPERATIONS();
1489
+ virtual bool needs_parens(Supports_Condition* cond) const { return false; }
1490
+ ATTACH_OPERATIONS()
1464
1491
  };
1465
1492
 
1466
- ////////////////////////////////////////////////////////
1467
- // Feature expressions (for use inside feature queries).
1468
- ////////////////////////////////////////////////////////
1469
- class Feature_Query_Condition : public Expression, public Vectorized<Feature_Query_Condition*> {
1493
+ ////////////////////////////////////////////////////////////
1494
+ // An operator condition (e.g. `CONDITION1 and CONDITION2`).
1495
+ ////////////////////////////////////////////////////////////
1496
+ class Supports_Operator : public Supports_Condition {
1470
1497
  public:
1471
- enum Operand { NONE, AND, OR, NOT };
1498
+ enum Operand { AND, OR };
1472
1499
  private:
1473
- ADD_PROPERTY(String*, feature);
1474
- ADD_PROPERTY(Expression*, value);
1500
+ ADD_PROPERTY(Supports_Condition*, left);
1501
+ ADD_PROPERTY(Supports_Condition*, right);
1475
1502
  ADD_PROPERTY(Operand, operand);
1476
- ADD_PROPERTY(bool, is_root);
1477
1503
  public:
1478
- Feature_Query_Condition(ParserState pstate, size_t s = 0, String* f = 0,
1479
- Expression* v = 0, Operand o = NONE, bool r = false)
1480
- : Expression(pstate), Vectorized<Feature_Query_Condition*>(s),
1481
- feature_(f), value_(v), operand_(o), is_root_(r)
1504
+ Supports_Operator(ParserState pstate, Supports_Condition* l, Supports_Condition* r, Operand o)
1505
+ : Supports_Condition(pstate), left_(l), right_(r), operand_(o)
1482
1506
  { }
1483
- ATTACH_OPERATIONS();
1507
+ virtual bool needs_parens(Supports_Condition* cond) const;
1508
+ ATTACH_OPERATIONS()
1509
+ };
1510
+
1511
+ //////////////////////////////////////////
1512
+ // A negation condition (`not CONDITION`).
1513
+ //////////////////////////////////////////
1514
+ class Supports_Negation : public Supports_Condition {
1515
+ private:
1516
+ ADD_PROPERTY(Supports_Condition*, condition);
1517
+ public:
1518
+ Supports_Negation(ParserState pstate, Supports_Condition* c)
1519
+ : Supports_Condition(pstate), condition_(c)
1520
+ { }
1521
+ virtual bool needs_parens(Supports_Condition* cond) const;
1522
+ ATTACH_OPERATIONS()
1523
+ };
1524
+
1525
+ /////////////////////////////////////////////////////
1526
+ // A declaration condition (e.g. `(feature: value)`).
1527
+ /////////////////////////////////////////////////////
1528
+ class Supports_Declaration : public Supports_Condition {
1529
+ private:
1530
+ ADD_PROPERTY(Expression*, feature);
1531
+ ADD_PROPERTY(Expression*, value);
1532
+ public:
1533
+ Supports_Declaration(ParserState pstate, Expression* f, Expression* v)
1534
+ : Supports_Condition(pstate), feature_(f), value_(v)
1535
+ { }
1536
+ virtual bool needs_parens(Supports_Condition* cond) const { return false; }
1537
+ ATTACH_OPERATIONS()
1538
+ };
1539
+
1540
+ ///////////////////////////////////////////////
1541
+ // An interpolation condition (e.g. `#{$var}`).
1542
+ ///////////////////////////////////////////////
1543
+ class Supports_Interpolation : public Supports_Condition {
1544
+ private:
1545
+ ADD_PROPERTY(Expression*, value);
1546
+ public:
1547
+ Supports_Interpolation(ParserState pstate, Expression* v)
1548
+ : Supports_Condition(pstate), value_(v)
1549
+ { }
1550
+ virtual bool needs_parens(Supports_Condition* cond) const { return false; }
1551
+ ATTACH_OPERATIONS()
1484
1552
  };
1485
1553
 
1486
1554
  /////////////////////////////////////////////////
@@ -1488,19 +1556,19 @@ namespace Sass {
1488
1556
  /////////////////////////////////////////////////
1489
1557
  class At_Root_Expression : public Expression {
1490
1558
  private:
1491
- ADD_PROPERTY(String*, feature);
1492
- ADD_PROPERTY(Expression*, value);
1493
- ADD_PROPERTY(bool, is_interpolated);
1559
+ ADD_PROPERTY(String*, feature)
1560
+ ADD_PROPERTY(Expression*, value)
1561
+ ADD_PROPERTY(bool, is_interpolated)
1494
1562
  public:
1495
1563
  At_Root_Expression(ParserState pstate, String* f = 0, Expression* v = 0, bool i = false)
1496
1564
  : Expression(pstate), feature_(f), value_(v), is_interpolated_(i)
1497
1565
  { }
1498
- bool exclude(string str)
1566
+ bool exclude(std::string str)
1499
1567
  {
1500
1568
  To_String to_string;
1501
1569
  bool with = feature() && unquote(feature()->perform(&to_string)).compare("with") == 0;
1502
1570
  List* l = static_cast<List*>(value());
1503
- string v;
1571
+ std::string v;
1504
1572
 
1505
1573
  if (with)
1506
1574
  {
@@ -1523,14 +1591,14 @@ namespace Sass {
1523
1591
  return false;
1524
1592
  }
1525
1593
  }
1526
- ATTACH_OPERATIONS();
1594
+ ATTACH_OPERATIONS()
1527
1595
  };
1528
1596
 
1529
1597
  ///////////
1530
1598
  // At-root.
1531
1599
  ///////////
1532
1600
  class At_Root_Block : public Has_Block {
1533
- ADD_PROPERTY(At_Root_Expression*, expression);
1601
+ ADD_PROPERTY(At_Root_Expression*, expression)
1534
1602
  public:
1535
1603
  At_Root_Block(ParserState pstate, Block* b = 0, At_Root_Expression* e = 0)
1536
1604
  : Has_Block(pstate, b), expression_(e)
@@ -1550,7 +1618,7 @@ namespace Sass {
1550
1618
  {
1551
1619
  return expression()->exclude("rule");
1552
1620
  }
1553
- if (s->statement_type() == Statement::FEATURE)
1621
+ if (s->statement_type() == Statement::SUPPORTS)
1554
1622
  {
1555
1623
  return expression()->exclude("supports");
1556
1624
  }
@@ -1560,40 +1628,38 @@ namespace Sass {
1560
1628
  }
1561
1629
  return false;
1562
1630
  }
1563
- ATTACH_OPERATIONS();
1631
+ ATTACH_OPERATIONS()
1564
1632
  };
1565
1633
 
1566
1634
  //////////////////
1567
1635
  // The null value.
1568
1636
  //////////////////
1569
- class Null : public Expression {
1637
+ class Null : public Value {
1570
1638
  public:
1571
- Null(ParserState pstate) : Expression(pstate) { concrete_type(NULL_VAL); }
1572
- string type() { return "null"; }
1573
- static string type_name() { return "null"; }
1574
- bool is_invisible() { return true; }
1639
+ Null(ParserState pstate) : Value(pstate) { concrete_type(NULL_VAL); }
1640
+ std::string type() { return "null"; }
1641
+ static std::string type_name() { return "null"; }
1642
+ bool is_invisible() const { return true; }
1575
1643
  operator bool() { return false; }
1576
1644
  bool is_false() { return true; }
1577
1645
 
1578
- virtual bool operator==(Expression& rhs) const
1579
- {
1580
- return rhs.concrete_type() == NULL_VAL;
1581
- }
1582
-
1583
1646
  virtual size_t hash()
1584
1647
  {
1585
- return 0;
1648
+ return -1;
1586
1649
  }
1587
1650
 
1588
- ATTACH_OPERATIONS();
1651
+ virtual bool operator== (const Expression& rhs) const;
1652
+ virtual std::string to_string(bool compressed = false, int precision = 5) const;
1653
+
1654
+ ATTACH_OPERATIONS()
1589
1655
  };
1590
1656
 
1591
1657
  /////////////////////////////////
1592
1658
  // Thunks for delayed evaluation.
1593
1659
  /////////////////////////////////
1594
1660
  class Thunk : public Expression {
1595
- ADD_PROPERTY(Expression*, expression);
1596
- ADD_PROPERTY(Env*, environment);
1661
+ ADD_PROPERTY(Expression*, expression)
1662
+ ADD_PROPERTY(Env*, environment)
1597
1663
  public:
1598
1664
  Thunk(ParserState pstate, Expression* exp, Env* env = 0)
1599
1665
  : Expression(pstate), expression_(exp), environment_(env)
@@ -1604,19 +1670,19 @@ namespace Sass {
1604
1670
  // Individual parameter objects for mixins and functions.
1605
1671
  /////////////////////////////////////////////////////////
1606
1672
  class Parameter : public AST_Node {
1607
- ADD_PROPERTY(string, name);
1608
- ADD_PROPERTY(Expression*, default_value);
1609
- ADD_PROPERTY(bool, is_rest_parameter);
1673
+ ADD_PROPERTY(std::string, name)
1674
+ ADD_PROPERTY(Expression*, default_value)
1675
+ ADD_PROPERTY(bool, is_rest_parameter)
1610
1676
  public:
1611
1677
  Parameter(ParserState pstate,
1612
- string n, Expression* def = 0, bool rest = false)
1678
+ std::string n, Expression* def = 0, bool rest = false)
1613
1679
  : AST_Node(pstate), name_(n), default_value_(def), is_rest_parameter_(rest)
1614
1680
  {
1615
1681
  if (default_value_ && is_rest_parameter_) {
1616
1682
  error("variable-length parameter may not have a default value", pstate);
1617
1683
  }
1618
1684
  }
1619
- ATTACH_OPERATIONS();
1685
+ ATTACH_OPERATIONS()
1620
1686
  };
1621
1687
 
1622
1688
  /////////////////////////////////////////////////////////////////////////
@@ -1625,8 +1691,8 @@ namespace Sass {
1625
1691
  // required parameters).
1626
1692
  /////////////////////////////////////////////////////////////////////////
1627
1693
  class Parameters : public AST_Node, public Vectorized<Parameter*> {
1628
- ADD_PROPERTY(bool, has_optional_parameters);
1629
- ADD_PROPERTY(bool, has_rest_parameter);
1694
+ ADD_PROPERTY(bool, has_optional_parameters)
1695
+ ADD_PROPERTY(bool, has_rest_parameter)
1630
1696
  protected:
1631
1697
  void adjust_after_pushing(Parameter* p)
1632
1698
  {
@@ -1658,60 +1724,37 @@ namespace Sass {
1658
1724
  has_optional_parameters_(false),
1659
1725
  has_rest_parameter_(false)
1660
1726
  { }
1661
- ATTACH_OPERATIONS();
1662
- };
1663
-
1664
- //////////////////////////////////////////////////////////////////////////////////////////
1665
- // Additional method on Lists to retrieve values directly or from an encompassed Argument.
1666
- //////////////////////////////////////////////////////////////////////////////////////////
1667
- inline Expression* List::value_at_index(size_t i) { return is_arglist_ ? ((Argument*)(*this)[i])->value() : (*this)[i]; }
1668
-
1669
- ////////////
1670
- // The Parent Selector Expression.
1671
- ////////////
1672
- class Parent_Selector : public Expression {
1673
- ADD_PROPERTY(Selector*, selector);
1674
- public:
1675
- Parent_Selector(ParserState pstate, Selector* r = 0)
1676
- : Expression(pstate), selector_(r)
1677
- { concrete_type(SELECTOR); }
1678
- virtual Selector* selector() { return selector_; }
1679
- string type() { return "selector"; }
1680
- static string type_name() { return "selector"; }
1681
-
1682
- ATTACH_OPERATIONS();
1727
+ ATTACH_OPERATIONS()
1683
1728
  };
1684
1729
 
1685
1730
  /////////////////////////////////////////
1686
1731
  // Abstract base class for CSS selectors.
1687
1732
  /////////////////////////////////////////
1688
- class Selector : public AST_Node {
1689
- ADD_PROPERTY(bool, has_reference);
1690
- ADD_PROPERTY(bool, has_placeholder);
1733
+ class Selector : public Expression {
1734
+ ADD_PROPERTY(bool, has_reference)
1735
+ ADD_PROPERTY(bool, has_placeholder)
1691
1736
  // line break before list separator
1692
- ADD_PROPERTY(bool, has_line_feed);
1737
+ ADD_PROPERTY(bool, has_line_feed)
1693
1738
  // line break after list separator
1694
- ADD_PROPERTY(bool, has_line_break);
1739
+ ADD_PROPERTY(bool, has_line_break)
1695
1740
  // maybe we have optional flag
1696
- ADD_PROPERTY(bool, is_optional);
1741
+ ADD_PROPERTY(bool, is_optional)
1697
1742
  // parent block pointers
1698
- ADD_PROPERTY(Block*, last_block);
1699
- ADD_PROPERTY(Media_Block*, media_block);
1743
+ ADD_PROPERTY(Media_Block*, media_block)
1700
1744
  public:
1701
1745
  Selector(ParserState pstate, bool r = false, bool h = false)
1702
- : AST_Node(pstate),
1746
+ : Expression(pstate),
1703
1747
  has_reference_(r),
1704
1748
  has_placeholder_(h),
1705
1749
  has_line_feed_(false),
1706
1750
  has_line_break_(false),
1707
1751
  is_optional_(false),
1708
1752
  media_block_(0)
1709
- { }
1753
+ { concrete_type(SELECTOR); }
1710
1754
  virtual ~Selector() = 0;
1711
- // virtual Selector_Placeholder* find_placeholder();
1712
1755
  virtual unsigned long specificity() {
1713
1756
  return Constants::Specificity_Universal;
1714
- };
1757
+ }
1715
1758
  };
1716
1759
  inline Selector::~Selector() { }
1717
1760
 
@@ -1720,72 +1763,125 @@ namespace Sass {
1720
1763
  // re-parsed into a normal selector class.
1721
1764
  /////////////////////////////////////////////////////////////////////////
1722
1765
  class Selector_Schema : public Selector {
1723
- ADD_PROPERTY(String*, contents);
1766
+ ADD_PROPERTY(String*, contents)
1767
+ ADD_PROPERTY(bool, at_root);
1724
1768
  public:
1725
1769
  Selector_Schema(ParserState pstate, String* c)
1726
- : Selector(pstate), contents_(c)
1770
+ : Selector(pstate), contents_(c), at_root_(false)
1727
1771
  { }
1728
- ATTACH_OPERATIONS();
1772
+ ATTACH_OPERATIONS()
1729
1773
  };
1730
1774
 
1731
1775
  ////////////////////////////////////////////
1732
1776
  // Abstract base class for simple selectors.
1733
1777
  ////////////////////////////////////////////
1734
1778
  class Simple_Selector : public Selector {
1779
+ ADD_PROPERTY(std::string, ns);
1780
+ ADD_PROPERTY(std::string, name)
1781
+ ADD_PROPERTY(bool, has_ns)
1735
1782
  public:
1736
- Simple_Selector(ParserState pstate)
1737
- : Selector(pstate)
1738
- { }
1783
+ Simple_Selector(ParserState pstate, std::string n = "")
1784
+ : Selector(pstate), ns_(""), name_(n), has_ns_(false)
1785
+ {
1786
+ size_t pos = n.find('|');
1787
+ // found some namespace
1788
+ if (pos != std::string::npos) {
1789
+ has_ns_ = true;
1790
+ ns_ = n.substr(0, pos);
1791
+ name_ = n.substr(pos + 1);
1792
+ }
1793
+ }
1794
+ virtual std::string ns_name() const
1795
+ {
1796
+ std::string name("");
1797
+ if (has_ns_)
1798
+ name += ns_ + "|";
1799
+ return name + name_;
1800
+ }
1801
+ // namespace query functions
1802
+ bool is_universal_ns() const
1803
+ {
1804
+ return has_ns_ && ns_ == "*";
1805
+ }
1806
+ bool has_universal_ns() const
1807
+ {
1808
+ return !has_ns_ || ns_ == "*";
1809
+ }
1810
+ bool is_empty_ns() const
1811
+ {
1812
+ return !has_ns_ || ns_ == "";
1813
+ }
1814
+ bool has_empty_ns() const
1815
+ {
1816
+ return has_ns_ && ns_ == "";
1817
+ }
1818
+ bool has_qualified_ns() const
1819
+ {
1820
+ return has_ns_ && ns_ != "" && ns_ != "*";
1821
+ }
1822
+ // name query functions
1823
+ bool is_universal() const
1824
+ {
1825
+ return name_ == "*";
1826
+ }
1827
+
1739
1828
  virtual ~Simple_Selector() = 0;
1740
1829
  virtual Compound_Selector* unify_with(Compound_Selector*, Context&);
1830
+ virtual bool has_parent_ref() { return false; };
1741
1831
  virtual bool is_pseudo_element() { return false; }
1742
1832
  virtual bool is_pseudo_class() { return false; }
1743
1833
 
1834
+ virtual bool is_superselector_of(Compound_Selector* sub) { return false; }
1835
+
1744
1836
  bool operator==(const Simple_Selector& rhs) const;
1745
1837
  inline bool operator!=(const Simple_Selector& rhs) const { return !(*this == rhs); }
1746
1838
 
1747
1839
  bool operator<(const Simple_Selector& rhs) const;
1840
+ ATTACH_OPERATIONS();
1748
1841
  };
1749
1842
  inline Simple_Selector::~Simple_Selector() { }
1750
1843
 
1751
- /////////////////////////////////////
1752
- // Parent references (i.e., the "&").
1753
- /////////////////////////////////////
1754
- class Selector_Reference : public Simple_Selector {
1755
- ADD_PROPERTY(Selector*, selector);
1756
- public:
1757
- Selector_Reference(ParserState pstate, Selector* r = 0)
1758
- : Simple_Selector(pstate), selector_(r)
1844
+
1845
+ //////////////////////////////////
1846
+ // The Parent Selector Expression.
1847
+ //////////////////////////////////
1848
+ // parent selectors can occur in selectors but also
1849
+ // inside strings in declarations (Compound_Selector).
1850
+ // only one simple parent selector means the first case.
1851
+ class Parent_Selector : public Simple_Selector {
1852
+ public:
1853
+ Parent_Selector(ParserState pstate)
1854
+ : Simple_Selector(pstate, "&")
1759
1855
  { has_reference(true); }
1856
+ virtual bool has_parent_ref() { return true; };
1760
1857
  virtual unsigned long specificity()
1761
1858
  {
1762
- if (!selector()) return 0;
1763
- return selector()->specificity();
1859
+ return 0;
1764
1860
  }
1765
- ATTACH_OPERATIONS();
1861
+ std::string type() { return "selector"; }
1862
+ static std::string type_name() { return "selector"; }
1863
+ ATTACH_OPERATIONS()
1766
1864
  };
1767
1865
 
1768
1866
  /////////////////////////////////////////////////////////////////////////
1769
1867
  // Placeholder selectors (e.g., "%foo") for use in extend-only selectors.
1770
1868
  /////////////////////////////////////////////////////////////////////////
1771
1869
  class Selector_Placeholder : public Simple_Selector {
1772
- ADD_PROPERTY(string, name);
1773
1870
  public:
1774
- Selector_Placeholder(ParserState pstate, string n)
1775
- : Simple_Selector(pstate), name_(n)
1871
+ Selector_Placeholder(ParserState pstate, std::string n)
1872
+ : Simple_Selector(pstate, n)
1776
1873
  { has_placeholder(true); }
1777
1874
  // virtual Selector_Placeholder* find_placeholder();
1778
- ATTACH_OPERATIONS();
1875
+ ATTACH_OPERATIONS()
1779
1876
  };
1780
1877
 
1781
1878
  /////////////////////////////////////////////////////////////////////
1782
1879
  // Type selectors (and the universal selector) -- e.g., div, span, *.
1783
1880
  /////////////////////////////////////////////////////////////////////
1784
1881
  class Type_Selector : public Simple_Selector {
1785
- ADD_PROPERTY(string, name);
1786
1882
  public:
1787
- Type_Selector(ParserState pstate, string n)
1788
- : Simple_Selector(pstate), name_(n)
1883
+ Type_Selector(ParserState pstate, std::string n)
1884
+ : Simple_Selector(pstate, n)
1789
1885
  { }
1790
1886
  virtual unsigned long specificity()
1791
1887
  {
@@ -1793,18 +1889,18 @@ namespace Sass {
1793
1889
  if (name() == "*") return Constants::Specificity_Universal;
1794
1890
  else return Constants::Specificity_Type;
1795
1891
  }
1892
+ virtual Simple_Selector* unify_with(Simple_Selector*, Context&);
1796
1893
  virtual Compound_Selector* unify_with(Compound_Selector*, Context&);
1797
- ATTACH_OPERATIONS();
1894
+ ATTACH_OPERATIONS()
1798
1895
  };
1799
1896
 
1800
1897
  ////////////////////////////////////////////////
1801
1898
  // Selector qualifiers -- i.e., classes and ids.
1802
1899
  ////////////////////////////////////////////////
1803
1900
  class Selector_Qualifier : public Simple_Selector {
1804
- ADD_PROPERTY(string, name);
1805
1901
  public:
1806
- Selector_Qualifier(ParserState pstate, string n)
1807
- : Simple_Selector(pstate), name_(n)
1902
+ Selector_Qualifier(ParserState pstate, std::string n)
1903
+ : Simple_Selector(pstate, n)
1808
1904
  { }
1809
1905
  virtual unsigned long specificity()
1810
1906
  {
@@ -1813,25 +1909,28 @@ namespace Sass {
1813
1909
  else return Constants::Specificity_Type;
1814
1910
  }
1815
1911
  virtual Compound_Selector* unify_with(Compound_Selector*, Context&);
1816
- ATTACH_OPERATIONS();
1912
+ ATTACH_OPERATIONS()
1817
1913
  };
1818
1914
 
1819
1915
  ///////////////////////////////////////////////////
1820
1916
  // Attribute selectors -- e.g., [src*=".jpg"], etc.
1821
1917
  ///////////////////////////////////////////////////
1822
1918
  class Attribute_Selector : public Simple_Selector {
1823
- ADD_PROPERTY(string, name);
1824
- ADD_PROPERTY(string, matcher);
1825
- ADD_PROPERTY(String*, value); // might be interpolated
1919
+ ADD_PROPERTY(std::string, matcher)
1920
+ ADD_PROPERTY(String*, value) // might be interpolated
1826
1921
  public:
1827
- Attribute_Selector(ParserState pstate, string n, string m, String* v)
1828
- : Simple_Selector(pstate), name_(n), matcher_(m), value_(v)
1922
+ Attribute_Selector(ParserState pstate, std::string n, std::string m, String* v)
1923
+ : Simple_Selector(pstate, n), matcher_(m), value_(v)
1829
1924
  { }
1830
1925
  virtual unsigned long specificity()
1831
1926
  {
1832
1927
  return Constants::Specificity_Attr;
1833
1928
  }
1834
- ATTACH_OPERATIONS();
1929
+ bool operator==(const Simple_Selector& rhs) const;
1930
+ bool operator==(const Attribute_Selector& rhs) const;
1931
+ bool operator<(const Simple_Selector& rhs) const;
1932
+ bool operator<(const Attribute_Selector& rhs) const;
1933
+ ATTACH_OPERATIONS()
1835
1934
  };
1836
1935
 
1837
1936
  //////////////////////////////////////////////////////////////////
@@ -1841,7 +1940,7 @@ namespace Sass {
1841
1940
  /* Except :first-line, :first-letter, :before and :after */
1842
1941
  /* Note that pseudo-elements are restricted to one per selector */
1843
1942
  /* and occur only in the last simple_selector_sequence. */
1844
- inline bool is_pseudo_class_element(const string& name)
1943
+ inline bool is_pseudo_class_element(const std::string& name)
1845
1944
  {
1846
1945
  return name == ":before" ||
1847
1946
  name == ":after" ||
@@ -1850,11 +1949,10 @@ namespace Sass {
1850
1949
  }
1851
1950
 
1852
1951
  class Pseudo_Selector : public Simple_Selector {
1853
- ADD_PROPERTY(string, name);
1854
- ADD_PROPERTY(String*, expression);
1952
+ ADD_PROPERTY(String*, expression)
1855
1953
  public:
1856
- Pseudo_Selector(ParserState pstate, string n, String* expr = 0)
1857
- : Simple_Selector(pstate), name_(n), expression_(expr)
1954
+ Pseudo_Selector(ParserState pstate, std::string n, String* expr = 0)
1955
+ : Simple_Selector(pstate, n), expression_(expr)
1858
1956
  { }
1859
1957
 
1860
1958
  // A pseudo-class always consists of a "colon" (:) followed by the name
@@ -1885,26 +1983,28 @@ namespace Sass {
1885
1983
  return Constants::Specificity_Pseudo;
1886
1984
  }
1887
1985
  virtual Compound_Selector* unify_with(Compound_Selector*, Context&);
1888
- ATTACH_OPERATIONS();
1986
+ ATTACH_OPERATIONS()
1889
1987
  };
1890
1988
 
1891
1989
  /////////////////////////////////////////////////
1892
1990
  // Wrapped selector -- pseudo selector that takes a list of selectors as argument(s) e.g., :not(:first-of-type), :-moz-any(ol p.blah, ul, menu, dir)
1893
1991
  /////////////////////////////////////////////////
1894
1992
  class Wrapped_Selector : public Simple_Selector {
1895
- ADD_PROPERTY(string, name);
1896
- ADD_PROPERTY(Selector*, selector);
1993
+ ADD_PROPERTY(Selector*, selector)
1897
1994
  public:
1898
- Wrapped_Selector(ParserState pstate, string n, Selector* sel)
1899
- : Simple_Selector(pstate), name_(n), selector_(sel)
1995
+ Wrapped_Selector(ParserState pstate, std::string n, Selector* sel)
1996
+ : Simple_Selector(pstate, n), selector_(sel)
1900
1997
  { }
1998
+ virtual bool is_superselector_of(Wrapped_Selector* sub);
1901
1999
  // Selectors inside the negation pseudo-class are counted like any
1902
2000
  // other, but the negation itself does not count as a pseudo-class.
1903
2001
  virtual unsigned long specificity()
1904
2002
  {
1905
2003
  return selector_ ? selector_->specificity() : 0;
1906
2004
  }
1907
- ATTACH_OPERATIONS();
2005
+ bool operator==(const Simple_Selector& rhs) const;
2006
+ bool operator==(const Wrapped_Selector& rhs) const;
2007
+ ATTACH_OPERATIONS()
1908
2008
  };
1909
2009
 
1910
2010
  struct Complex_Selector_Pointer_Compare {
@@ -1915,10 +2015,11 @@ namespace Sass {
1915
2015
  // Simple selector sequences. Maintains flags indicating whether it contains
1916
2016
  // any parent references or placeholders, to simplify expansion.
1917
2017
  ////////////////////////////////////////////////////////////////////////////
1918
- typedef set<Complex_Selector*, Complex_Selector_Pointer_Compare> SourcesSet;
2018
+ typedef std::set<Complex_Selector*, Complex_Selector_Pointer_Compare> SourcesSet;
1919
2019
  class Compound_Selector : public Selector, public Vectorized<Simple_Selector*> {
1920
2020
  private:
1921
2021
  SourcesSet sources_;
2022
+ ADD_PROPERTY(bool, has_parent_reference);
1922
2023
  protected:
1923
2024
  void adjust_after_pushing(Simple_Selector* s)
1924
2025
  {
@@ -1928,24 +2029,40 @@ namespace Sass {
1928
2029
  public:
1929
2030
  Compound_Selector(ParserState pstate, size_t s = 0)
1930
2031
  : Selector(pstate),
1931
- Vectorized<Simple_Selector*>(s)
2032
+ Vectorized<Simple_Selector*>(s),
2033
+ has_parent_reference_(false)
1932
2034
  { }
2035
+ bool contains_placeholder() {
2036
+ for (size_t i = 0, L = length(); i < L; ++i) {
2037
+ if ((*this)[i]->has_placeholder()) return true;
2038
+ }
2039
+ return false;
2040
+ };
2041
+
2042
+ bool is_universal() const
2043
+ {
2044
+ return length() == 1 && (*this)[0]->is_universal();
2045
+ }
1933
2046
 
2047
+ Complex_Selector* to_complex(Memory_Manager& mem);
1934
2048
  Compound_Selector* unify_with(Compound_Selector* rhs, Context& ctx);
1935
2049
  // virtual Selector_Placeholder* find_placeholder();
2050
+ virtual bool has_parent_ref();
1936
2051
  Simple_Selector* base()
1937
2052
  {
1938
2053
  // Implement non-const in terms of const. Safe to const_cast since this method is non-const
1939
2054
  return const_cast<Simple_Selector*>(static_cast<const Compound_Selector*>(this)->base());
1940
2055
  }
1941
2056
  const Simple_Selector* base() const {
1942
- if (length() > 0 && typeid(*(*this)[0]) == typeid(Type_Selector))
2057
+ if (length() == 0) return 0;
2058
+ if (typeid(*(*this)[0]) == typeid(Type_Selector))
1943
2059
  return (*this)[0];
2060
+ // else cerr << "SERIOUSELY " << "\n";
1944
2061
  return 0;
1945
2062
  }
1946
- bool is_superselector_of(Compound_Selector* sub);
1947
- // bool is_superselector_of(Complex_Selector* sub);
1948
- // bool is_superselector_of(Selector_List* sub);
2063
+ virtual bool is_superselector_of(Compound_Selector* sub, std::string wrapped = "");
2064
+ virtual bool is_superselector_of(Complex_Selector* sub, std::string wrapped = "");
2065
+ virtual bool is_superselector_of(Selector_List* sub, std::string wrapped = "");
1949
2066
  virtual unsigned long specificity()
1950
2067
  {
1951
2068
  int sum = 0;
@@ -1953,13 +2070,13 @@ namespace Sass {
1953
2070
  { sum += (*this)[i]->specificity(); }
1954
2071
  return sum;
1955
2072
  }
2073
+
1956
2074
  bool is_empty_reference()
1957
2075
  {
1958
2076
  return length() == 1 &&
1959
- typeid(*(*this)[0]) == typeid(Selector_Reference) &&
1960
- !static_cast<Selector_Reference*>((*this)[0])->selector();
2077
+ typeid(*(*this)[0]) == typeid(Parent_Selector);
1961
2078
  }
1962
- vector<string> to_str_vec(); // sometimes need to convert to a flat "by-value" data structure
2079
+ std::vector<std::string> to_str_vec(); // sometimes need to convert to a flat "by-value" data structure
1963
2080
 
1964
2081
  bool operator<(const Compound_Selector& rhs) const;
1965
2082
 
@@ -1973,7 +2090,7 @@ namespace Sass {
1973
2090
  Compound_Selector* clone(Context&) const; // does not clone the Simple_Selector*s
1974
2091
 
1975
2092
  Compound_Selector* minus(Compound_Selector* rhs, Context& ctx);
1976
- ATTACH_OPERATIONS();
2093
+ ATTACH_OPERATIONS()
1977
2094
  };
1978
2095
 
1979
2096
  ////////////////////////////////////////////////////////////////////////////
@@ -1983,30 +2100,78 @@ namespace Sass {
1983
2100
  ////////////////////////////////////////////////////////////////////////////
1984
2101
  class Complex_Selector : public Selector {
1985
2102
  public:
1986
- enum Combinator { ANCESTOR_OF, PARENT_OF, PRECEDES, ADJACENT_TO };
2103
+ enum Combinator { ANCESTOR_OF, PARENT_OF, PRECEDES, ADJACENT_TO, REFERENCE };
1987
2104
  private:
1988
- ADD_PROPERTY(Combinator, combinator);
1989
- ADD_PROPERTY(Compound_Selector*, head);
1990
- ADD_PROPERTY(Complex_Selector*, tail);
1991
- public:
2105
+ ADD_PROPERTY(Combinator, combinator)
2106
+ ADD_PROPERTY(Compound_Selector*, head)
2107
+ ADD_PROPERTY(Complex_Selector*, tail)
2108
+ ADD_PROPERTY(String*, reference);
2109
+ public:
2110
+ bool contains_placeholder() {
2111
+ if (head() && head()->contains_placeholder()) return true;
2112
+ if (tail() && tail()->contains_placeholder()) return true;
2113
+ return false;
2114
+ };
1992
2115
  Complex_Selector(ParserState pstate,
1993
- Combinator c,
1994
- Compound_Selector* h,
1995
- Complex_Selector* t)
1996
- : Selector(pstate), combinator_(c), head_(h), tail_(t)
2116
+ Combinator c = ANCESTOR_OF,
2117
+ Compound_Selector* h = 0,
2118
+ Complex_Selector* t = 0,
2119
+ String* r = 0)
2120
+ : Selector(pstate), combinator_(c), head_(h), tail_(t), reference_(r)
1997
2121
  {
1998
2122
  if ((h && h->has_reference()) || (t && t->has_reference())) has_reference(true);
1999
2123
  if ((h && h->has_placeholder()) || (t && t->has_placeholder())) has_placeholder(true);
2000
2124
  }
2001
- Compound_Selector* base();
2125
+ virtual bool has_parent_ref();
2126
+
2127
+ Complex_Selector* skip_empty_reference()
2128
+ {
2129
+ if ((!head_ || !head_->length() || head_->is_empty_reference()) &&
2130
+ combinator() == Combinator::ANCESTOR_OF)
2131
+ {
2132
+ tail_->has_line_feed_ = this->has_line_feed_;
2133
+ // tail_->has_line_break_ = this->has_line_break_;
2134
+ return tail_ ? tail_->skip_empty_reference() : 0;
2135
+ }
2136
+ return this;
2137
+ }
2138
+
2139
+ // can still have a tail
2140
+ bool is_empty_ancestor() const
2141
+ {
2142
+ return (!head() || head()->length() == 0) &&
2143
+ combinator() == Combinator::ANCESTOR_OF;
2144
+ }
2145
+
2002
2146
  Complex_Selector* context(Context&);
2003
- Complex_Selector* innermost();
2004
- size_t length();
2005
- bool is_superselector_of(Compound_Selector* sub);
2006
- bool is_superselector_of(Complex_Selector* sub);
2007
- bool is_superselector_of(Selector_List* sub);
2147
+
2148
+
2149
+ // front returns the first real tail
2150
+ // skips over parent and empty ones
2151
+ const Complex_Selector* first() const;
2152
+
2153
+ // last returns the last real tail
2154
+ const Complex_Selector* last() const;
2155
+
2156
+ Selector_List* tails(Context& ctx, Selector_List* tails);
2157
+
2158
+ // unconstant accessors
2159
+ Complex_Selector* first();
2160
+ Complex_Selector* last();
2161
+
2162
+ // some shortcuts that should be removed
2163
+ const Complex_Selector* innermost() const { return last(); };
2164
+ Complex_Selector* innermost() { return last(); };
2165
+
2166
+ size_t length() const;
2167
+ Selector_List* parentize(Selector_List* parents, Context& ctx);
2168
+ virtual bool is_superselector_of(Compound_Selector* sub, std::string wrapping = "");
2169
+ virtual bool is_superselector_of(Complex_Selector* sub, std::string wrapping = "");
2170
+ virtual bool is_superselector_of(Selector_List* sub, std::string wrapping = "");
2008
2171
  // virtual Selector_Placeholder* find_placeholder();
2172
+ Selector_List* unify_with(Complex_Selector* rhs, Context& ctx);
2009
2173
  Combinator clear_innermost();
2174
+ void append(Context&, Complex_Selector*);
2010
2175
  void set_innermost(Complex_Selector*, Combinator);
2011
2176
  virtual unsigned long specificity() const
2012
2177
  {
@@ -2068,50 +2233,52 @@ namespace Sass {
2068
2233
  }
2069
2234
  Complex_Selector* clone(Context&) const; // does not clone Compound_Selector*s
2070
2235
  Complex_Selector* cloneFully(Context&) const; // clones Compound_Selector*s
2071
- // vector<Compound_Selector*> to_vector();
2072
- ATTACH_OPERATIONS();
2236
+ // std::vector<Compound_Selector*> to_vector();
2237
+ ATTACH_OPERATIONS()
2073
2238
  };
2074
2239
 
2075
- typedef deque<Complex_Selector*> ComplexSelectorDeque;
2240
+ typedef std::deque<Complex_Selector*> ComplexSelectorDeque;
2241
+ typedef Subset_Map<std::string, std::pair<Complex_Selector*, Compound_Selector*> > ExtensionSubsetMap;
2076
2242
 
2077
2243
  ///////////////////////////////////
2078
2244
  // Comma-separated selector groups.
2079
2245
  ///////////////////////////////////
2080
2246
  class Selector_List : public Selector, public Vectorized<Complex_Selector*> {
2081
- #ifdef DEBUG
2082
- ADD_PROPERTY(string, mCachedSelector);
2083
- #endif
2084
- ADD_PROPERTY(vector<string>, wspace);
2247
+ ADD_PROPERTY(std::vector<std::string>, wspace)
2085
2248
  protected:
2086
2249
  void adjust_after_pushing(Complex_Selector* c);
2087
2250
  public:
2088
2251
  Selector_List(ParserState pstate, size_t s = 0)
2089
2252
  : Selector(pstate), Vectorized<Complex_Selector*>(s), wspace_(0)
2090
2253
  { }
2254
+ // remove parent selector references
2255
+ // basically unwraps parsed selectors
2256
+ void remove_parent_selectors();
2091
2257
  // virtual Selector_Placeholder* find_placeholder();
2092
- bool is_superselector_of(Compound_Selector* sub);
2093
- bool is_superselector_of(Complex_Selector* sub);
2094
- bool is_superselector_of(Selector_List* sub);
2258
+ Selector_List* parentize(Selector_List* parents, Context& ctx);
2259
+ virtual bool is_superselector_of(Compound_Selector* sub, std::string wrapping = "");
2260
+ virtual bool is_superselector_of(Complex_Selector* sub, std::string wrapping = "");
2261
+ virtual bool is_superselector_of(Selector_List* sub, std::string wrapping = "");
2262
+ Selector_List* unify_with(Selector_List*, Context&);
2263
+ void populate_extends(Selector_List*, Context&, ExtensionSubsetMap&);
2095
2264
  virtual unsigned long specificity()
2096
2265
  {
2097
2266
  unsigned long sum = 0;
2267
+ unsigned long specificity = 0;
2098
2268
  for (size_t i = 0, L = length(); i < L; ++i)
2099
- { sum += (*this)[i]->specificity(); }
2269
+ {
2270
+ specificity = (*this)[i]->specificity();
2271
+ if (sum < specificity) sum = specificity;
2272
+ }
2100
2273
  return sum;
2101
2274
  }
2102
- // vector<Complex_Selector*> members() { return elements_; }
2103
- ATTACH_OPERATIONS();
2275
+ Selector_List* clone(Context&) const; // does not clone Compound_Selector*s
2276
+ Selector_List* cloneFully(Context&) const; // clones Compound_Selector*s
2277
+ virtual bool operator==(const Selector& rhs) const;
2278
+ virtual bool operator==(const Selector_List& rhs) const;
2279
+ ATTACH_OPERATIONS()
2104
2280
  };
2105
2281
 
2106
- inline bool Ruleset::is_invisible() {
2107
- bool is_invisible = true;
2108
- Selector_List* sl = static_cast<Selector_List*>(selector());
2109
- for (size_t i = 0, L = sl->length(); i < L && is_invisible; ++i)
2110
- is_invisible &= (*sl)[i]->has_placeholder();
2111
- return is_invisible;
2112
- }
2113
-
2114
-
2115
2282
  template<typename SelectorType>
2116
2283
  bool selectors_equal(const SelectorType& one, const SelectorType& two, bool simpleSelectorOrderDependent) {
2117
2284
  // Test for equality among selectors while differentiating between checks that demand the underlying Simple_Selector
@@ -2130,6 +2297,11 @@ namespace Sass {
2130
2297
  }
2131
2298
  }
2132
2299
 
2300
+ // compare function for sorting and probably other other uses
2301
+ struct cmp_complex_selector { inline bool operator() (const Complex_Selector* l, const Complex_Selector* r) { return (*l < *r); } };
2302
+ struct cmp_compound_selector { inline bool operator() (const Compound_Selector* l, const Compound_Selector* r) { return (*l < *r); } };
2303
+ struct cmp_simple_selector { inline bool operator() (const Simple_Selector* l, const Simple_Selector* r) { return (*l < *r); } };
2304
+
2133
2305
  }
2134
2306
 
2135
2307
  #ifdef __clang__