sassc 1.10.1 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
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();