sassc 1.10.1 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -2
  3. data/ext/libsass/.github/CONTRIBUTING.md +65 -0
  4. data/ext/libsass/.github/ISSUE_TEMPLATE.md +29 -0
  5. data/ext/libsass/Makefile +8 -3
  6. data/ext/libsass/Makefile.conf +28 -22
  7. data/ext/libsass/Readme.md +14 -7
  8. data/ext/libsass/configure.ac +5 -8
  9. data/ext/libsass/docs/api-context-internal.md +3 -0
  10. data/ext/libsass/docs/api-context.md +7 -0
  11. data/ext/libsass/docs/api-doc.md +4 -0
  12. data/ext/libsass/docs/api-importer.md +2 -0
  13. data/ext/libsass/docs/api-value-example.md +55 -0
  14. data/ext/libsass/docs/api-value.md +49 -22
  15. data/ext/libsass/docs/implementations.md +4 -0
  16. data/ext/libsass/include/sass/base.h +5 -4
  17. data/ext/libsass/include/sass/context.h +3 -0
  18. data/ext/libsass/include/sass/values.h +28 -27
  19. data/ext/libsass/include/sass/version.h +1 -1
  20. data/ext/libsass/include/sass2scss.h +1 -1
  21. data/ext/libsass/script/ci-build-libsass +3 -3
  22. data/ext/libsass/script/ci-install-deps +12 -3
  23. data/ext/libsass/src/ast.cpp +321 -212
  24. data/ext/libsass/src/ast.hpp +273 -165
  25. data/ext/libsass/src/ast_factory.hpp +4 -5
  26. data/ext/libsass/src/ast_fwd_decl.hpp +8 -7
  27. data/ext/libsass/src/bind.cpp +2 -7
  28. data/ext/libsass/src/bind.hpp +0 -1
  29. data/ext/libsass/src/check_nesting.cpp +379 -0
  30. data/ext/libsass/src/check_nesting.hpp +60 -0
  31. data/ext/libsass/src/constants.cpp +7 -6
  32. data/ext/libsass/src/constants.hpp +2 -1
  33. data/ext/libsass/src/context.cpp +7 -1
  34. data/ext/libsass/src/context.hpp +1 -1
  35. data/ext/libsass/src/cssize.cpp +76 -32
  36. data/ext/libsass/src/cssize.hpp +7 -8
  37. data/ext/libsass/src/debugger.hpp +70 -40
  38. data/ext/libsass/src/error_handling.cpp +15 -2
  39. data/ext/libsass/src/error_handling.hpp +19 -0
  40. data/ext/libsass/src/eval.cpp +107 -161
  41. data/ext/libsass/src/eval.hpp +12 -8
  42. data/ext/libsass/src/expand.cpp +81 -74
  43. data/ext/libsass/src/expand.hpp +13 -12
  44. data/ext/libsass/src/extend.cpp +149 -142
  45. data/ext/libsass/src/extend.hpp +10 -3
  46. data/ext/libsass/src/file.cpp +2 -1
  47. data/ext/libsass/src/functions.cpp +96 -59
  48. data/ext/libsass/src/functions.hpp +2 -2
  49. data/ext/libsass/src/inspect.cpp +33 -45
  50. data/ext/libsass/src/inspect.hpp +7 -7
  51. data/ext/libsass/src/json.cpp +17 -5
  52. data/ext/libsass/src/lexer.cpp +3 -3
  53. data/ext/libsass/src/listize.cpp +10 -10
  54. data/ext/libsass/src/listize.hpp +3 -3
  55. data/ext/libsass/src/node.cpp +30 -30
  56. data/ext/libsass/src/node.hpp +13 -13
  57. data/ext/libsass/src/operation.hpp +21 -19
  58. data/ext/libsass/src/output.cpp +48 -103
  59. data/ext/libsass/src/output.hpp +0 -1
  60. data/ext/libsass/src/parser.cpp +161 -133
  61. data/ext/libsass/src/parser.hpp +10 -7
  62. data/ext/libsass/src/remove_placeholders.cpp +6 -6
  63. data/ext/libsass/src/remove_placeholders.hpp +1 -1
  64. data/ext/libsass/src/sass.cpp +21 -0
  65. data/ext/libsass/src/sass.hpp +8 -1
  66. data/ext/libsass/src/sass2scss.cpp +14 -3
  67. data/ext/libsass/src/sass_context.cpp +69 -24
  68. data/ext/libsass/src/sass_context.hpp +3 -0
  69. data/ext/libsass/src/source_map.cpp +22 -10
  70. data/ext/libsass/src/to_value.cpp +2 -2
  71. data/ext/libsass/src/to_value.hpp +1 -1
  72. data/ext/libsass/src/units.hpp +3 -1
  73. data/ext/libsass/src/util.cpp +20 -16
  74. data/ext/libsass/src/util.hpp +2 -1
  75. data/ext/libsass/win/libsass.targets +2 -0
  76. data/ext/libsass/win/libsass.vcxproj.filters +6 -0
  77. data/lib/sassc/engine.rb +5 -0
  78. data/lib/sassc/native/native_functions_api.rb +13 -1
  79. data/lib/sassc/script/value_conversion.rb +11 -1
  80. data/lib/sassc/script/value_conversion/list.rb +23 -0
  81. data/lib/sassc/version.rb +1 -1
  82. data/test/engine_test.rb +18 -2
  83. data/test/functions_test.rb +30 -0
  84. data/test/native_test.rb +1 -1
  85. metadata +8 -3
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "ast.hpp"
5
5
  #include "context.hpp"
6
+ #include "listize.hpp"
6
7
  #include "operation.hpp"
7
8
  #include "environment.hpp"
8
9
 
@@ -22,11 +23,12 @@ namespace Sass {
22
23
  Eval(Expand& exp);
23
24
  ~Eval();
24
25
 
26
+ bool force;
25
27
  bool is_in_comment;
26
28
 
27
29
  Env* environment();
28
30
  Context& context();
29
- Selector_List* selector();
31
+ CommaSequence_Selector* selector();
30
32
  Backtrace* backtrace();
31
33
 
32
34
  // for evaluating function bodies
@@ -50,11 +52,12 @@ namespace Sass {
50
52
  Expression* operator()(Variable*);
51
53
  Expression* operator()(Textual*);
52
54
  Expression* operator()(Number*);
55
+ Expression* operator()(Color*);
53
56
  Expression* operator()(Boolean*);
54
57
  Expression* operator()(String_Schema*);
55
58
  Expression* operator()(String_Quoted*);
56
59
  Expression* operator()(String_Constant*);
57
- // Expression* operator()(Selector_List*);
60
+ // Expression* operator()(CommaSequence_Selector*);
58
61
  Expression* operator()(Media_Query*);
59
62
  Expression* operator()(Media_Query_Expression*);
60
63
  Expression* operator()(At_Root_Query*);
@@ -68,17 +71,18 @@ namespace Sass {
68
71
  Expression* operator()(Comment*);
69
72
 
70
73
  // these will return selectors
71
- Selector_List* operator()(Selector_List*);
72
- Selector_List* operator()(Complex_Selector*);
74
+ CommaSequence_Selector* operator()(CommaSequence_Selector*);
75
+ CommaSequence_Selector* operator()(Sequence_Selector*);
73
76
  Attribute_Selector* operator()(Attribute_Selector*);
74
77
  // they don't have any specific implementatio (yet)
75
- Type_Selector* operator()(Type_Selector* s) { return s; };
78
+ Element_Selector* operator()(Element_Selector* s) { return s; };
76
79
  Pseudo_Selector* operator()(Pseudo_Selector* s) { return s; };
77
80
  Wrapped_Selector* operator()(Wrapped_Selector* s) { return s; };
78
- Selector_Qualifier* operator()(Selector_Qualifier* s) { return s; };
79
- Selector_Placeholder* operator()(Selector_Placeholder* s) { return s; };
81
+ Class_Selector* operator()(Class_Selector* s) { return s; };
82
+ Id_Selector* operator()(Id_Selector* s) { return s; };
83
+ Placeholder_Selector* operator()(Placeholder_Selector* s) { return s; };
80
84
  // actual evaluated selectors
81
- Selector_List* operator()(Selector_Schema*);
85
+ CommaSequence_Selector* operator()(Selector_Schema*);
82
86
  Expression* operator()(Parent_Selector*);
83
87
 
84
88
  template <typename U>
@@ -11,17 +11,23 @@
11
11
 
12
12
  namespace Sass {
13
13
 
14
- Expand::Expand(Context& ctx, Env* env, Backtrace* bt)
14
+ // simple endless recursion protection
15
+ const unsigned int maxRecursion = 500;
16
+ static unsigned int recursions = 0;
17
+
18
+ Expand::Expand(Context& ctx, Env* env, Backtrace* bt, std::vector<CommaSequence_Selector*>* stack)
15
19
  : ctx(ctx),
16
20
  eval(Eval(*this)),
17
21
  env_stack(std::vector<Env*>()),
18
22
  block_stack(std::vector<Block*>()),
19
23
  call_stack(std::vector<AST_Node*>()),
20
24
  property_stack(std::vector<String*>()),
21
- selector_stack(std::vector<Selector_List*>()),
25
+ selector_stack(std::vector<CommaSequence_Selector*>()),
22
26
  media_block_stack(std::vector<Media_Block*>()),
23
27
  backtrace_stack(std::vector<Backtrace*>()),
24
- in_keyframes(false)
28
+ in_keyframes(false),
29
+ at_root_without_rule(false),
30
+ old_at_root_without_rule(false)
25
31
  {
26
32
  env_stack.push_back(0);
27
33
  env_stack.push_back(env);
@@ -29,7 +35,8 @@ namespace Sass {
29
35
  call_stack.push_back(0);
30
36
  // import_stack.push_back(0);
31
37
  property_stack.push_back(0);
32
- selector_stack.push_back(0);
38
+ if (stack == NULL) { selector_stack.push_back(0); }
39
+ else { selector_stack.insert(selector_stack.end(), stack->begin(), stack->end()); }
33
40
  media_block_stack.push_back(0);
34
41
  backtrace_stack.push_back(0);
35
42
  backtrace_stack.push_back(bt);
@@ -47,7 +54,7 @@ namespace Sass {
47
54
  return 0;
48
55
  }
49
56
 
50
- Selector_List* Expand::selector()
57
+ CommaSequence_Selector* Expand::selector()
51
58
  {
52
59
  if (selector_stack.size() > 0)
53
60
  return selector_stack.back();
@@ -86,23 +93,26 @@ namespace Sass {
86
93
 
87
94
  Statement* Expand::operator()(Ruleset* r)
88
95
  {
89
- // reset when leaving scope
96
+ LOCAL_FLAG(old_at_root_without_rule, at_root_without_rule);
90
97
 
91
98
  if (in_keyframes) {
92
99
  Keyframe_Rule* k = SASS_MEMORY_NEW(ctx.mem, Keyframe_Rule, r->pstate(), r->block()->perform(this)->block());
93
100
  if (r->selector()) {
94
101
  selector_stack.push_back(0);
95
- k->selector(static_cast<Selector_List*>(r->selector()->perform(&eval)));
102
+ k->selector(static_cast<CommaSequence_Selector*>(r->selector()->perform(&eval)));
96
103
  selector_stack.pop_back();
97
104
  }
98
105
  return k;
99
106
  }
100
107
 
108
+ // reset when leaving scope
109
+ LOCAL_FLAG(at_root_without_rule, false);
110
+
101
111
  // do some special checks for the base level rules
102
112
  if (r->is_root()) {
103
- if (Selector_List* selector_list = dynamic_cast<Selector_List*>(r->selector())) {
104
- for (Complex_Selector* complex_selector : selector_list->elements()) {
105
- Complex_Selector* tail = complex_selector;
113
+ if (CommaSequence_Selector* selector_list = dynamic_cast<CommaSequence_Selector*>(r->selector())) {
114
+ for (Sequence_Selector* complex_selector : selector_list->elements()) {
115
+ Sequence_Selector* tail = complex_selector;
106
116
  while (tail) {
107
117
  if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
108
118
  if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
@@ -116,13 +126,13 @@ namespace Sass {
116
126
  }
117
127
 
118
128
  Expression* ex = r->selector()->perform(&eval);
119
- Selector_List* sel = dynamic_cast<Selector_List*>(ex);
129
+ CommaSequence_Selector* sel = dynamic_cast<CommaSequence_Selector*>(ex);
120
130
  if (sel == 0) throw std::runtime_error("Expanded null selector");
121
131
 
122
132
  if (sel->length() == 0 || sel->has_parent_ref()) {
123
133
  bool has_parent_selector = false;
124
134
  for (size_t i = 0, L = selector_stack.size(); i < L && !has_parent_selector; i++) {
125
- Selector_List* ll = selector_stack.at(i);
135
+ CommaSequence_Selector* ll = selector_stack.at(i);
126
136
  has_parent_selector = ll != 0 && ll->length() > 0;
127
137
  }
128
138
  if (!has_parent_selector) {
@@ -131,10 +141,9 @@ namespace Sass {
131
141
  }
132
142
 
133
143
  selector_stack.push_back(sel);
134
- Env* env = 0;
144
+ Env env(environment());
135
145
  if (block_stack.back()->is_root()) {
136
- env = new Env(environment());
137
- env_stack.push_back(env);
146
+ env_stack.push_back(&env);
138
147
  }
139
148
  sel->set_media_block(media_block_stack.back());
140
149
  Block* blk = r->block()->perform(this)->block();
@@ -145,48 +154,14 @@ namespace Sass {
145
154
  selector_stack.pop_back();
146
155
  if (block_stack.back()->is_root()) {
147
156
  env_stack.pop_back();
148
- delete env;
149
157
  }
158
+
150
159
  rr->is_root(r->is_root());
151
160
  rr->tabs(r->tabs());
152
161
 
153
162
  return rr;
154
163
  }
155
164
 
156
- Statement* Expand::operator()(Propset* p)
157
- {
158
- property_stack.push_back(p->property_fragment());
159
- Block* expanded_block = p->block()->perform(this)->block();
160
-
161
- for (size_t i = 0, L = expanded_block->length(); i < L; ++i) {
162
- Statement* stm = (*expanded_block)[i];
163
- if (Declaration* dec = static_cast<Declaration*>(stm)) {
164
- String_Schema* combined_prop = SASS_MEMORY_NEW(ctx.mem, String_Schema, p->pstate());
165
- if (!property_stack.empty()) {
166
- *combined_prop << property_stack.back()->perform(&eval)
167
- << SASS_MEMORY_NEW(ctx.mem, String_Quoted,
168
- p->pstate(), "-")
169
- << dec->property(); // TODO: eval the prop into a string constant
170
- }
171
- else {
172
- *combined_prop << dec->property();
173
- }
174
- dec->property(combined_prop);
175
- *block_stack.back() << dec;
176
- }
177
- else if (typeid(*stm) == typeid(Comment)) {
178
- // drop comments in propsets
179
- }
180
- else {
181
- error("contents of namespaced properties must result in style declarations only", stm->pstate(), backtrace());
182
- }
183
- }
184
-
185
- property_stack.pop_back();
186
-
187
- return 0;
188
- }
189
-
190
165
  Statement* Expand::operator()(Supports_Block* f)
191
166
  {
192
167
  Expression* condition = f->condition()->perform(&eval);
@@ -219,16 +194,19 @@ namespace Sass {
219
194
  Statement* Expand::operator()(At_Root_Block* a)
220
195
  {
221
196
  Block* ab = a->block();
222
- // if (ab) ab->is_root(true);
223
197
  Expression* ae = a->expression();
198
+
224
199
  if (ae) ae = ae->perform(&eval);
225
200
  else ae = SASS_MEMORY_NEW(ctx.mem, At_Root_Query, a->pstate());
201
+
202
+ LOCAL_FLAG(at_root_without_rule, true);
203
+ LOCAL_FLAG(in_keyframes, false);
204
+
226
205
  Block* bb = ab ? ab->perform(this)->block() : 0;
227
206
  At_Root_Block* aa = SASS_MEMORY_NEW(ctx.mem, At_Root_Block,
228
207
  a->pstate(),
229
208
  bb,
230
209
  static_cast<At_Root_Query*>(ae));
231
- // aa->block()->is_root(true);
232
210
  return aa;
233
211
  }
234
212
 
@@ -254,15 +232,20 @@ namespace Sass {
254
232
 
255
233
  Statement* Expand::operator()(Declaration* d)
256
234
  {
235
+ Block* ab = d->block();
257
236
  String* old_p = d->property();
258
237
  String* new_p = static_cast<String*>(old_p->perform(&eval));
259
238
  Expression* value = d->value()->perform(&eval);
260
- if (!value || (value->is_invisible() && !d->is_important())) return 0;
239
+ Block* bb = ab ? ab->perform(this)->block() : 0;
240
+ if (!bb) {
241
+ if (!value || (value->is_invisible() && !d->is_important())) return 0;
242
+ }
261
243
  Declaration* decl = SASS_MEMORY_NEW(ctx.mem, Declaration,
262
244
  d->pstate(),
263
245
  new_p,
264
246
  value,
265
- d->is_important());
247
+ d->is_important(),
248
+ bb);
266
249
  decl->tabs(d->tabs());
267
250
  return decl;
268
251
  }
@@ -477,7 +460,7 @@ namespace Sass {
477
460
  if (expr->concrete_type() == Expression::MAP) {
478
461
  map = static_cast<Map*>(expr);
479
462
  }
480
- else if (Selector_List* ls = dynamic_cast<Selector_List*>(expr)) {
463
+ else if (CommaSequence_Selector* ls = dynamic_cast<CommaSequence_Selector*>(expr)) {
481
464
  Listize listize(ctx.mem);
482
465
  list = dynamic_cast<List*>(ls->perform(&listize));
483
466
  }
@@ -513,7 +496,7 @@ namespace Sass {
513
496
  }
514
497
  else {
515
498
  // bool arglist = list->is_arglist();
516
- if (list->length() == 1 && dynamic_cast<Selector_List*>(list)) {
499
+ if (list->length() == 1 && dynamic_cast<CommaSequence_Selector*>(list)) {
517
500
  list = dynamic_cast<Vectorized<Expression*>*>(list);
518
501
  }
519
502
  for (size_t i = 0, L = list->length(); i < L; ++i) {
@@ -573,11 +556,11 @@ namespace Sass {
573
556
  }
574
557
 
575
558
 
576
- void Expand::expand_selector_list(Selector* s, Selector_List* extender) {
559
+ void Expand::expand_selector_list(Selector* s, CommaSequence_Selector* extender) {
577
560
 
578
- if (Selector_List* sl = dynamic_cast<Selector_List*>(s)) {
579
- for (Complex_Selector* complex_selector : sl->elements()) {
580
- Complex_Selector* tail = complex_selector;
561
+ if (CommaSequence_Selector* sl = dynamic_cast<CommaSequence_Selector*>(s)) {
562
+ for (Sequence_Selector* complex_selector : sl->elements()) {
563
+ Sequence_Selector* tail = complex_selector;
581
564
  while (tail) {
582
565
  if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
583
566
  if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
@@ -590,24 +573,24 @@ namespace Sass {
590
573
  }
591
574
 
592
575
 
593
- Selector_List* contextualized = dynamic_cast<Selector_List*>(s->perform(&eval));
576
+ CommaSequence_Selector* contextualized = dynamic_cast<CommaSequence_Selector*>(s->perform(&eval));
594
577
  if (contextualized == NULL) return;
595
578
  for (auto complex_sel : contextualized->elements()) {
596
- Complex_Selector* c = complex_sel;
579
+ Sequence_Selector* c = complex_sel;
597
580
  if (!c->head() || c->tail()) {
598
581
  std::string sel_str(contextualized->to_string(ctx.c_options));
599
582
  error("Can't extend " + sel_str + ": can't extend nested selectors", c->pstate(), backtrace());
600
583
  }
601
- Compound_Selector* placeholder = c->head();
584
+ SimpleSequence_Selector* placeholder = c->head();
602
585
  if (contextualized->is_optional()) placeholder->is_optional(true);
603
586
  for (size_t i = 0, L = extender->length(); i < L; ++i) {
604
- Complex_Selector* sel = (*extender)[i];
587
+ Sequence_Selector* sel = (*extender)[i];
605
588
  if (!(sel->head() && sel->head()->length() > 0 &&
606
589
  dynamic_cast<Parent_Selector*>((*sel->head())[0])))
607
590
  {
608
- Compound_Selector* hh = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, (*extender)[i]->pstate());
591
+ SimpleSequence_Selector* hh = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, (*extender)[i]->pstate());
609
592
  hh->media_block((*extender)[i]->media_block());
610
- Complex_Selector* ssel = SASS_MEMORY_NEW(ctx.mem, Complex_Selector, (*extender)[i]->pstate());
593
+ Sequence_Selector* ssel = SASS_MEMORY_NEW(ctx.mem, Sequence_Selector, (*extender)[i]->pstate());
611
594
  ssel->media_block((*extender)[i]->media_block());
612
595
  if (sel->has_line_feed()) ssel->has_line_feed(true);
613
596
  Parent_Selector* ps = SASS_MEMORY_NEW(ctx.mem, Parent_Selector, (*extender)[i]->pstate());
@@ -626,13 +609,13 @@ namespace Sass {
626
609
 
627
610
  Statement* Expand::operator()(Extension* e)
628
611
  {
629
- if (Selector_List* extender = dynamic_cast<Selector_List*>(selector())) {
612
+ if (CommaSequence_Selector* extender = dynamic_cast<CommaSequence_Selector*>(selector())) {
630
613
  Selector* s = e->selector();
631
614
  if (Selector_Schema* schema = dynamic_cast<Selector_Schema*>(s)) {
632
615
  if (schema->has_parent_ref()) s = eval(schema);
633
616
  }
634
- if (Selector_List* sl = dynamic_cast<Selector_List*>(s)) {
635
- for (Complex_Selector* cs : *sl) {
617
+ if (CommaSequence_Selector* sl = dynamic_cast<CommaSequence_Selector*>(s)) {
618
+ for (Sequence_Selector* cs : *sl) {
636
619
  if (cs != NULL && cs->head() != NULL) {
637
620
  cs->head()->media_block(media_block_stack.back());
638
621
  }
@@ -673,6 +656,12 @@ namespace Sass {
673
656
 
674
657
  Statement* Expand::operator()(Mixin_Call* c)
675
658
  {
659
+ recursions ++;
660
+
661
+ if (recursions > maxRecursion) {
662
+ throw Exception::StackError(*c);
663
+ }
664
+
676
665
  Env* env = environment();
677
666
  std::string full_name(c->name() + "[m]");
678
667
  if (!env->has(full_name)) {
@@ -704,10 +693,23 @@ namespace Sass {
704
693
  }
705
694
 
706
695
  bind(std::string("Mixin"), c->name(), params, args, &ctx, &new_env, &eval);
707
- append_block(body);
708
- backtrace_stack.pop_back();
696
+
697
+ Block* trace_block = SASS_MEMORY_NEW(ctx.mem, Block, c->pstate());
698
+ Trace* trace = SASS_MEMORY_NEW(ctx.mem, Trace, c->pstate(), c->name(), trace_block);
699
+
700
+
701
+ block_stack.push_back(trace_block);
702
+ for (auto bb : *body) {
703
+ Statement* ith = bb->perform(this);
704
+ if (ith) *trace->block() << ith;
705
+ }
706
+ block_stack.pop_back();
707
+
709
708
  env_stack.pop_back();
710
- return 0;
709
+ backtrace_stack.pop_back();
710
+
711
+ recursions --;
712
+ return trace;
711
713
  }
712
714
 
713
715
  Statement* Expand::operator()(Content* c)
@@ -715,18 +717,23 @@ namespace Sass {
715
717
  Env* env = environment();
716
718
  // convert @content directives into mixin calls to the underlying thunk
717
719
  if (!env->has("@content[m]")) return 0;
720
+
718
721
  if (block_stack.back()->is_root()) {
719
722
  selector_stack.push_back(0);
720
723
  }
724
+
721
725
  Mixin_Call* call = SASS_MEMORY_NEW(ctx.mem, Mixin_Call,
722
726
  c->pstate(),
723
727
  "@content",
724
728
  SASS_MEMORY_NEW(ctx.mem, Arguments, c->pstate()));
725
- Statement* stm = call->perform(this);
729
+
730
+ Trace* trace = dynamic_cast<Trace*>(call->perform(this));
731
+
726
732
  if (block_stack.back()->is_root()) {
727
733
  selector_stack.pop_back();
728
734
  }
729
- return stm;
735
+
736
+ return trace;
730
737
  }
731
738
 
732
739
  // produce an error if something is not implemented
@@ -21,34 +21,35 @@ namespace Sass {
21
21
 
22
22
  Env* environment();
23
23
  Context& context();
24
- Selector_List* selector();
24
+ CommaSequence_Selector* selector();
25
25
  Backtrace* backtrace();
26
26
 
27
27
  Context& ctx;
28
28
  Eval eval;
29
29
 
30
30
  // it's easier to work with vectors
31
- std::vector<Env*> env_stack;
32
- std::vector<Block*> block_stack;
33
- std::vector<AST_Node*> call_stack;
34
- std::vector<String*> property_stack;
35
- std::vector<Selector_List*> selector_stack;
36
- std::vector<Media_Block*> media_block_stack;
37
- std::vector<Backtrace*>backtrace_stack;
38
- bool in_keyframes;
31
+ std::vector<Env*> env_stack;
32
+ std::vector<Block*> block_stack;
33
+ std::vector<AST_Node*> call_stack;
34
+ std::vector<String*> property_stack;
35
+ std::vector<CommaSequence_Selector*> selector_stack;
36
+ std::vector<Media_Block*> media_block_stack;
37
+ std::vector<Backtrace*> backtrace_stack;
38
+ bool in_keyframes;
39
+ bool at_root_without_rule;
40
+ bool old_at_root_without_rule;
39
41
 
40
42
  Statement* fallback_impl(AST_Node* n);
41
43
 
42
44
  private:
43
- void expand_selector_list(Selector*, Selector_List* extender);
45
+ void expand_selector_list(Selector*, CommaSequence_Selector* extender);
44
46
 
45
47
  public:
46
- Expand(Context&, Env*, Backtrace*);
48
+ Expand(Context&, Env*, Backtrace*, std::vector<CommaSequence_Selector*>* stack = NULL);
47
49
  ~Expand() { }
48
50
 
49
51
  Statement* operator()(Block*);
50
52
  Statement* operator()(Ruleset*);
51
- Statement* operator()(Propset*);
52
53
  Statement* operator()(Media_Block*);
53
54
  Statement* operator()(Supports_Block*);
54
55
  Statement* operator()(At_Root_Block*);
@@ -62,26 +62,26 @@
62
62
  namespace Sass {
63
63
 
64
64
 
65
- typedef std::pair<Complex_Selector*, Compound_Selector*> ExtensionPair;
65
+ typedef std::pair<Sequence_Selector*, SimpleSequence_Selector*> ExtensionPair;
66
66
  typedef std::vector<ExtensionPair> SubsetMapEntries;
67
67
 
68
68
  #ifdef DEBUG
69
69
 
70
70
  // TODO: move the ast specific ostream operators into ast.hpp/ast.cpp
71
- std::ostream& operator<<(std::ostream& os, const Complex_Selector::Combinator combinator) {
71
+ std::ostream& operator<<(std::ostream& os, const Sequence_Selector::Combinator combinator) {
72
72
  switch (combinator) {
73
- case Complex_Selector::ANCESTOR_OF: os << "\" \""; break;
74
- case Complex_Selector::PARENT_OF: os << "\">\""; break;
75
- case Complex_Selector::PRECEDES: os << "\"~\""; break;
76
- case Complex_Selector::ADJACENT_TO: os << "\"+\""; break;
77
- case Complex_Selector::REFERENCE: os << "\"/\""; break;
73
+ case Sequence_Selector::ANCESTOR_OF: os << "\" \""; break;
74
+ case Sequence_Selector::PARENT_OF: os << "\">\""; break;
75
+ case Sequence_Selector::PRECEDES: os << "\"~\""; break;
76
+ case Sequence_Selector::ADJACENT_TO: os << "\"+\""; break;
77
+ case Sequence_Selector::REFERENCE: os << "\"/\""; break;
78
78
  }
79
79
 
80
80
  return os;
81
81
  }
82
82
 
83
83
 
84
- std::ostream& operator<<(std::ostream& os, Compound_Selector& compoundSelector) {
84
+ std::ostream& operator<<(std::ostream& os, SimpleSequence_Selector& compoundSelector) {
85
85
  for (size_t i = 0, L = compoundSelector.length(); i < L; ++i) {
86
86
  if (i > 0) os << ", ";
87
87
  os << compoundSelector[i]->to_string();
@@ -94,7 +94,7 @@ namespace Sass {
94
94
  return os;
95
95
  }
96
96
 
97
- // Print a string representation of a Compound_Selector
97
+ // Print a string representation of a SimpleSequence_Selector
98
98
  static void printSimpleSelector(Simple_Selector* pSimpleSelector, const char* message=NULL, bool newline=true) {
99
99
 
100
100
  if (message) {
@@ -112,13 +112,13 @@ namespace Sass {
112
112
  }
113
113
  }
114
114
 
115
- // Print a string representation of a Compound_Selector
116
- typedef std::pair<Compound_Selector*, Complex_Selector*> SelsNewSeqPair;
115
+ // Print a string representation of a SimpleSequence_Selector
116
+ typedef std::pair<SimpleSequence_Selector*, Sequence_Selector*> SelsNewSeqPair;
117
117
  typedef std::vector<SelsNewSeqPair> SelsNewSeqPairCollection;
118
118
 
119
119
 
120
- // Print a string representation of a Compound_Selector
121
- static void printCompoundSelector(Compound_Selector* pCompoundSelector, const char* message=NULL, bool newline=true) {
120
+ // Print a string representation of a SimpleSequence_Selector
121
+ static void printCompoundSelector(SimpleSequence_Selector* pCompoundSelector, const char* message=NULL, bool newline=true) {
122
122
 
123
123
  if (message) {
124
124
  std::cerr << message;
@@ -136,13 +136,13 @@ namespace Sass {
136
136
  }
137
137
 
138
138
 
139
- std::ostream& operator<<(std::ostream& os, Complex_Selector& complexSelector) {
139
+ std::ostream& operator<<(std::ostream& os, Sequence_Selector& complexSelector) {
140
140
 
141
141
  os << "[";
142
- Complex_Selector* pIter = &complexSelector;
142
+ Sequence_Selector* pIter = &complexSelector;
143
143
  bool first = true;
144
144
  while (pIter) {
145
- if (pIter->combinator() != Complex_Selector::ANCESTOR_OF) {
145
+ if (pIter->combinator() != Sequence_Selector::ANCESTOR_OF) {
146
146
  if (!first) {
147
147
  os << ", ";
148
148
  }
@@ -169,8 +169,8 @@ namespace Sass {
169
169
  }
170
170
 
171
171
 
172
- // Print a string representation of a Complex_Selector
173
- static void printComplexSelector(Complex_Selector* pComplexSelector, const char* message=NULL, bool newline=true) {
172
+ // Print a string representation of a Sequence_Selector
173
+ static void printComplexSelector(Sequence_Selector* pComplexSelector, const char* message=NULL, bool newline=true) {
174
174
 
175
175
  if (message) {
176
176
  std::cerr << message;
@@ -201,8 +201,8 @@ namespace Sass {
201
201
  std::cerr << ", ";
202
202
  }
203
203
  std::cerr << "[";
204
- Compound_Selector* pSels = pair.first;
205
- Complex_Selector* pNewSelector = pair.second;
204
+ SimpleSequence_Selector* pSels = pair.first;
205
+ Sequence_Selector* pNewSelector = pair.second;
206
206
  std::cerr << "[" << *pSels << "], ";
207
207
  printComplexSelector(pNewSelector, NULL, false);
208
208
  }
@@ -225,7 +225,7 @@ namespace Sass {
225
225
  typedef std::deque<std::string> SourceStrings;
226
226
  SourceStrings sourceStrings;
227
227
  for (SourcesSet::iterator iterator = sources.begin(), iteratorEnd = sources.end(); iterator != iteratorEnd; ++iterator) {
228
- Complex_Selector* pSource = *iterator;
228
+ Sequence_Selector* pSource = *iterator;
229
229
  std::stringstream sstream;
230
230
  sstream << complexSelectorToNode(pSource, ctx);
231
231
  sourceStrings.push_back(sstream.str());
@@ -254,8 +254,8 @@ namespace Sass {
254
254
  os << "SUBSET_MAP_ENTRIES[";
255
255
 
256
256
  for (SubsetMapEntries::iterator iterator = entries.begin(), endIterator = entries.end(); iterator != endIterator; ++iterator) {
257
- Complex_Selector* pExtComplexSelector = iterator->first; // The selector up to where the @extend is (ie, the thing to merge)
258
- Compound_Selector* pExtCompoundSelector = iterator->second; // The stuff after the @extend
257
+ Sequence_Selector* pExtComplexSelector = iterator->first; // The selector up to where the @extend is (ie, the thing to merge)
258
+ SimpleSequence_Selector* pExtCompoundSelector = iterator->second; // The stuff after the @extend
259
259
 
260
260
  if (iterator != entries.begin()) {
261
261
  os << ", ";
@@ -287,17 +287,17 @@ namespace Sass {
287
287
  }
288
288
  #endif
289
289
 
290
- static bool parentSuperselector(Complex_Selector* pOne, Complex_Selector* pTwo, Context& ctx) {
291
- // TODO: figure out a better way to create a Complex_Selector from scratch
290
+ static bool parentSuperselector(Sequence_Selector* pOne, Sequence_Selector* pTwo, Context& ctx) {
291
+ // TODO: figure out a better way to create a Sequence_Selector from scratch
292
292
  // TODO: There's got to be a better way. This got ugly quick...
293
293
  Position noPosition(-1, -1, -1);
294
- Type_Selector fakeParent(ParserState("[FAKE]"), "temp");
295
- Compound_Selector fakeHead(ParserState("[FAKE]"), 1 /*size*/);
294
+ Element_Selector fakeParent(ParserState("[FAKE]"), "temp");
295
+ SimpleSequence_Selector fakeHead(ParserState("[FAKE]"), 1 /*size*/);
296
296
  fakeHead.elements().push_back(&fakeParent);
297
- Complex_Selector fakeParentContainer(ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
297
+ Sequence_Selector fakeParentContainer(ParserState("[FAKE]"), Sequence_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
298
298
 
299
- pOne->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
300
- pTwo->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
299
+ pOne->set_innermost(&fakeParentContainer, Sequence_Selector::ANCESTOR_OF);
300
+ pTwo->set_innermost(&fakeParentContainer, Sequence_Selector::ANCESTOR_OF);
301
301
 
302
302
  bool isSuperselector = pOne->is_superselector_of(pTwo);
303
303
 
@@ -318,7 +318,7 @@ namespace Sass {
318
318
  Node result = Node::createCollection();
319
319
 
320
320
  for (ComplexSelectorDeque::const_iterator iter = deque.begin(), iterEnd = deque.end(); iter != iterEnd; iter++) {
321
- Complex_Selector* pChild = *iter;
321
+ Sequence_Selector* pChild = *iter;
322
322
  result.collection()->push_back(complexSelectorToNode(pChild, ctx));
323
323
  }
324
324
 
@@ -331,7 +331,7 @@ namespace Sass {
331
331
 
332
332
  Context& mCtx;
333
333
 
334
- bool operator()(Complex_Selector* pOne, Complex_Selector* pTwo, Complex_Selector*& pOut) const {
334
+ bool operator()(Sequence_Selector* pOne, Sequence_Selector* pTwo, Sequence_Selector*& pOut) const {
335
335
  /*
336
336
  This code is based on the following block from ruby sass' subweave
337
337
  do |s1, s2|
@@ -347,7 +347,7 @@ namespace Sass {
347
347
  return true;
348
348
  }
349
349
 
350
- if (pOne->combinator() != Complex_Selector::ANCESTOR_OF || pTwo->combinator() != Complex_Selector::ANCESTOR_OF) {
350
+ if (pOne->combinator() != Sequence_Selector::ANCESTOR_OF || pTwo->combinator() != Sequence_Selector::ANCESTOR_OF) {
351
351
  return false;
352
352
  }
353
353
 
@@ -382,7 +382,7 @@ namespace Sass {
382
382
  }
383
383
 
384
384
 
385
- Complex_Selector* pCompareOut = NULL;
385
+ Sequence_Selector* pCompareOut = NULL;
386
386
  if (comparator(x[i], y[j], pCompareOut)) {
387
387
  DEBUG_PRINTLN(LCS, "RETURNING AFTER ELEM COMPARE")
388
388
  lcs_backtrace(c, x, y, i - 1, j - 1, comparator, out);
@@ -419,7 +419,7 @@ namespace Sass {
419
419
 
420
420
  for (size_t i = 1; i < x.size(); i++) {
421
421
  for (size_t j = 1; j < y.size(); j++) {
422
- Complex_Selector* pCompareOut = NULL;
422
+ Sequence_Selector* pCompareOut = NULL;
423
423
 
424
424
  if (comparator(x[i], y[j], pCompareOut)) {
425
425
  c[i][j] = c[i - 1][j - 1] + 1;
@@ -559,7 +559,7 @@ namespace Sass {
559
559
  for (NodeDeque::iterator seqs1Iter = seqs1.collection()->begin(), seqs1EndIter = seqs1.collection()->end(); seqs1Iter != seqs1EndIter; ++seqs1Iter) {
560
560
  Node& seq1 = *seqs1Iter;
561
561
 
562
- Complex_Selector* pSeq1 = nodeToComplexSelector(seq1, ctx);
562
+ Sequence_Selector* pSeq1 = nodeToComplexSelector(seq1, ctx);
563
563
 
564
564
  // Compute the maximum specificity. This requires looking at the "sources" of the sequence. See SimpleSequence.sources in the ruby code
565
565
  // for a good description of sources.
@@ -576,7 +576,7 @@ namespace Sass {
576
576
  DEBUG_EXEC(TRIM, printSourcesSet(sources, ctx, "TRIM SOURCES: "))
577
577
 
578
578
  for (SourcesSet::iterator sourcesSetIterator = sources.begin(), sourcesSetIteratorEnd = sources.end(); sourcesSetIterator != sourcesSetIteratorEnd; ++sourcesSetIterator) {
579
- const Complex_Selector* const pCurrentSelector = *sourcesSetIterator;
579
+ const Sequence_Selector* const pCurrentSelector = *sourcesSetIterator;
580
580
  maxSpecificity = std::max(maxSpecificity, pCurrentSelector->specificity());
581
581
  }
582
582
 
@@ -606,7 +606,7 @@ namespace Sass {
606
606
  for (NodeDeque::iterator seqs2Iter = seqs2.collection()->begin(), seqs2IterEnd = seqs2.collection()->end(); seqs2Iter != seqs2IterEnd; ++seqs2Iter) {
607
607
  Node& seq2 = *seqs2Iter;
608
608
 
609
- Complex_Selector* pSeq2 = nodeToComplexSelector(seq2, ctx);
609
+ Sequence_Selector* pSeq2 = nodeToComplexSelector(seq2, ctx);
610
610
 
611
611
  DEBUG_PRINTLN(TRIM, "SEQ2 SPEC: " << pSeq2->specificity())
612
612
  DEBUG_PRINTLN(TRIM, "IS SPEC: " << pSeq2->specificity() << " >= " << maxSpecificity << " " << (pSeq2->specificity() >= maxSpecificity ? "true" : "false"))
@@ -651,18 +651,18 @@ namespace Sass {
651
651
 
652
652
 
653
653
  static bool parentSuperselector(const Node& one, const Node& two, Context& ctx) {
654
- // TODO: figure out a better way to create a Complex_Selector from scratch
654
+ // TODO: figure out a better way to create a Sequence_Selector from scratch
655
655
  // TODO: There's got to be a better way. This got ugly quick...
656
656
  Position noPosition(-1, -1, -1);
657
- Type_Selector fakeParent(ParserState("[FAKE]"), "temp");
658
- Compound_Selector fakeHead(ParserState("[FAKE]"), 1 /*size*/);
657
+ Element_Selector fakeParent(ParserState("[FAKE]"), "temp");
658
+ SimpleSequence_Selector fakeHead(ParserState("[FAKE]"), 1 /*size*/);
659
659
  fakeHead.elements().push_back(&fakeParent);
660
- Complex_Selector fakeParentContainer(ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
660
+ Sequence_Selector fakeParentContainer(ParserState("[FAKE]"), Sequence_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
661
661
 
662
- Complex_Selector* pOneWithFakeParent = nodeToComplexSelector(one, ctx);
663
- pOneWithFakeParent->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
664
- Complex_Selector* pTwoWithFakeParent = nodeToComplexSelector(two, ctx);
665
- pTwoWithFakeParent->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
662
+ Sequence_Selector* pOneWithFakeParent = nodeToComplexSelector(one, ctx);
663
+ pOneWithFakeParent->set_innermost(&fakeParentContainer, Sequence_Selector::ANCESTOR_OF);
664
+ Sequence_Selector* pTwoWithFakeParent = nodeToComplexSelector(two, ctx);
665
+ pTwoWithFakeParent->set_innermost(&fakeParentContainer, Sequence_Selector::ANCESTOR_OF);
666
666
 
667
667
  return pOneWithFakeParent->is_superselector_of(pTwoWithFakeParent);
668
668
  }
@@ -970,7 +970,7 @@ namespace Sass {
970
970
  Node sel2 = seq2.collection()->back();
971
971
  seq2.collection()->pop_back();
972
972
 
973
- if (op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::PRECEDES) {
973
+ if (op1.combinator() == Sequence_Selector::PRECEDES && op2.combinator() == Sequence_Selector::PRECEDES) {
974
974
 
975
975
  if (sel1.selector()->is_superselector_of(sel2.selector())) {
976
976
 
@@ -987,9 +987,9 @@ namespace Sass {
987
987
  DEBUG_PRINTLN(ALL, "sel1: " << sel1)
988
988
  DEBUG_PRINTLN(ALL, "sel2: " << sel2)
989
989
 
990
- Complex_Selector* pMergedWrapper = sel1.selector()->clone(ctx); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
990
+ Sequence_Selector* pMergedWrapper = sel1.selector()->clone(ctx); // Clone the Sequence_Selector to get back to something we can transform to a node once we replace the head with the unification result
991
991
  // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
992
- Compound_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
992
+ SimpleSequence_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
993
993
  pMergedWrapper->head(pMerged);
994
994
 
995
995
  DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
@@ -998,22 +998,22 @@ namespace Sass {
998
998
 
999
999
  Node firstPerm = Node::createCollection();
1000
1000
  firstPerm.collection()->push_back(sel1);
1001
- firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1001
+ firstPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
1002
1002
  firstPerm.collection()->push_back(sel2);
1003
- firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1003
+ firstPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
1004
1004
  newRes.collection()->push_back(firstPerm);
1005
1005
 
1006
1006
  Node secondPerm = Node::createCollection();
1007
1007
  secondPerm.collection()->push_back(sel2);
1008
- secondPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1008
+ secondPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
1009
1009
  secondPerm.collection()->push_back(sel1);
1010
- secondPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1010
+ secondPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
1011
1011
  newRes.collection()->push_back(secondPerm);
1012
1012
 
1013
1013
  if (pMerged) {
1014
1014
  Node mergedPerm = Node::createCollection();
1015
1015
  mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper, ctx));
1016
- mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1016
+ mergedPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
1017
1017
  newRes.collection()->push_back(mergedPerm);
1018
1018
  }
1019
1019
 
@@ -1023,13 +1023,13 @@ namespace Sass {
1023
1023
 
1024
1024
  }
1025
1025
 
1026
- } else if (((op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::ADJACENT_TO)) || ((op1.combinator() == Complex_Selector::ADJACENT_TO && op2.combinator() == Complex_Selector::PRECEDES))) {
1026
+ } else if (((op1.combinator() == Sequence_Selector::PRECEDES && op2.combinator() == Sequence_Selector::ADJACENT_TO)) || ((op1.combinator() == Sequence_Selector::ADJACENT_TO && op2.combinator() == Sequence_Selector::PRECEDES))) {
1027
1027
 
1028
1028
  Node tildeSel = sel1;
1029
1029
  Node tildeOp = op1;
1030
1030
  Node plusSel = sel2;
1031
1031
  Node plusOp = op2;
1032
- if (op1.combinator() != Complex_Selector::PRECEDES) {
1032
+ if (op1.combinator() != Sequence_Selector::PRECEDES) {
1033
1033
  tildeSel = sel2;
1034
1034
  tildeOp = op2;
1035
1035
  plusSel = sel1;
@@ -1046,9 +1046,9 @@ namespace Sass {
1046
1046
  DEBUG_PRINTLN(ALL, "PLUS SEL: " << plusSel)
1047
1047
  DEBUG_PRINTLN(ALL, "TILDE SEL: " << tildeSel)
1048
1048
 
1049
- Complex_Selector* pMergedWrapper = plusSel.selector()->clone(ctx); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
1049
+ Sequence_Selector* pMergedWrapper = plusSel.selector()->clone(ctx); // Clone the Sequence_Selector to get back to something we can transform to a node once we replace the head with the unification result
1050
1050
  // TODO: does subject matter? Ruby: merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
1051
- Compound_Selector* pMerged = plusSel.selector()->head()->unify_with(tildeSel.selector()->head(), ctx);
1051
+ SimpleSequence_Selector* pMerged = plusSel.selector()->head()->unify_with(tildeSel.selector()->head(), ctx);
1052
1052
  pMergedWrapper->head(pMerged);
1053
1053
 
1054
1054
  DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
@@ -1057,15 +1057,15 @@ namespace Sass {
1057
1057
 
1058
1058
  Node firstPerm = Node::createCollection();
1059
1059
  firstPerm.collection()->push_back(tildeSel);
1060
- firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1060
+ firstPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::PRECEDES));
1061
1061
  firstPerm.collection()->push_back(plusSel);
1062
- firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO));
1062
+ firstPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::ADJACENT_TO));
1063
1063
  newRes.collection()->push_back(firstPerm);
1064
1064
 
1065
1065
  if (pMerged) {
1066
1066
  Node mergedPerm = Node::createCollection();
1067
1067
  mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper, ctx));
1068
- mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO));
1068
+ mergedPerm.collection()->push_back(Node::createCombinator(Sequence_Selector::ADJACENT_TO));
1069
1069
  newRes.collection()->push_back(mergedPerm);
1070
1070
  }
1071
1071
 
@@ -1074,7 +1074,7 @@ namespace Sass {
1074
1074
  DEBUG_PRINTLN(ALL, "RESULT: " << res)
1075
1075
 
1076
1076
  }
1077
- } else if (op1.combinator() == Complex_Selector::PARENT_OF && (op2.combinator() == Complex_Selector::PRECEDES || op2.combinator() == Complex_Selector::ADJACENT_TO)) {
1077
+ } else if (op1.combinator() == Sequence_Selector::PARENT_OF && (op2.combinator() == Sequence_Selector::PRECEDES || op2.combinator() == Sequence_Selector::ADJACENT_TO)) {
1078
1078
 
1079
1079
  res.collection()->push_front(op2);
1080
1080
  res.collection()->push_front(sel2);
@@ -1082,7 +1082,7 @@ namespace Sass {
1082
1082
  seq1.collection()->push_back(sel1);
1083
1083
  seq1.collection()->push_back(op1);
1084
1084
 
1085
- } else if (op2.combinator() == Complex_Selector::PARENT_OF && (op1.combinator() == Complex_Selector::PRECEDES || op1.combinator() == Complex_Selector::ADJACENT_TO)) {
1085
+ } else if (op2.combinator() == Sequence_Selector::PARENT_OF && (op1.combinator() == Sequence_Selector::PRECEDES || op1.combinator() == Sequence_Selector::ADJACENT_TO)) {
1086
1086
 
1087
1087
  res.collection()->push_front(op1);
1088
1088
  res.collection()->push_front(sel1);
@@ -1095,9 +1095,9 @@ namespace Sass {
1095
1095
  DEBUG_PRINTLN(ALL, "sel1: " << sel1)
1096
1096
  DEBUG_PRINTLN(ALL, "sel2: " << sel2)
1097
1097
 
1098
- Complex_Selector* pMergedWrapper = sel1.selector()->clone(ctx); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
1098
+ Sequence_Selector* pMergedWrapper = sel1.selector()->clone(ctx); // Clone the Sequence_Selector to get back to something we can transform to a node once we replace the head with the unification result
1099
1099
  // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
1100
- Compound_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
1100
+ SimpleSequence_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
1101
1101
  pMergedWrapper->head(pMerged);
1102
1102
 
1103
1103
  DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
@@ -1121,7 +1121,7 @@ namespace Sass {
1121
1121
 
1122
1122
  Node op1 = ops1.collection()->front();
1123
1123
 
1124
- if (op1.combinator() == Complex_Selector::PARENT_OF && !seq2.collection()->empty() && seq2.collection()->back().selector()->is_superselector_of(seq1.collection()->back().selector())) {
1124
+ if (op1.combinator() == Sequence_Selector::PARENT_OF && !seq2.collection()->empty() && seq2.collection()->back().selector()->is_superselector_of(seq1.collection()->back().selector())) {
1125
1125
  seq2.collection()->pop_back();
1126
1126
  }
1127
1127
 
@@ -1136,7 +1136,7 @@ namespace Sass {
1136
1136
 
1137
1137
  Node op2 = ops2.collection()->front();
1138
1138
 
1139
- if (op2.combinator() == Complex_Selector::PARENT_OF && !seq1.collection()->empty() && seq1.collection()->back().selector()->is_superselector_of(seq2.collection()->back().selector())) {
1139
+ if (op2.combinator() == Sequence_Selector::PARENT_OF && !seq1.collection()->empty() && seq1.collection()->back().selector()->is_superselector_of(seq2.collection()->back().selector())) {
1140
1140
  seq1.collection()->pop_back();
1141
1141
  }
1142
1142
 
@@ -1509,10 +1509,10 @@ namespace Sass {
1509
1509
  // This forward declaration is needed since extendComplexSelector calls extendCompoundSelector, which may recursively
1510
1510
  // call extendComplexSelector again.
1511
1511
  static Node extendComplexSelector(
1512
- Complex_Selector* pComplexSelector,
1512
+ Sequence_Selector* pComplexSelector,
1513
1513
  Context& ctx,
1514
1514
  ExtensionSubsetMap& subset_map,
1515
- std::set<Compound_Selector> seen, bool isReplace, bool isOriginal);
1515
+ std::set<SimpleSequence_Selector> seen, bool isReplace, bool isOriginal);
1516
1516
 
1517
1517
 
1518
1518
 
@@ -1532,15 +1532,15 @@ namespace Sass {
1532
1532
  class GroupByToAFunctor {
1533
1533
  public:
1534
1534
  KeyType operator()(ExtensionPair& extPair) const {
1535
- Complex_Selector* pSelector = extPair.first;
1535
+ Sequence_Selector* pSelector = extPair.first;
1536
1536
  return *pSelector;
1537
1537
  }
1538
1538
  };
1539
1539
  static Node extendCompoundSelector(
1540
- Compound_Selector* pSelector,
1540
+ SimpleSequence_Selector* pSelector,
1541
1541
  Context& ctx,
1542
1542
  ExtensionSubsetMap& subset_map,
1543
- std::set<Compound_Selector> seen, bool isReplace) {
1543
+ std::set<SimpleSequence_Selector> seen, bool isReplace) {
1544
1544
 
1545
1545
  DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND: "))
1546
1546
  // TODO: Ruby has another loop here to skip certain members?
@@ -1550,13 +1550,13 @@ namespace Sass {
1550
1550
 
1551
1551
  SubsetMapEntries entries = subset_map.get_v(pSelector->to_str_vec());
1552
1552
 
1553
- typedef std::vector<std::pair<Complex_Selector, std::vector<ExtensionPair> > > GroupedByToAResult;
1553
+ typedef std::vector<std::pair<Sequence_Selector, std::vector<ExtensionPair> > > GroupedByToAResult;
1554
1554
 
1555
- GroupByToAFunctor<Complex_Selector> extPairKeyFunctor;
1555
+ GroupByToAFunctor<Sequence_Selector> extPairKeyFunctor;
1556
1556
  GroupedByToAResult arr;
1557
1557
  group_by_to_a(entries, extPairKeyFunctor, arr);
1558
1558
 
1559
- typedef std::pair<Compound_Selector*, Complex_Selector*> SelsNewSeqPair;
1559
+ typedef std::pair<SimpleSequence_Selector*, Sequence_Selector*> SelsNewSeqPair;
1560
1560
  typedef std::vector<SelsNewSeqPair> SelsNewSeqPairCollection;
1561
1561
 
1562
1562
 
@@ -1564,18 +1564,18 @@ namespace Sass {
1564
1564
 
1565
1565
 
1566
1566
  for (GroupedByToAResult::iterator groupedIter = arr.begin(), groupedIterEnd = arr.end(); groupedIter != groupedIterEnd; groupedIter++) {
1567
- std::pair<Complex_Selector, std::vector<ExtensionPair> >& groupedPair = *groupedIter;
1567
+ std::pair<Sequence_Selector, std::vector<ExtensionPair> >& groupedPair = *groupedIter;
1568
1568
 
1569
- Complex_Selector& seq = groupedPair.first;
1569
+ Sequence_Selector& seq = groupedPair.first;
1570
1570
  std::vector<ExtensionPair>& group = groupedPair.second;
1571
1571
 
1572
1572
  DEBUG_EXEC(EXTEND_COMPOUND, printComplexSelector(&seq, "SEQ: "))
1573
1573
 
1574
1574
 
1575
- Compound_Selector* pSels = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, pSelector->pstate());
1575
+ SimpleSequence_Selector* pSels = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, pSelector->pstate());
1576
1576
  for (std::vector<ExtensionPair>::iterator groupIter = group.begin(), groupIterEnd = group.end(); groupIter != groupIterEnd; groupIter++) {
1577
1577
  ExtensionPair& pair = *groupIter;
1578
- Compound_Selector* pCompound = pair.second;
1578
+ SimpleSequence_Selector* pCompound = pair.second;
1579
1579
  for (size_t index = 0; index < pCompound->length(); index++) {
1580
1580
  Simple_Selector* pSimpleSelector = (*pCompound)[index];
1581
1581
  (*pSels) << pSimpleSelector;
@@ -1585,21 +1585,21 @@ namespace Sass {
1585
1585
 
1586
1586
  DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSels, "SELS: "))
1587
1587
 
1588
- Complex_Selector* pExtComplexSelector = &seq; // The selector up to where the @extend is (ie, the thing to merge)
1589
- Compound_Selector* pExtCompoundSelector = pSels; // All the simple selectors to be replaced from the current compound selector from all extensions
1588
+ Sequence_Selector* pExtComplexSelector = &seq; // The selector up to where the @extend is (ie, the thing to merge)
1589
+ SimpleSequence_Selector* pExtCompoundSelector = pSels; // All the simple selectors to be replaced from the current compound selector from all extensions
1590
1590
 
1591
- // TODO: This can return a Compound_Selector with no elements. Should that just be returning NULL?
1591
+ // TODO: This can return a SimpleSequence_Selector with no elements. Should that just be returning NULL?
1592
1592
  // RUBY: self_without_sel = Sass::Util.array_minus(members, sels)
1593
- Compound_Selector* pSelectorWithoutExtendSelectors = pSelector->minus(pExtCompoundSelector, ctx);
1593
+ SimpleSequence_Selector* pSelectorWithoutExtendSelectors = pSelector->minus(pExtCompoundSelector, ctx);
1594
1594
 
1595
1595
  DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "MEMBERS: "))
1596
1596
  DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "SELF_WO_SEL: "))
1597
1597
 
1598
- Compound_Selector* pInnermostCompoundSelector = pExtComplexSelector->last()->head();
1599
- Compound_Selector* pUnifiedSelector = NULL;
1598
+ SimpleSequence_Selector* pInnermostCompoundSelector = pExtComplexSelector->last()->head();
1599
+ SimpleSequence_Selector* pUnifiedSelector = NULL;
1600
1600
 
1601
1601
  if (!pInnermostCompoundSelector) {
1602
- pInnermostCompoundSelector = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, pSelector->pstate());
1602
+ pInnermostCompoundSelector = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, pSelector->pstate());
1603
1603
  }
1604
1604
 
1605
1605
  pUnifiedSelector = pInnermostCompoundSelector->unify_with(pSelectorWithoutExtendSelectors, ctx);
@@ -1618,14 +1618,14 @@ namespace Sass {
1618
1618
  // next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
1619
1619
 
1620
1620
  // TODO: This seems a little fishy to me. See if it causes any problems. From the ruby, we should be able to just
1621
- // get rid of the last Compound_Selector and replace it with this one. I think the reason this code is more
1622
- // complex is that Complex_Selector contains a combinator, but in ruby combinators have already been filtered
1621
+ // get rid of the last SimpleSequence_Selector and replace it with this one. I think the reason this code is more
1622
+ // complex is that Sequence_Selector contains a combinator, but in ruby combinators have already been filtered
1623
1623
  // out and aren't operated on.
1624
- Complex_Selector* pNewSelector = pExtComplexSelector->cloneFully(ctx); // ->first();
1624
+ Sequence_Selector* pNewSelector = pExtComplexSelector->cloneFully(ctx); // ->first();
1625
1625
 
1626
- Complex_Selector* pNewInnerMost = SASS_MEMORY_NEW(ctx.mem, Complex_Selector, pSelector->pstate(), Complex_Selector::ANCESTOR_OF, pUnifiedSelector, NULL);
1626
+ Sequence_Selector* pNewInnerMost = SASS_MEMORY_NEW(ctx.mem, Sequence_Selector, pSelector->pstate(), Sequence_Selector::ANCESTOR_OF, pUnifiedSelector, NULL);
1627
1627
 
1628
- Complex_Selector::Combinator combinator = pNewSelector->clear_innermost();
1628
+ Sequence_Selector::Combinator combinator = pNewSelector->clear_innermost();
1629
1629
  pNewSelector->set_innermost(pNewInnerMost, combinator);
1630
1630
 
1631
1631
  #ifdef DEBUG
@@ -1642,7 +1642,7 @@ namespace Sass {
1642
1642
 
1643
1643
 
1644
1644
  // if (pSelector && pSelector->has_line_feed()) pNewInnerMost->has_line_feed(true);
1645
- // Set the sources on our new Complex_Selector to the sources of this simple sequence plus the thing we're extending.
1645
+ // Set the sources on our new Sequence_Selector to the sources of this simple sequence plus the thing we're extending.
1646
1646
  DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector, ctx))
1647
1647
 
1648
1648
  DEBUG_EXEC(EXTEND_COMPOUND, SourcesSet oldSet = pNewSelector->sources(); printSourcesSet(oldSet, ctx, "SOURCES NEW SEQ BEGIN: "))
@@ -1669,8 +1669,8 @@ namespace Sass {
1669
1669
  for (SelsNewSeqPairCollection::iterator holderIter = holder.begin(), holderIterEnd = holder.end(); holderIter != holderIterEnd; holderIter++) {
1670
1670
  SelsNewSeqPair& pair = *holderIter;
1671
1671
 
1672
- Compound_Selector* pSels = pair.first;
1673
- Complex_Selector* pNewSelector = pair.second;
1672
+ SimpleSequence_Selector* pSels = pair.first;
1673
+ Sequence_Selector* pNewSelector = pair.second;
1674
1674
 
1675
1675
 
1676
1676
  // RUBY??: next [] if seen.include?(sels)
@@ -1679,7 +1679,7 @@ namespace Sass {
1679
1679
  }
1680
1680
 
1681
1681
 
1682
- std::set<Compound_Selector> recurseSeen(seen);
1682
+ std::set<SimpleSequence_Selector> recurseSeen(seen);
1683
1683
  recurseSeen.insert(*pSels);
1684
1684
 
1685
1685
 
@@ -1709,33 +1709,19 @@ namespace Sass {
1709
1709
 
1710
1710
 
1711
1711
  static bool complexSelectorHasExtension(
1712
- Complex_Selector* pComplexSelector,
1712
+ Sequence_Selector* pComplexSelector,
1713
1713
  Context& ctx,
1714
- ExtensionSubsetMap& subset_map) {
1714
+ ExtensionSubsetMap& subset_map,
1715
+ std::set<SimpleSequence_Selector>& seen) {
1715
1716
 
1716
1717
  bool hasExtension = false;
1717
1718
 
1718
- Complex_Selector* pIter = pComplexSelector;
1719
+ Sequence_Selector* pIter = pComplexSelector;
1719
1720
 
1720
1721
  while (!hasExtension && pIter) {
1721
- Compound_Selector* pHead = pIter->head();
1722
+ SimpleSequence_Selector* pHead = pIter->head();
1722
1723
 
1723
1724
  if (pHead) {
1724
- for (Simple_Selector* pSimple : *pHead) {
1725
- if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(pSimple)) {
1726
- if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
1727
- for (Complex_Selector* cs : sl->elements()) {
1728
- while (cs) {
1729
- if (complexSelectorHasExtension(cs, ctx, subset_map)) {
1730
- hasExtension = true;
1731
- break;
1732
- }
1733
- cs = cs->tail();
1734
- }
1735
- }
1736
- }
1737
- }
1738
- }
1739
1725
  SubsetMapEntries entries = subset_map.get_v(pHead->to_str_vec());
1740
1726
  for (ExtensionPair ext : entries) {
1741
1727
  // check if both selectors have the same media block parent
@@ -1783,10 +1769,10 @@ namespace Sass {
1783
1769
  next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
1784
1770
  */
1785
1771
  static Node extendComplexSelector(
1786
- Complex_Selector* pComplexSelector,
1772
+ Sequence_Selector* pComplexSelector,
1787
1773
  Context& ctx,
1788
1774
  ExtensionSubsetMap& subset_map,
1789
- std::set<Compound_Selector> seen, bool isReplace, bool isOriginal) {
1775
+ std::set<SimpleSequence_Selector> seen, bool isReplace, bool isOriginal) {
1790
1776
 
1791
1777
  Node complexSelector = complexSelectorToNode(pComplexSelector, ctx);
1792
1778
  DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX: " << complexSelector)
@@ -1806,7 +1792,7 @@ namespace Sass {
1806
1792
  // RUBY: next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
1807
1793
  if (!sseqOrOp.isSelector()) {
1808
1794
  // Wrap our Combinator in two collections to match ruby. This is essentially making a collection Node
1809
- // with one collection child. The collection child represents a Complex_Selector that is only a combinator.
1795
+ // with one collection child. The collection child represents a Sequence_Selector that is only a combinator.
1810
1796
  Node outer = Node::createCollection();
1811
1797
  Node inner = Node::createCollection();
1812
1798
  outer.collection()->push_back(inner);
@@ -1815,7 +1801,7 @@ namespace Sass {
1815
1801
  continue;
1816
1802
  }
1817
1803
 
1818
- Compound_Selector* pCompoundSelector = sseqOrOp.selector()->head();
1804
+ SimpleSequence_Selector* pCompoundSelector = sseqOrOp.selector()->head();
1819
1805
 
1820
1806
  // RUBY: extended = sseq_or_op.do_extend(extends, parent_directives, replace, seen)
1821
1807
  Node extended = extendCompoundSelector(pCompoundSelector, ctx, subset_map, seen, isReplace);
@@ -1823,9 +1809,9 @@ namespace Sass {
1823
1809
  DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED: " << extended)
1824
1810
 
1825
1811
 
1826
- // Prepend the Compound_Selector based on the choices logic; choices seems to be extend but with an ruby Array instead of a Sequence
1812
+ // Prepend the SimpleSequence_Selector based on the choices logic; choices seems to be extend but with an ruby Array instead of a Sequence
1827
1813
  // due to the member mapping: choices = extended.map {|seq| seq.members}
1828
- Complex_Selector* pJustCurrentCompoundSelector = sseqOrOp.selector();
1814
+ Sequence_Selector* pJustCurrentCompoundSelector = sseqOrOp.selector();
1829
1815
 
1830
1816
  // RUBY: extended.first.add_sources!([self]) if original && !has_placeholder?
1831
1817
  if (isOriginal && !pComplexSelector->has_placeholder()) {
@@ -1839,7 +1825,7 @@ namespace Sass {
1839
1825
  for (NodeDeque::iterator iterator = extended.collection()->begin(), endIterator = extended.collection()->end();
1840
1826
  iterator != endIterator; ++iterator) {
1841
1827
  Node& childNode = *iterator;
1842
- Complex_Selector* pExtensionSelector = nodeToComplexSelector(childNode, ctx);
1828
+ Sequence_Selector* pExtensionSelector = nodeToComplexSelector(childNode, ctx);
1843
1829
  if (pExtensionSelector->is_superselector_of(pJustCurrentCompoundSelector)) {
1844
1830
  isSuperselector = true;
1845
1831
  break;
@@ -1906,33 +1892,40 @@ namespace Sass {
1906
1892
  /*
1907
1893
  This is the equivalent of ruby's CommaSequence.do_extend.
1908
1894
  */
1909
- Selector_List* Extend::extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool& extendedSomething) {
1895
+ CommaSequence_Selector* Extend::extendSelectorList(CommaSequence_Selector* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool& extendedSomething) {
1896
+ std::set<SimpleSequence_Selector> seen;
1897
+ return extendSelectorList(pSelectorList, ctx, subset_map, isReplace, extendedSomething, seen);
1898
+ }
1899
+
1900
+ /*
1901
+ This is the equivalent of ruby's CommaSequence.do_extend.
1902
+ */
1903
+ CommaSequence_Selector* Extend::extendSelectorList(CommaSequence_Selector* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool& extendedSomething, std::set<SimpleSequence_Selector>& seen) {
1910
1904
 
1911
- Selector_List* pNewSelectors = SASS_MEMORY_NEW(ctx.mem, Selector_List, pSelectorList->pstate(), pSelectorList->length());
1905
+ CommaSequence_Selector* pNewSelectors = SASS_MEMORY_NEW(ctx.mem, CommaSequence_Selector, pSelectorList->pstate(), pSelectorList->length());
1912
1906
 
1913
1907
  extendedSomething = false;
1914
1908
 
1915
1909
  for (size_t index = 0, length = pSelectorList->length(); index < length; index++) {
1916
- Complex_Selector* pSelector = (*pSelectorList)[index];
1910
+ Sequence_Selector* pSelector = (*pSelectorList)[index];
1917
1911
 
1918
1912
  // ruby sass seems to keep a list of things that have extensions and then only extend those. We don't currently do that.
1919
1913
  // Since it's not that expensive to check if an extension exists in the subset map and since it can be relatively expensive to
1920
1914
  // run through the extend code (which does a data model transformation), check if there is anything to extend before doing
1921
1915
  // the extend. We might be able to optimize extendComplexSelector, but this approach keeps us closer to ruby sass (which helps
1922
1916
  // when debugging).
1923
- if (!complexSelectorHasExtension(pSelector, ctx, subset_map)) {
1917
+ if (!complexSelectorHasExtension(pSelector, ctx, subset_map, seen)) {
1924
1918
  *pNewSelectors << pSelector;
1925
1919
  continue;
1926
1920
  }
1927
1921
 
1928
1922
  extendedSomething = true;
1929
1923
 
1930
- std::set<Compound_Selector> seen;
1931
-
1932
1924
  Node extendedSelectors = extendComplexSelector(pSelector, ctx, subset_map, seen, isReplace, true);
1933
1925
  if (!pSelector->has_placeholder()) {
1934
1926
  if (!extendedSelectors.contains(complexSelectorToNode(pSelector, ctx), true /*simpleSelectorOrderDependent*/)) {
1935
1927
  *pNewSelectors << pSelector;
1928
+ continue;
1936
1929
  }
1937
1930
  }
1938
1931
 
@@ -1951,32 +1944,46 @@ namespace Sass {
1951
1944
  pNewSelectors = remove_placeholders.remove_placeholders(pNewSelectors);
1952
1945
 
1953
1946
  // unwrap all wrapped selectors with inner lists
1954
- for (Complex_Selector* cur : *pNewSelectors) {
1947
+ for (Sequence_Selector* cur : *pNewSelectors) {
1955
1948
  // process tails
1956
1949
  while (cur) {
1957
1950
  // process header
1958
- if (cur->head()) {
1951
+ if (cur->head() && seen.find(*cur->head()) == seen.end()) {
1952
+ std::set<SimpleSequence_Selector> recseen(seen);
1953
+ recseen.insert(*cur->head());
1959
1954
  // create a copy since we add multiple items if stuff get unwrapped
1960
- Compound_Selector* cpy_head = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, cur->pstate());
1955
+ SimpleSequence_Selector* cpy_head = SASS_MEMORY_NEW(ctx.mem, SimpleSequence_Selector, cur->pstate());
1961
1956
  for (Simple_Selector* hs : *cur->head()) {
1962
1957
  if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(hs)) {
1963
- if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
1958
+ if (CommaSequence_Selector* sl = dynamic_cast<CommaSequence_Selector*>(ws->selector())) {
1964
1959
  // special case for ruby ass
1965
1960
  if (sl->empty()) {
1966
1961
  // this seems inconsistent but it is how ruby sass seems to remove parentheses
1967
- *cpy_head << SASS_MEMORY_NEW(ctx.mem, Type_Selector, hs->pstate(), ws->name());
1962
+ *cpy_head << SASS_MEMORY_NEW(ctx.mem, Element_Selector, hs->pstate(), ws->name());
1968
1963
  }
1969
1964
  // has wrapped selectors
1970
1965
  else {
1971
1966
  // extend the inner list of wrapped selector
1972
- Selector_List* ext_sl = extendSelectorList(sl, ctx, subset_map);
1967
+ CommaSequence_Selector* ext_sl = extendSelectorList(sl, ctx, subset_map, recseen);
1973
1968
  for (size_t i = 0; i < ext_sl->length(); i += 1) {
1974
- if (Complex_Selector* ext_cs = ext_sl->at(i)) {
1969
+ if (Sequence_Selector* ext_cs = ext_sl->at(i)) {
1975
1970
  // create clones for wrapped selector and the inner list
1976
1971
  Wrapped_Selector* cpy_ws = SASS_MEMORY_NEW(ctx.mem, Wrapped_Selector, *ws);
1977
- Selector_List* cpy_ws_sl = SASS_MEMORY_NEW(ctx.mem, Selector_List, sl->pstate());
1972
+ CommaSequence_Selector* cpy_ws_sl = SASS_MEMORY_NEW(ctx.mem, CommaSequence_Selector, sl->pstate());
1978
1973
  // remove parent selectors from inner selector
1979
- if (ext_cs->first()) *cpy_ws_sl << ext_cs->first();
1974
+ if (ext_cs->first() && ext_cs->first()->head()->length() > 0) {
1975
+ Wrapped_Selector* ext_ws = dynamic_cast<Wrapped_Selector*>(ext_cs->first()->head()->first());
1976
+ if (ext_ws/* && ext_cs->length() == 1*/) {
1977
+ CommaSequence_Selector* ws_cs = dynamic_cast<CommaSequence_Selector*>(ext_ws->selector());
1978
+ SimpleSequence_Selector* ws_ss = ws_cs->first()->head();
1979
+ if (!(
1980
+ dynamic_cast<Pseudo_Selector*>(ws_ss->first()) ||
1981
+ dynamic_cast<Element_Selector*>(ws_ss->first()) ||
1982
+ dynamic_cast<Placeholder_Selector*>(ws_ss->first())
1983
+ )) continue;
1984
+ }
1985
+ *cpy_ws_sl << ext_cs->first();
1986
+ }
1980
1987
  // assign list to clone
1981
1988
  cpy_ws->selector(cpy_ws_sl);
1982
1989
  // append the clone
@@ -2038,7 +2045,7 @@ namespace Sass {
2038
2045
  template <typename ObjectType>
2039
2046
  static void extendObjectWithSelectorAndBlock(ObjectType* pObject, Context& ctx, ExtensionSubsetMap& subset_map) {
2040
2047
 
2041
- DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<Selector_List*>(pObject->selector())->to_string(ctx.c_options))
2048
+ DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<CommaSequence_Selector*>(pObject->selector())->to_string(ctx.c_options))
2042
2049
 
2043
2050
  // Ruby sass seems to filter nodes that don't have any content well before we get here. I'm not sure the repercussions
2044
2051
  // of doing so, so for now, let's just not extend things that won't be output later.
@@ -2048,10 +2055,10 @@ namespace Sass {
2048
2055
  }
2049
2056
 
2050
2057
  bool extendedSomething = false;
2051
- Selector_List* pNewSelectorList = Extend::extendSelectorList(static_cast<Selector_List*>(pObject->selector()), ctx, subset_map, false, extendedSomething);
2058
+ CommaSequence_Selector* pNewSelectorList = Extend::extendSelectorList(static_cast<CommaSequence_Selector*>(pObject->selector()), ctx, subset_map, false, extendedSomething);
2052
2059
 
2053
2060
  if (extendedSomething && pNewSelectorList) {
2054
- DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<Selector_List*>(pObject->selector())->to_string(ctx.c_options))
2061
+ DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<CommaSequence_Selector*>(pObject->selector())->to_string(ctx.c_options))
2055
2062
  DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->to_string(ctx.c_options))
2056
2063
  pNewSelectorList->remove_parent_selectors();
2057
2064
  pObject->selector(pNewSelectorList);
@@ -2076,8 +2083,8 @@ namespace Sass {
2076
2083
  if (b->is_root()) {
2077
2084
  // debug_subset_map(subset_map);
2078
2085
  for(auto const &it : subset_map.values()) {
2079
- Complex_Selector* sel = it.first ? it.first->first() : NULL;
2080
- Compound_Selector* ext = it.second ? it.second : NULL;
2086
+ Sequence_Selector* sel = it.first ? it.first->first() : NULL;
2087
+ SimpleSequence_Selector* ext = it.second ? it.second : NULL;
2081
2088
  if (ext && (ext->extended() || ext->is_optional())) continue;
2082
2089
  std::string str_sel(sel->to_string({ NESTED, 5 }));
2083
2090
  std::string str_ext(ext->to_string({ NESTED, 5 }));
@@ -2110,7 +2117,7 @@ namespace Sass {
2110
2117
 
2111
2118
  void Extend::operator()(Directive* a)
2112
2119
  {
2113
- // Selector_List* ls = dynamic_cast<Selector_List*>(a->selector());
2120
+ // CommaSequence_Selector* ls = dynamic_cast<CommaSequence_Selector*>(a->selector());
2114
2121
  // selector_stack.push_back(ls);
2115
2122
  if (a->block()) a->block()->perform(this);
2116
2123
  // exp.selector_stack.pop_back();