Initial commit
[yaffs-website] / node_modules / node-sass / src / libsass / src / extend.cpp
1 #include "sass.hpp"
2 #include "extend.hpp"
3 #include "context.hpp"
4 #include "backtrace.hpp"
5 #include "paths.hpp"
6 #include "parser.hpp"
7 #include "node.hpp"
8 #include "sass_util.hpp"
9 #include "remove_placeholders.hpp"
10 #include "debug.hpp"
11 #include <iostream>
12 #include <deque>
13 #include <set>
14
15 /*
16  NOTES:
17
18  - The print* functions print to cerr. This allows our testing frameworks (like sass-spec) to ignore the output, which
19    is very helpful when debugging. The format of the output is mainly to wrap things in square brackets to match what
20    ruby already outputs (to make comparisons easier).
21
22  - For the direct porting effort, we're trying to port method-for-method until we get all the tests passing.
23    Where applicable, I've tried to include the ruby code above the function for reference until all our tests pass.
24    The ruby code isn't always directly portable, so I've tried to include any modified ruby code that was actually
25    used for the porting.
26
27  - DO NOT try to optimize yet. We get a tremendous benefit out of comparing the output of each stage of the extend to the ruby
28    output at the same stage. This makes it much easier to determine where problems are. Try to keep as close to
29    the ruby code as you can until we have all the sass-spec tests passing. Then, we should optimize. However, if you see
30    something that could probably be optimized, let's not forget it. Add a // TODO: or // IMPROVEMENT: comment.
31
32  - Coding conventions in this file (these may need to be changed before merging back into master)
33    - Very basic hungarian notation:
34      p prefix for pointers (pSelector)
35      no prefix for value types and references (selector)
36    - Use STL iterators where possible
37    - prefer verbose naming over terse naming
38    - use typedefs for STL container types for make maintenance easier
39
40  - You may see a lot of comments that say "// TODO: is this the correct combinator?". See the comment referring to combinators
41    in extendCompoundSelector for a more extensive explanation of my confusion. I think our divergence in data model from ruby
42    sass causes this to be necessary.
43
44
45  GLOBAL TODOS:
46
47  - wrap the contents of the print functions in DEBUG preprocesser conditionals so they will be optimized away in non-debug mode.
48
49  - consider making the extend* functions member functions to avoid passing around ctx and subset_map map around. This has the
50    drawback that the implementation details of the operator are then exposed to the outside world, which is not ideal and
51    can cause additional compile time dependencies.
52
53  - mark the helper methods in this file static to given them compilation unit linkage.
54
55  - implement parent directive matching
56
57  - fix compilation warnings for unused Extend members if we really don't need those references anymore.
58  */
59
60
61 namespace Sass {
62
63
64
65 #ifdef DEBUG
66
67   // TODO: move the ast specific ostream operators into ast.hpp/ast.cpp
68   std::ostream& operator<<(std::ostream& os, const Complex_Selector::Combinator combinator) {
69     switch (combinator) {
70       case Complex_Selector::ANCESTOR_OF: os << "\" \""; break;
71       case Complex_Selector::PARENT_OF:   os << "\">\""; break;
72       case Complex_Selector::PRECEDES:    os << "\"~\""; break;
73       case Complex_Selector::ADJACENT_TO: os << "\"+\""; break;
74       case Complex_Selector::REFERENCE:   os << "\"/\""; break;
75     }
76
77     return os;
78   }
79
80
81   std::ostream& operator<<(std::ostream& os, Compound_Selector& compoundSelector) {
82     for (size_t i = 0, L = compoundSelector.length(); i < L; ++i) {
83       if (i > 0) os << ", ";
84       os << compoundSelector[i]->to_string();
85     }
86     return os;
87   }
88
89   std::ostream& operator<<(std::ostream& os, Simple_Selector& simpleSelector) {
90     os << simpleSelector.to_string();
91     return os;
92   }
93
94   // Print a string representation of a Compound_Selector
95   static void printSimpleSelector(Simple_Selector* pSimpleSelector, const char* message=NULL, bool newline=true) {
96
97     if (message) {
98       std::cerr << message;
99     }
100
101     if (pSimpleSelector) {
102       std::cerr << "[" << *pSimpleSelector << "]";
103     } else {
104       std::cerr << "NULL";
105     }
106
107     if (newline) {
108       std::cerr << std::endl;
109     }
110   }
111
112   // Print a string representation of a Compound_Selector
113   static void printCompoundSelector(Compound_Selector_Ptr pCompoundSelector, const char* message=NULL, bool newline=true) {
114
115     if (message) {
116       std::cerr << message;
117     }
118
119     if (pCompoundSelector) {
120       std::cerr << "[" << *pCompoundSelector << "]";
121     } else {
122       std::cerr << "NULL";
123     }
124
125     if (newline) {
126       std::cerr << std::endl;
127     }
128   }
129
130
131   std::ostream& operator<<(std::ostream& os, Complex_Selector& complexSelector) {
132
133     os << "[";
134     Complex_Selector_Ptr pIter = &complexSelector;
135     bool first = true;
136     while (pIter) {
137       if (pIter->combinator() != Complex_Selector::ANCESTOR_OF) {
138         if (!first) {
139           os << ", ";
140         }
141         first = false;
142         os << pIter->combinator();
143       }
144
145       if (!first) {
146         os << ", ";
147       }
148       first = false;
149
150       if (pIter->head()) {
151         os << pIter->head()->to_string();
152       } else {
153         os << "NULL_HEAD";
154       }
155
156       pIter = pIter->tail();
157     }
158     os << "]";
159
160     return os;
161   }
162
163
164   // Print a string representation of a Complex_Selector
165   static void printComplexSelector(Complex_Selector_Ptr pComplexSelector, const char* message=NULL, bool newline=true) {
166
167     if (message) {
168       std::cerr << message;
169     }
170
171     if (pComplexSelector) {
172       std::cerr << *pComplexSelector;
173     } else {
174       std::cerr << "NULL";
175     }
176
177     if (newline) {
178       std::cerr << std::endl;
179     }
180   }
181
182   static void printSelsNewSeqPairCollection(SubSetMapLookups& collection, const char* message=NULL, bool newline=true) {
183
184     if (message) {
185       std::cerr << message;
186     }
187     bool first = true;
188     std::cerr << "[";
189     for(SubSetMapLookup& pair : collection) {
190       if (first) {
191         first = false;
192       } else {
193         std::cerr << ", ";
194       }
195       std::cerr << "[";
196       Compound_Selector_Ptr pSels = pair.first;
197       Complex_Selector_Ptr pNewSelector = pair.second;
198       std::cerr << "[" << *pSels << "], ";
199       printComplexSelector(pNewSelector, NULL, false);
200     }
201     std::cerr << "]";
202
203     if (newline) {
204       std::cerr << std::endl;
205     }
206   }
207
208   // Print a string representation of a ComplexSelectorSet
209   static void printSourcesSet(ComplexSelectorSet& sources, Context& ctx, const char* message=NULL, bool newline=true) {
210
211     if (message) {
212       std::cerr << message;
213     }
214
215     // Convert to a deque of strings so we can sort since order doesn't matter in a set. This should cut down on
216     // the differences we see when debug printing.
217     typedef std::deque<std::string> SourceStrings;
218     SourceStrings sourceStrings;
219     for (ComplexSelectorSet::iterator iterator = sources.begin(), iteratorEnd = sources.end(); iterator != iteratorEnd; ++iterator) {
220       Complex_Selector_Ptr pSource = *iterator;
221       std::stringstream sstream;
222       sstream << complexSelectorToNode(pSource, ctx);
223       sourceStrings.push_back(sstream.str());
224     }
225
226     // Sort to get consistent output
227     std::sort(sourceStrings.begin(), sourceStrings.end());
228
229     std::cerr << "ComplexSelectorSet[";
230     for (SourceStrings::iterator iterator = sourceStrings.begin(), iteratorEnd = sourceStrings.end(); iterator != iteratorEnd; ++iterator) {
231       std::string source = *iterator;
232       if (iterator != sourceStrings.begin()) {
233         std::cerr << ", ";
234       }
235       std::cerr << source;
236     }
237     std::cerr << "]";
238
239     if (newline) {
240       std::cerr << std::endl;
241     }
242   }
243
244
245   std::ostream& operator<<(std::ostream& os, SubSetMapPairs& entries) {
246     os << "SUBSET_MAP_ENTRIES[";
247
248     for (SubSetMapPairs::iterator iterator = entries.begin(), endIterator = entries.end(); iterator != endIterator; ++iterator) {
249       Complex_Selector_Obj pExtComplexSelector = iterator->first;    // The selector up to where the @extend is (ie, the thing to merge)
250       Compound_Selector_Obj pExtCompoundSelector = iterator->second; // The stuff after the @extend
251
252       if (iterator != entries.begin()) {
253         os << ", ";
254       }
255
256       os << "(";
257
258       if (pExtComplexSelector) {
259         std::cerr << *pExtComplexSelector;
260       } else {
261         std::cerr << "NULL";
262       }
263
264       os << " -> ";
265
266       if (pExtCompoundSelector) {
267         std::cerr << *pExtCompoundSelector;
268       } else {
269         std::cerr << "NULL";
270       }
271
272       os << ")";
273
274     }
275
276     os << "]";
277
278     return os;
279   }
280 #endif
281
282   static bool parentSuperselector(Complex_Selector_Ptr pOne, Complex_Selector_Ptr pTwo, Context& ctx) {
283     // TODO: figure out a better way to create a Complex_Selector from scratch
284     // TODO: There's got to be a better way. This got ugly quick...
285     Position noPosition(-1, -1, -1);
286     Element_Selector_Obj fakeParent = SASS_MEMORY_NEW(Element_Selector, ParserState("[FAKE]"), "temp");
287     Compound_Selector_Obj fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[FAKE]"), 1 /*size*/);
288     fakeHead->elements().push_back(fakeParent);
289     Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, fakeHead /*head*/, NULL /*tail*/);
290
291     pOne->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
292     pTwo->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
293
294     bool isSuperselector = pOne->is_superselector_of(pTwo);
295
296     pOne->clear_innermost();
297     pTwo->clear_innermost();
298
299     return isSuperselector;
300   }
301
302   void nodeToComplexSelectorDeque(const Node& node, ComplexSelectorDeque& out, Context& ctx) {
303     for (NodeDeque::iterator iter = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) {
304       Node& child = *iter;
305       out.push_back(nodeToComplexSelector(child, ctx));
306     }
307   }
308
309   Node complexSelectorDequeToNode(const ComplexSelectorDeque& deque, Context& ctx) {
310     Node result = Node::createCollection();
311
312     for (ComplexSelectorDeque::const_iterator iter = deque.begin(), iterEnd = deque.end(); iter != iterEnd; iter++) {
313       Complex_Selector_Obj pChild = *iter;
314       result.collection()->push_back(complexSelectorToNode(pChild, ctx));
315     }
316
317     return result;
318   }
319
320   class LcsCollectionComparator {
321   public:
322     LcsCollectionComparator(Context& ctx) : mCtx(ctx) {}
323
324     Context& mCtx;
325
326     bool operator()(Complex_Selector_Obj pOne, Complex_Selector_Obj pTwo, Complex_Selector_Obj& pOut) const {
327       /*
328       This code is based on the following block from ruby sass' subweave
329         do |s1, s2|
330           next s1 if s1 == s2
331           next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
332           next s2 if parent_superselector?(s1, s2)
333           next s1 if parent_superselector?(s2, s1)
334         end
335       */
336
337       if (*pOne == *pTwo) {
338         pOut = pOne;
339         return true;
340       }
341
342       if (pOne->combinator() != Complex_Selector::ANCESTOR_OF || pTwo->combinator() != Complex_Selector::ANCESTOR_OF) {
343         return false;
344       }
345
346       if (parentSuperselector(pOne, pTwo, mCtx)) {
347         pOut = pTwo;
348         return true;
349       }
350
351       if (parentSuperselector(pTwo, pOne, mCtx)) {
352         pOut = pOne;
353         return true;
354       }
355
356       return false;
357     }
358   };
359
360
361   /*
362   This is the equivalent of ruby's Sass::Util.lcs_backtrace.
363
364   # Computes a single longest common subsequence for arrays x and y.
365   # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS
366   */
367   void lcs_backtrace(const LCSTable& c, ComplexSelectorDeque& x, ComplexSelectorDeque& y, int i, int j, const LcsCollectionComparator& comparator, ComplexSelectorDeque& out) {
368     //DEBUG_PRINTLN(LCS, "LCSBACK: X=" << x << " Y=" << y << " I=" << i << " J=" << j)
369     // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
370
371     if (i == 0 || j == 0) {
372       DEBUG_PRINTLN(LCS, "RETURNING EMPTY")
373       return;
374     }
375
376
377     Complex_Selector_Obj pCompareOut;
378     if (comparator(x[i], y[j], pCompareOut)) {
379       DEBUG_PRINTLN(LCS, "RETURNING AFTER ELEM COMPARE")
380       lcs_backtrace(c, x, y, i - 1, j - 1, comparator, out);
381       out.push_back(pCompareOut);
382       return;
383     }
384
385     if (c[i][j - 1] > c[i - 1][j]) {
386       DEBUG_PRINTLN(LCS, "RETURNING AFTER TABLE COMPARE")
387       lcs_backtrace(c, x, y, i, j - 1, comparator, out);
388       return;
389     }
390
391     DEBUG_PRINTLN(LCS, "FINAL RETURN")
392     lcs_backtrace(c, x, y, i - 1, j, comparator, out);
393     return;
394   }
395
396   /*
397   This is the equivalent of ruby's Sass::Util.lcs_table.
398
399   # Calculates the memoization table for the Least Common Subsequence algorithm.
400   # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS
401   */
402   void lcs_table(const ComplexSelectorDeque& x, const ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, LCSTable& out) {
403     //DEBUG_PRINTLN(LCS, "LCSTABLE: X=" << x << " Y=" << y)
404     // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
405
406     LCSTable c(x.size(), std::vector<int>(y.size()));
407
408     // These shouldn't be necessary since the vector will be initialized to 0 already.
409     // x.size.times {|i| c[i][0] = 0}
410     // y.size.times {|j| c[0][j] = 0}
411
412     for (size_t i = 1; i < x.size(); i++) {
413       for (size_t j = 1; j < y.size(); j++) {
414         Complex_Selector_Obj pCompareOut;
415
416         if (comparator(x[i], y[j], pCompareOut)) {
417           c[i][j] = c[i - 1][j - 1] + 1;
418         } else {
419           c[i][j] = std::max(c[i][j - 1], c[i - 1][j]);
420         }
421       }
422     }
423
424     out = c;
425   }
426
427   /*
428   This is the equivalent of ruby's Sass::Util.lcs.
429
430   # Computes a single longest common subsequence for `x` and `y`.
431   # If there are more than one longest common subsequences,
432   # the one returned is that which starts first in `x`.
433
434   # @param x [NodeCollection]
435   # @param y [NodeCollection]
436   # @comparator An equality check between elements of `x` and `y`.
437   # @return [NodeCollection] The LCS
438
439   http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
440   */
441   void lcs(ComplexSelectorDeque& x, ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, Context& ctx, ComplexSelectorDeque& out) {
442     //DEBUG_PRINTLN(LCS, "LCS: X=" << x << " Y=" << y)
443     // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
444
445     x.push_front(NULL);
446     y.push_front(NULL);
447
448     LCSTable table;
449     lcs_table(x, y, comparator, table);
450
451     return lcs_backtrace(table, x, y, static_cast<int>(x.size()) - 1, static_cast<int>(y.size()) - 1, comparator, out);
452   }
453
454
455   /*
456    This is the equivalent of ruby's Sequence.trim.
457
458    The following is the modified version of the ruby code that was more portable to C++. You
459    should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
460
461         # Avoid truly horrific quadratic behavior. TODO: I think there
462         # may be a way to get perfect trimming without going quadratic.
463         return seqses if seqses.size > 100
464
465         # Keep the results in a separate array so we can be sure we aren't
466         # comparing against an already-trimmed selector. This ensures that two
467         # identical selectors don't mutually trim one another.
468         result = seqses.dup
469
470         # This is n^2 on the sequences, but only comparing between
471         # separate sequences should limit the quadratic behavior.
472         seqses.each_with_index do |seqs1, i|
473           tempResult = []
474
475           for seq1 in seqs1 do
476             max_spec = 0
477             for seq in _sources(seq1) do
478               max_spec = [max_spec, seq.specificity].max
479             end
480
481
482             isMoreSpecificOuter = false
483             for seqs2 in result do
484               if seqs1.equal?(seqs2) then
485                 next
486               end
487
488               # Second Law of Extend: the specificity of a generated selector
489               # should never be less than the specificity of the extending
490               # selector.
491               #
492               # See https://github.com/nex3/sass/issues/324.
493               isMoreSpecificInner = false
494               for seq2 in seqs2 do
495                 isMoreSpecificInner = _specificity(seq2) >= max_spec && _superselector?(seq2, seq1)
496                 if isMoreSpecificInner then
497                   break
498                 end
499               end
500
501               if isMoreSpecificInner then
502                 isMoreSpecificOuter = true
503                 break
504               end
505             end
506
507             if !isMoreSpecificOuter then
508               tempResult.push(seq1)
509             end
510           end
511
512           result[i] = tempResult
513
514         end
515
516         result
517    */
518   /*
519    - IMPROVEMENT: We could probably work directly in the output trimmed deque.
520    */
521   static Node trim(Node& seqses, Context& ctx, bool isReplace) {
522     // See the comments in the above ruby code before embarking on understanding this function.
523
524     // Avoid poor performance in extreme cases.
525     if (seqses.collection()->size() > 100) {
526       return seqses;
527     }
528
529
530     DEBUG_PRINTLN(TRIM, "TRIM: " << seqses)
531
532
533     Node result = Node::createCollection();
534     result.plus(seqses);
535
536     DEBUG_PRINTLN(TRIM, "RESULT INITIAL: " << result)
537
538     // Normally we use the standard STL iterators, but in this case, we need to access the result collection by index since we're
539     // iterating the input collection, computing a value, and then setting the result in the output collection. We have to keep track
540     // of the index manually.
541     int toTrimIndex = 0;
542
543     for (NodeDeque::iterator seqsesIter = seqses.collection()->begin(), seqsesIterEnd = seqses.collection()->end(); seqsesIter != seqsesIterEnd; ++seqsesIter) {
544       Node& seqs1 = *seqsesIter;
545
546       DEBUG_PRINTLN(TRIM, "SEQS1: " << seqs1 << " " << toTrimIndex)
547
548       Node tempResult = Node::createCollection();
549       tempResult.got_line_feed = seqs1.got_line_feed;
550
551       for (NodeDeque::iterator seqs1Iter = seqs1.collection()->begin(), seqs1EndIter = seqs1.collection()->end(); seqs1Iter != seqs1EndIter; ++seqs1Iter) {
552         Node& seq1 = *seqs1Iter;
553
554         Complex_Selector_Obj pSeq1 = nodeToComplexSelector(seq1, ctx);
555
556         // Compute the maximum specificity. This requires looking at the "sources" of the sequence. See SimpleSequence.sources in the ruby code
557         // for a good description of sources.
558         //
559         // TODO: I'm pretty sure there's a bug in the sources code. It was implemented for sass-spec's 182_test_nested_extend_loop test.
560         // While the test passes, I compared the state of each trim call to verify correctness. The last trim call had incorrect sources. We
561         // had an extra source that the ruby version did not have. Without a failing test case, this is going to be extra hard to find. My
562         // best guess at this point is that we're cloning an object somewhere and maintaining the sources when we shouldn't be. This is purely
563         // a guess though.
564         unsigned long maxSpecificity = isReplace ? pSeq1->specificity() : 0;
565         ComplexSelectorSet sources = pSeq1->sources();
566
567         DEBUG_PRINTLN(TRIM, "TRIM SEQ1: " << seq1)
568         DEBUG_EXEC(TRIM, printSourcesSet(sources, ctx, "TRIM SOURCES: "))
569
570         for (ComplexSelectorSet::iterator sourcesSetIterator = sources.begin(), sourcesSetIteratorEnd = sources.end(); sourcesSetIterator != sourcesSetIteratorEnd; ++sourcesSetIterator) {
571           const Complex_Selector_Obj& pCurrentSelector = *sourcesSetIterator;
572           maxSpecificity = std::max(maxSpecificity, pCurrentSelector->specificity());
573         }
574
575         DEBUG_PRINTLN(TRIM, "MAX SPECIFICITY: " << maxSpecificity)
576
577         bool isMoreSpecificOuter = false;
578
579         int resultIndex = 0;
580
581         for (NodeDeque::iterator resultIter = result.collection()->begin(), resultIterEnd = result.collection()->end(); resultIter != resultIterEnd; ++resultIter) {
582           Node& seqs2 = *resultIter;
583
584           DEBUG_PRINTLN(TRIM, "SEQS1: " << seqs1)
585           DEBUG_PRINTLN(TRIM, "SEQS2: " << seqs2)
586
587           // Do not compare the same sequence to itself. The ruby call we're trying to
588           // emulate is: seqs1.equal?(seqs2). equal? is an object comparison, not an equivalency comparision.
589           // Since we have the same pointers in seqes and results, we can do a pointer comparision. seqs1 is
590           // derived from seqses and seqs2 is derived from result.
591           if (seqs1.collection() == seqs2.collection()) {
592             DEBUG_PRINTLN(TRIM, "CONTINUE")
593             continue;
594           }
595
596           bool isMoreSpecificInner = false;
597
598           for (NodeDeque::iterator seqs2Iter = seqs2.collection()->begin(), seqs2IterEnd = seqs2.collection()->end(); seqs2Iter != seqs2IterEnd; ++seqs2Iter) {
599             Node& seq2 = *seqs2Iter;
600
601             Complex_Selector_Obj pSeq2 = nodeToComplexSelector(seq2, ctx);
602
603             DEBUG_PRINTLN(TRIM, "SEQ2 SPEC: " << pSeq2->specificity())
604             DEBUG_PRINTLN(TRIM, "IS SPEC: " << pSeq2->specificity() << " >= " << maxSpecificity << " " << (pSeq2->specificity() >= maxSpecificity ? "true" : "false"))
605             DEBUG_PRINTLN(TRIM, "IS SUPER: " << (pSeq2->is_superselector_of(pSeq1) ? "true" : "false"))
606
607             isMoreSpecificInner = pSeq2->specificity() >= maxSpecificity && pSeq2->is_superselector_of(pSeq1);
608
609             if (isMoreSpecificInner) {
610               DEBUG_PRINTLN(TRIM, "FOUND MORE SPECIFIC")
611               break;
612             }
613           }
614
615           // If we found something more specific, we're done. Let the outer loop know and stop iterating.
616           if (isMoreSpecificInner) {
617             isMoreSpecificOuter = true;
618             break;
619           }
620
621           resultIndex++;
622         }
623
624         if (!isMoreSpecificOuter) {
625           DEBUG_PRINTLN(TRIM, "PUSHING: " << seq1)
626           tempResult.collection()->push_back(seq1);
627         }
628
629       }
630
631       DEBUG_PRINTLN(TRIM, "RESULT BEFORE ASSIGN: " << result)
632       DEBUG_PRINTLN(TRIM, "TEMP RESULT: " << toTrimIndex << " " << tempResult)
633       (*result.collection())[toTrimIndex] = tempResult;
634
635       toTrimIndex++;
636
637       DEBUG_PRINTLN(TRIM, "RESULT: " << result)
638     }
639
640     return result;
641   }
642
643
644
645   static bool parentSuperselector(const Node& one, const Node& two, Context& ctx) {
646     // TODO: figure out a better way to create a Complex_Selector from scratch
647     // TODO: There's got to be a better way. This got ugly quick...
648     Position noPosition(-1, -1, -1);
649     Element_Selector_Obj fakeParent = SASS_MEMORY_NEW(Element_Selector, ParserState("[FAKE]"), "temp");
650     Compound_Selector_Obj fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[FAKE]"), 1 /*size*/);
651     fakeHead->elements().push_back(fakeParent);
652     Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, fakeHead /*head*/, NULL /*tail*/);
653
654     Complex_Selector_Obj pOneWithFakeParent = nodeToComplexSelector(one, ctx);
655     pOneWithFakeParent->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
656     Complex_Selector_Obj pTwoWithFakeParent = nodeToComplexSelector(two, ctx);
657     pTwoWithFakeParent->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
658
659     return pOneWithFakeParent->is_superselector_of(pTwoWithFakeParent);
660   }
661
662
663   class ParentSuperselectorChunker {
664   public:
665     ParentSuperselectorChunker(Node& lcs, Context& ctx) : mLcs(lcs), mCtx(ctx) {}
666     Node& mLcs;
667     Context& mCtx;
668
669     bool operator()(const Node& seq) const {
670       // {|s| parent_superselector?(s.first, lcs.first)}
671       if (seq.collection()->size() == 0) return false;
672       return parentSuperselector(seq.collection()->front(), mLcs.collection()->front(), mCtx);
673     }
674   };
675
676   class SubweaveEmptyChunker {
677   public:
678     bool operator()(const Node& seq) const {
679       // {|s| s.empty?}
680
681       return seq.collection()->empty();
682     }
683   };
684
685   /*
686   # Takes initial subsequences of `seq1` and `seq2` and returns all
687   # orderings of those subsequences. The initial subsequences are determined
688   # by a block.
689   #
690   # Destructively removes the initial subsequences of `seq1` and `seq2`.
691   #
692   # For example, given `(A B C | D E)` and `(1 2 | 3 4 5)` (with `|`
693   # denoting the boundary of the initial subsequence), this would return
694   # `[(A B C 1 2), (1 2 A B C)]`. The sequences would then be `(D E)` and
695   # `(3 4 5)`.
696   #
697   # @param seq1 [Array]
698   # @param seq2 [Array]
699   # @yield [a] Used to determine when to cut off the initial subsequences.
700   #   Called repeatedly for each sequence until it returns true.
701   # @yieldparam a [Array] A final subsequence of one input sequence after
702   #   cutting off some initial subsequence.
703   # @yieldreturn [Boolean] Whether or not to cut off the initial subsequence
704   #   here.
705   # @return [Array<Array>] All possible orderings of the initial subsequences.
706   def chunks(seq1, seq2)
707     chunk1 = []
708     chunk1 << seq1.shift until yield seq1
709     chunk2 = []
710     chunk2 << seq2.shift until yield seq2
711     return [] if chunk1.empty? && chunk2.empty?
712     return [chunk2] if chunk1.empty?
713     return [chunk1] if chunk2.empty?
714     [chunk1 + chunk2, chunk2 + chunk1]
715   end
716   */
717   template<typename ChunkerType>
718   static Node chunks(Node& seq1, Node& seq2, const ChunkerType& chunker) {
719     Node chunk1 = Node::createCollection();
720     while (seq1.collection()->size() && !chunker(seq1)) {
721       chunk1.collection()->push_back(seq1.collection()->front());
722       seq1.collection()->pop_front();
723     }
724
725     Node chunk2 = Node::createCollection();
726     while (!chunker(seq2)) {
727       chunk2.collection()->push_back(seq2.collection()->front());
728       seq2.collection()->pop_front();
729     }
730
731     if (chunk1.collection()->empty() && chunk2.collection()->empty()) {
732       DEBUG_PRINTLN(CHUNKS, "RETURNING BOTH EMPTY")
733       return Node::createCollection();
734     }
735
736     if (chunk1.collection()->empty()) {
737       Node chunk2Wrapper = Node::createCollection();
738       chunk2Wrapper.collection()->push_back(chunk2);
739       DEBUG_PRINTLN(CHUNKS, "RETURNING ONE EMPTY")
740       return chunk2Wrapper;
741     }
742
743     if (chunk2.collection()->empty()) {
744       Node chunk1Wrapper = Node::createCollection();
745       chunk1Wrapper.collection()->push_back(chunk1);
746       DEBUG_PRINTLN(CHUNKS, "RETURNING TWO EMPTY")
747       return chunk1Wrapper;
748     }
749
750     Node perms = Node::createCollection();
751
752     Node firstPermutation = Node::createCollection();
753     firstPermutation.collection()->insert(firstPermutation.collection()->end(), chunk1.collection()->begin(), chunk1.collection()->end());
754     firstPermutation.collection()->insert(firstPermutation.collection()->end(), chunk2.collection()->begin(), chunk2.collection()->end());
755     perms.collection()->push_back(firstPermutation);
756
757     Node secondPermutation = Node::createCollection();
758     secondPermutation.collection()->insert(secondPermutation.collection()->end(), chunk2.collection()->begin(), chunk2.collection()->end());
759     secondPermutation.collection()->insert(secondPermutation.collection()->end(), chunk1.collection()->begin(), chunk1.collection()->end());
760     perms.collection()->push_back(secondPermutation);
761
762     DEBUG_PRINTLN(CHUNKS, "RETURNING PERM")
763
764     return perms;
765   }
766
767
768   static Node groupSelectors(Node& seq, Context& ctx) {
769     Node newSeq = Node::createCollection();
770
771     Node tail = Node::createCollection();
772     tail.plus(seq);
773
774     while (!tail.collection()->empty()) {
775       Node head = Node::createCollection();
776
777       do {
778         head.collection()->push_back(tail.collection()->front());
779         tail.collection()->pop_front();
780       } while (!tail.collection()->empty() && (head.collection()->back().isCombinator() || tail.collection()->front().isCombinator()));
781
782       newSeq.collection()->push_back(head);
783     }
784
785     return newSeq;
786   }
787
788
789   static void getAndRemoveInitialOps(Node& seq, Node& ops) {
790     NodeDeque& seqCollection = *(seq.collection());
791     NodeDeque& opsCollection = *(ops.collection());
792
793     while (seqCollection.size() > 0 && seqCollection.front().isCombinator()) {
794       opsCollection.push_back(seqCollection.front());
795       seqCollection.pop_front();
796     }
797   }
798
799
800   static void getAndRemoveFinalOps(Node& seq, Node& ops) {
801     NodeDeque& seqCollection = *(seq.collection());
802     NodeDeque& opsCollection = *(ops.collection());
803
804     while (seqCollection.size() > 0 && seqCollection.back().isCombinator()) {
805       opsCollection.push_back(seqCollection.back()); // Purposefully reversed to match ruby code
806       seqCollection.pop_back();
807     }
808   }
809
810
811   /*
812       def merge_initial_ops(seq1, seq2)
813         ops1, ops2 = [], []
814         ops1 << seq1.shift while seq1.first.is_a?(String)
815         ops2 << seq2.shift while seq2.first.is_a?(String)
816
817         newline = false
818         newline ||= !!ops1.shift if ops1.first == "\n"
819         newline ||= !!ops2.shift if ops2.first == "\n"
820
821         # If neither sequence is a subsequence of the other, they cannot be
822         # merged successfully
823         lcs = Sass::Util.lcs(ops1, ops2)
824         return unless lcs == ops1 || lcs == ops2
825         return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2)
826       end
827   */
828   static Node mergeInitialOps(Node& seq1, Node& seq2, Context& ctx) {
829     Node ops1 = Node::createCollection();
830     Node ops2 = Node::createCollection();
831
832     getAndRemoveInitialOps(seq1, ops1);
833     getAndRemoveInitialOps(seq2, ops2);
834
835     // TODO: Do we have this information available to us?
836     // newline = false
837     // newline ||= !!ops1.shift if ops1.first == "\n"
838     // newline ||= !!ops2.shift if ops2.first == "\n"
839
840     // If neither sequence is a subsequence of the other, they cannot be merged successfully
841     DefaultLcsComparator lcsDefaultComparator;
842     Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator, ctx);
843
844     if (!(opsLcs == ops1 || opsLcs == ops2)) {
845       return Node::createNil();
846     }
847
848     // TODO: more newline logic
849     // return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2)
850
851     return (ops1.collection()->size() > ops2.collection()->size() ? ops1 : ops2);
852   }
853
854
855   /*
856       def merge_final_ops(seq1, seq2, res = [])
857
858
859         # This code looks complicated, but it's actually just a bunch of special
860         # cases for interactions between different combinators.
861         op1, op2 = ops1.first, ops2.first
862         if op1 && op2
863           sel1 = seq1.pop
864           sel2 = seq2.pop
865           if op1 == '~' && op2 == '~'
866             if sel1.superselector?(sel2)
867               res.unshift sel2, '~'
868             elsif sel2.superselector?(sel1)
869               res.unshift sel1, '~'
870             else
871               merged = sel1.unify(sel2.members, sel2.subject?)
872               res.unshift [
873                 [sel1, '~', sel2, '~'],
874                 [sel2, '~', sel1, '~'],
875                 ([merged, '~'] if merged)
876               ].compact
877             end
878           elsif (op1 == '~' && op2 == '+') || (op1 == '+' && op2 == '~')
879             if op1 == '~'
880               tilde_sel, plus_sel = sel1, sel2
881             else
882               tilde_sel, plus_sel = sel2, sel1
883             end
884
885             if tilde_sel.superselector?(plus_sel)
886               res.unshift plus_sel, '+'
887             else
888               merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
889               res.unshift [
890                 [tilde_sel, '~', plus_sel, '+'],
891                 ([merged, '+'] if merged)
892               ].compact
893             end
894           elsif op1 == '>' && %w[~ +].include?(op2)
895             res.unshift sel2, op2
896             seq1.push sel1, op1
897           elsif op2 == '>' && %w[~ +].include?(op1)
898             res.unshift sel1, op1
899             seq2.push sel2, op2
900           elsif op1 == op2
901             return unless merged = sel1.unify(sel2.members, sel2.subject?)
902             res.unshift merged, op1
903           else
904             # Unknown selector combinators can't be unified
905             return
906           end
907           return merge_final_ops(seq1, seq2, res)
908         elsif op1
909           seq2.pop if op1 == '>' && seq2.last && seq2.last.superselector?(seq1.last)
910           res.unshift seq1.pop, op1
911           return merge_final_ops(seq1, seq2, res)
912         else # op2
913           seq1.pop if op2 == '>' && seq1.last && seq1.last.superselector?(seq2.last)
914           res.unshift seq2.pop, op2
915           return merge_final_ops(seq1, seq2, res)
916         end
917       end
918   */
919   static Node mergeFinalOps(Node& seq1, Node& seq2, Context& ctx, Node& res) {
920
921     Node ops1 = Node::createCollection();
922     Node ops2 = Node::createCollection();
923
924     getAndRemoveFinalOps(seq1, ops1);
925     getAndRemoveFinalOps(seq2, ops2);
926
927     // TODO: do we have newlines to remove?
928     // ops1.reject! {|o| o == "\n"}
929     // ops2.reject! {|o| o == "\n"}
930
931     if (ops1.collection()->empty() && ops2.collection()->empty()) {
932       return res;
933     }
934
935     if (ops1.collection()->size() > 1 || ops2.collection()->size() > 1) {
936       DefaultLcsComparator lcsDefaultComparator;
937       Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator, ctx);
938
939       // If there are multiple operators, something hacky's going on. If one is a supersequence of the other, use that, otherwise give up.
940
941       if (!(opsLcs == ops1 || opsLcs == ops2)) {
942         return Node::createNil();
943       }
944
945       if (ops1.collection()->size() > ops2.collection()->size()) {
946         res.collection()->insert(res.collection()->begin(), ops1.collection()->rbegin(), ops1.collection()->rend());
947       } else {
948         res.collection()->insert(res.collection()->begin(), ops2.collection()->rbegin(), ops2.collection()->rend());
949       }
950
951       return res;
952     }
953
954     if (!ops1.collection()->empty() && !ops2.collection()->empty()) {
955
956       Node op1 = ops1.collection()->front();
957       Node op2 = ops2.collection()->front();
958
959       Node sel1 = seq1.collection()->back();
960       seq1.collection()->pop_back();
961
962       Node sel2 = seq2.collection()->back();
963       seq2.collection()->pop_back();
964
965       if (op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::PRECEDES) {
966
967         if (sel1.selector()->is_superselector_of(sel2.selector())) {
968
969           res.collection()->push_front(op1 /*PRECEDES - could have been op2 as well*/);
970           res.collection()->push_front(sel2);
971
972         } else if (sel2.selector()->is_superselector_of(sel1.selector())) {
973
974           res.collection()->push_front(op1 /*PRECEDES - could have been op2 as well*/);
975           res.collection()->push_front(sel1);
976
977         } else {
978
979           DEBUG_PRINTLN(ALL, "sel1: " << sel1)
980           DEBUG_PRINTLN(ALL, "sel2: " << sel2)
981
982           Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
983           // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
984           Compound_Selector_Ptr pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
985           pMergedWrapper->head(pMerged);
986
987           DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
988
989           Node newRes = Node::createCollection();
990
991           Node firstPerm = Node::createCollection();
992           firstPerm.collection()->push_back(sel1);
993           firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
994           firstPerm.collection()->push_back(sel2);
995           firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
996           newRes.collection()->push_back(firstPerm);
997
998           Node secondPerm = Node::createCollection();
999           secondPerm.collection()->push_back(sel2);
1000           secondPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1001           secondPerm.collection()->push_back(sel1);
1002           secondPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1003           newRes.collection()->push_back(secondPerm);
1004
1005           if (pMerged) {
1006             Node mergedPerm = Node::createCollection();
1007             mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper, ctx));
1008             mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1009             newRes.collection()->push_back(mergedPerm);
1010           }
1011
1012           res.collection()->push_front(newRes);
1013
1014           DEBUG_PRINTLN(ALL, "RESULT: " << res)
1015
1016         }
1017
1018       } else if (((op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::ADJACENT_TO)) || ((op1.combinator() == Complex_Selector::ADJACENT_TO && op2.combinator() == Complex_Selector::PRECEDES))) {
1019
1020           Node tildeSel = sel1;
1021           Node tildeOp = op1;
1022           Node plusSel = sel2;
1023           Node plusOp = op2;
1024           if (op1.combinator() != Complex_Selector::PRECEDES) {
1025             tildeSel = sel2;
1026             tildeOp = op2;
1027             plusSel = sel1;
1028             plusOp = op1;
1029           }
1030
1031           if (tildeSel.selector()->is_superselector_of(plusSel.selector())) {
1032
1033             res.collection()->push_front(plusOp);
1034             res.collection()->push_front(plusSel);
1035
1036           } else {
1037
1038             DEBUG_PRINTLN(ALL, "PLUS SEL: " << plusSel)
1039             DEBUG_PRINTLN(ALL, "TILDE SEL: " << tildeSel)
1040
1041             Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(plusSel.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
1042             // TODO: does subject matter? Ruby: merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
1043             Compound_Selector_Ptr pMerged = plusSel.selector()->head()->unify_with(tildeSel.selector()->head(), ctx);
1044             pMergedWrapper->head(pMerged);
1045
1046             DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
1047
1048             Node newRes = Node::createCollection();
1049
1050             Node firstPerm = Node::createCollection();
1051             firstPerm.collection()->push_back(tildeSel);
1052             firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1053             firstPerm.collection()->push_back(plusSel);
1054             firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO));
1055             newRes.collection()->push_back(firstPerm);
1056
1057             if (pMerged) {
1058               Node mergedPerm = Node::createCollection();
1059               mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper, ctx));
1060               mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO));
1061               newRes.collection()->push_back(mergedPerm);
1062             }
1063
1064             res.collection()->push_front(newRes);
1065
1066             DEBUG_PRINTLN(ALL, "RESULT: " << res)
1067
1068           }
1069       } else if (op1.combinator() == Complex_Selector::PARENT_OF && (op2.combinator() == Complex_Selector::PRECEDES || op2.combinator() == Complex_Selector::ADJACENT_TO)) {
1070
1071         res.collection()->push_front(op2);
1072         res.collection()->push_front(sel2);
1073
1074         seq1.collection()->push_back(sel1);
1075         seq1.collection()->push_back(op1);
1076
1077       } else if (op2.combinator() == Complex_Selector::PARENT_OF && (op1.combinator() == Complex_Selector::PRECEDES || op1.combinator() == Complex_Selector::ADJACENT_TO)) {
1078
1079         res.collection()->push_front(op1);
1080         res.collection()->push_front(sel1);
1081
1082         seq2.collection()->push_back(sel2);
1083         seq2.collection()->push_back(op2);
1084
1085       } else if (op1.combinator() == op2.combinator()) {
1086
1087         DEBUG_PRINTLN(ALL, "sel1: " << sel1)
1088         DEBUG_PRINTLN(ALL, "sel2: " << sel2)
1089
1090         Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
1091         // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
1092         Compound_Selector_Ptr pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head(), ctx);
1093         pMergedWrapper->head(pMerged);
1094
1095         DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
1096
1097         if (!pMerged) {
1098           return Node::createNil();
1099         }
1100
1101         res.collection()->push_front(op1);
1102         res.collection()->push_front(Node::createSelector(pMergedWrapper, ctx));
1103
1104         DEBUG_PRINTLN(ALL, "RESULT: " << res)
1105
1106       } else {
1107         return Node::createNil();
1108       }
1109
1110       return mergeFinalOps(seq1, seq2, ctx, res);
1111
1112     } else if (!ops1.collection()->empty()) {
1113
1114       Node op1 = ops1.collection()->front();
1115
1116       if (op1.combinator() == Complex_Selector::PARENT_OF && !seq2.collection()->empty() && seq2.collection()->back().selector()->is_superselector_of(seq1.collection()->back().selector())) {
1117         seq2.collection()->pop_back();
1118       }
1119
1120       // TODO: consider unshift(NodeCollection, Node)
1121       res.collection()->push_front(op1);
1122       res.collection()->push_front(seq1.collection()->back());
1123       seq1.collection()->pop_back();
1124
1125       return mergeFinalOps(seq1, seq2, ctx, res);
1126
1127     } else { // !ops2.collection()->empty()
1128
1129       Node op2 = ops2.collection()->front();
1130
1131       if (op2.combinator() == Complex_Selector::PARENT_OF && !seq1.collection()->empty() && seq1.collection()->back().selector()->is_superselector_of(seq2.collection()->back().selector())) {
1132         seq1.collection()->pop_back();
1133       }
1134
1135       res.collection()->push_front(op2);
1136       res.collection()->push_front(seq2.collection()->back());
1137       seq2.collection()->pop_back();
1138
1139       return mergeFinalOps(seq1, seq2, ctx, res);
1140
1141     }
1142
1143   }
1144
1145
1146   /*
1147     This is the equivalent of ruby's Sequence.subweave.
1148
1149     Here is the original subweave code for reference during porting.
1150
1151       def subweave(seq1, seq2)
1152         return [seq2] if seq1.empty?
1153         return [seq1] if seq2.empty?
1154
1155         seq1, seq2 = seq1.dup, seq2.dup
1156         return unless init = merge_initial_ops(seq1, seq2)
1157         return unless fin = merge_final_ops(seq1, seq2)
1158         seq1 = group_selectors(seq1)
1159         seq2 = group_selectors(seq2)
1160         lcs = Sass::Util.lcs(seq2, seq1) do |s1, s2|
1161           next s1 if s1 == s2
1162           next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
1163           next s2 if parent_superselector?(s1, s2)
1164           next s1 if parent_superselector?(s2, s1)
1165         end
1166
1167         diff = [[init]]
1168         until lcs.empty?
1169           diff << chunks(seq1, seq2) {|s| parent_superselector?(s.first, lcs.first)} << [lcs.shift]
1170           seq1.shift
1171           seq2.shift
1172         end
1173         diff << chunks(seq1, seq2) {|s| s.empty?}
1174         diff += fin.map {|sel| sel.is_a?(Array) ? sel : [sel]}
1175         diff.reject! {|c| c.empty?}
1176
1177         result = Sass::Util.paths(diff).map {|p| p.flatten}.reject {|p| path_has_two_subjects?(p)}
1178
1179         result
1180       end
1181   */
1182   Node Extend::subweave(Node& one, Node& two, Context& ctx) {
1183     // Check for the simple cases
1184     if (one.collection()->size() == 0) {
1185       Node out = Node::createCollection();
1186       out.collection()->push_back(two);
1187       return out;
1188     }
1189     if (two.collection()->size() == 0) {
1190       Node out = Node::createCollection();
1191       out.collection()->push_back(one);
1192       return out;
1193     }
1194
1195
1196
1197     Node seq1 = Node::createCollection();
1198     seq1.plus(one);
1199     Node seq2 = Node::createCollection();
1200     seq2.plus(two);
1201
1202     DEBUG_PRINTLN(SUBWEAVE, "SUBWEAVE ONE: " << seq1)
1203     DEBUG_PRINTLN(SUBWEAVE, "SUBWEAVE TWO: " << seq2)
1204
1205     Node init = mergeInitialOps(seq1, seq2, ctx);
1206     if (init.isNil()) {
1207       return Node::createNil();
1208     }
1209
1210     DEBUG_PRINTLN(SUBWEAVE, "INIT: " << init)
1211
1212     Node res = Node::createCollection();
1213     Node fin = mergeFinalOps(seq1, seq2, ctx, res);
1214     if (fin.isNil()) {
1215       return Node::createNil();
1216     }
1217
1218     DEBUG_PRINTLN(SUBWEAVE, "FIN: " << fin)
1219
1220
1221     // Moving this line up since fin isn't modified between now and when it happened before
1222     // fin.map {|sel| sel.is_a?(Array) ? sel : [sel]}
1223
1224     for (NodeDeque::iterator finIter = fin.collection()->begin(), finEndIter = fin.collection()->end();
1225            finIter != finEndIter; ++finIter) {
1226
1227       Node& childNode = *finIter;
1228
1229       if (!childNode.isCollection()) {
1230         Node wrapper = Node::createCollection();
1231         wrapper.collection()->push_back(childNode);
1232         childNode = wrapper;
1233       }
1234
1235     }
1236
1237     DEBUG_PRINTLN(SUBWEAVE, "FIN MAPPED: " << fin)
1238
1239
1240
1241     Node groupSeq1 = groupSelectors(seq1, ctx);
1242     DEBUG_PRINTLN(SUBWEAVE, "SEQ1: " << groupSeq1)
1243
1244     Node groupSeq2 = groupSelectors(seq2, ctx);
1245     DEBUG_PRINTLN(SUBWEAVE, "SEQ2: " << groupSeq2)
1246
1247
1248     ComplexSelectorDeque groupSeq1Converted;
1249     nodeToComplexSelectorDeque(groupSeq1, groupSeq1Converted, ctx);
1250
1251     ComplexSelectorDeque groupSeq2Converted;
1252     nodeToComplexSelectorDeque(groupSeq2, groupSeq2Converted, ctx);
1253
1254     ComplexSelectorDeque out;
1255     LcsCollectionComparator collectionComparator(ctx);
1256     lcs(groupSeq2Converted, groupSeq1Converted, collectionComparator, ctx, out);
1257     Node seqLcs = complexSelectorDequeToNode(out, ctx);
1258
1259     DEBUG_PRINTLN(SUBWEAVE, "SEQLCS: " << seqLcs)
1260
1261
1262     Node initWrapper = Node::createCollection();
1263     initWrapper.collection()->push_back(init);
1264     Node diff = Node::createCollection();
1265     diff.collection()->push_back(initWrapper);
1266
1267     DEBUG_PRINTLN(SUBWEAVE, "DIFF INIT: " << diff)
1268
1269
1270     while (!seqLcs.collection()->empty()) {
1271       ParentSuperselectorChunker superselectorChunker(seqLcs, ctx);
1272       Node chunksResult = chunks(groupSeq1, groupSeq2, superselectorChunker);
1273       diff.collection()->push_back(chunksResult);
1274
1275       Node lcsWrapper = Node::createCollection();
1276       lcsWrapper.collection()->push_back(seqLcs.collection()->front());
1277       seqLcs.collection()->pop_front();
1278       diff.collection()->push_back(lcsWrapper);
1279
1280       if (groupSeq1.collection()->size()) groupSeq1.collection()->pop_front();
1281       if (groupSeq2.collection()->size()) groupSeq2.collection()->pop_front();
1282     }
1283
1284     DEBUG_PRINTLN(SUBWEAVE, "DIFF POST LCS: " << diff)
1285
1286
1287     DEBUG_PRINTLN(SUBWEAVE, "CHUNKS: ONE=" << groupSeq1 << " TWO=" << groupSeq2)
1288
1289
1290     SubweaveEmptyChunker emptyChunker;
1291     Node chunksResult = chunks(groupSeq1, groupSeq2, emptyChunker);
1292     diff.collection()->push_back(chunksResult);
1293
1294
1295     DEBUG_PRINTLN(SUBWEAVE, "DIFF POST CHUNKS: " << diff)
1296
1297
1298     diff.collection()->insert(diff.collection()->end(), fin.collection()->begin(), fin.collection()->end());
1299
1300     DEBUG_PRINTLN(SUBWEAVE, "DIFF POST FIN MAPPED: " << diff)
1301
1302     // JMA - filter out the empty nodes (use a new collection, since iterator erase() invalidates the old collection)
1303     Node diffFiltered = Node::createCollection();
1304     for (NodeDeque::iterator diffIter = diff.collection()->begin(), diffEndIter = diff.collection()->end();
1305            diffIter != diffEndIter; ++diffIter) {
1306       Node& node = *diffIter;
1307       if (node.collection() && !node.collection()->empty()) {
1308         diffFiltered.collection()->push_back(node);
1309       }
1310     }
1311     diff = diffFiltered;
1312
1313     DEBUG_PRINTLN(SUBWEAVE, "DIFF POST REJECT: " << diff)
1314
1315
1316     Node pathsResult = paths(diff, ctx);
1317
1318     DEBUG_PRINTLN(SUBWEAVE, "PATHS: " << pathsResult)
1319
1320
1321     // We're flattening in place
1322     for (NodeDeque::iterator pathsIter = pathsResult.collection()->begin(), pathsEndIter = pathsResult.collection()->end();
1323       pathsIter != pathsEndIter; ++pathsIter) {
1324
1325       Node& child = *pathsIter;
1326       child = flatten(child, ctx);
1327     }
1328
1329     DEBUG_PRINTLN(SUBWEAVE, "FLATTENED: " << pathsResult)
1330
1331
1332     /*
1333       TODO: implement
1334       rejected = mapped.reject {|p| path_has_two_subjects?(p)}
1335       $stderr.puts "REJECTED: #{rejected}"
1336      */
1337
1338
1339     return pathsResult;
1340
1341   }
1342   /*
1343   // disabled to avoid clang warning [-Wunused-function]
1344   static Node subweaveNaive(const Node& one, const Node& two, Context& ctx) {
1345     Node out = Node::createCollection();
1346
1347     // Check for the simple cases
1348     if (one.isNil()) {
1349       out.collection()->push_back(two.klone(ctx));
1350     } else if (two.isNil()) {
1351       out.collection()->push_back(one.klone(ctx));
1352     } else {
1353       // Do the naive implementation. pOne = A B and pTwo = C D ...yields...  A B C D and C D A B
1354       // See https://gist.github.com/nex3/7609394 for details.
1355
1356       Node firstPerm = one.klone(ctx);
1357       Node twoCloned = two.klone(ctx);
1358       firstPerm.plus(twoCloned);
1359       out.collection()->push_back(firstPerm);
1360
1361       Node secondPerm = two.klone(ctx);
1362       Node oneCloned = one.klone(ctx);
1363       secondPerm.plus(oneCloned );
1364       out.collection()->push_back(secondPerm);
1365     }
1366
1367     return out;
1368   }
1369   */
1370
1371
1372   /*
1373    This is the equivalent of ruby's Sequence.weave.
1374
1375    The following is the modified version of the ruby code that was more portable to C++. You
1376    should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
1377
1378       def weave(path)
1379         # This function works by moving through the selector path left-to-right,
1380         # building all possible prefixes simultaneously. These prefixes are
1381         # `befores`, while the remaining parenthesized suffixes is `afters`.
1382         befores = [[]]
1383         afters = path.dup
1384
1385         until afters.empty?
1386           current = afters.shift.dup
1387           last_current = [current.pop]
1388
1389           tempResult = []
1390
1391           for before in befores do
1392             sub = subweave(before, current)
1393             if sub.nil?
1394               next
1395             end
1396
1397             for seqs in sub do
1398               tempResult.push(seqs + last_current)
1399             end
1400           end
1401
1402           befores = tempResult
1403
1404         end
1405
1406         return befores
1407       end
1408    */
1409   /*
1410       def weave(path)
1411         befores = [[]]
1412         afters = path.dup
1413
1414         until afters.empty?
1415           current = afters.shift.dup
1416
1417           last_current = [current.pop]
1418
1419
1420           tempResult = []
1421
1422           for before in befores do
1423             sub = subweave(before, current)
1424
1425             if sub.nil?
1426               next []
1427             end
1428
1429
1430             for seqs in sub do
1431               toPush = seqs + last_current
1432
1433               tempResult.push(seqs + last_current)
1434             end
1435
1436           end
1437
1438           befores = tempResult
1439
1440         end
1441
1442         return befores
1443       end
1444   */
1445   static Node weave(Node& path, Context& ctx) {
1446
1447     DEBUG_PRINTLN(WEAVE, "WEAVE: " << path)
1448
1449     Node befores = Node::createCollection();
1450     befores.collection()->push_back(Node::createCollection());
1451
1452     Node afters = Node::createCollection();
1453     afters.plus(path);
1454
1455     while (!afters.collection()->empty()) {
1456       Node current = afters.collection()->front().klone(ctx);
1457       afters.collection()->pop_front();
1458       DEBUG_PRINTLN(WEAVE, "CURRENT: " << current)
1459       if (current.collection()->size() == 0) continue;
1460
1461       Node last_current = Node::createCollection();
1462       last_current.collection()->push_back(current.collection()->back());
1463       current.collection()->pop_back();
1464       DEBUG_PRINTLN(WEAVE, "CURRENT POST POP: " << current)
1465       DEBUG_PRINTLN(WEAVE, "LAST CURRENT: " << last_current)
1466
1467       Node tempResult = Node::createCollection();
1468
1469       for (NodeDeque::iterator beforesIter = befores.collection()->begin(), beforesEndIter = befores.collection()->end(); beforesIter != beforesEndIter; beforesIter++) {
1470         Node& before = *beforesIter;
1471
1472         Node sub = Extend::subweave(before, current, ctx);
1473
1474         DEBUG_PRINTLN(WEAVE, "SUB: " << sub)
1475
1476         if (sub.isNil()) {
1477           return Node::createCollection();
1478         }
1479
1480         for (NodeDeque::iterator subIter = sub.collection()->begin(), subEndIter = sub.collection()->end(); subIter != subEndIter; subIter++) {
1481           Node& seqs = *subIter;
1482
1483           Node toPush = Node::createCollection();
1484           toPush.plus(seqs);
1485           toPush.plus(last_current);
1486
1487           tempResult.collection()->push_back(toPush);
1488
1489         }
1490       }
1491
1492       befores = tempResult;
1493
1494     }
1495
1496     return befores;
1497   }
1498
1499
1500
1501   // This forward declaration is needed since extendComplexSelector calls extendCompoundSelector, which may recursively
1502   // call extendComplexSelector again.
1503   static Node extendComplexSelector(
1504     Complex_Selector_Ptr pComplexSelector,
1505     Context& ctx,
1506     Subset_Map& subset_map,
1507     std::set<Compound_Selector> seen, bool isReplace, bool isOriginal);
1508
1509
1510
1511   /*
1512    This is the equivalent of ruby's SimpleSequence.do_extend.
1513
1514     // TODO: I think I have some modified ruby code to put here. Check.
1515   */
1516   /*
1517    ISSUES:
1518    - Previous TODO: Do we need to group the results by extender?
1519    - What does subject do in?: next unless unified = seq.members.last.unify(self_without_sel, subject?)
1520    - IMPROVEMENT: The search for uniqueness at the end is not ideal since it's has to loop over everything...
1521    - IMPROVEMENT: Check if the final search for uniqueness is doing anything that extendComplexSelector isn't already doing...
1522    */
1523   template<typename KeyType>
1524   class GroupByToAFunctor {
1525   public:
1526     KeyType operator()(SubSetMapPair& extPair) const {
1527       Complex_Selector_Obj pSelector = extPair.first;
1528       return pSelector;
1529     }
1530   };
1531   static Node extendCompoundSelector(
1532     Compound_Selector_Ptr pSelector,
1533     Context& ctx,
1534     Subset_Map& subset_map,
1535     std::set<Compound_Selector> seen, bool isReplace) {
1536
1537     DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND: "))
1538     // TODO: Ruby has another loop here to skip certain members?
1539
1540     Node extendedSelectors = Node::createCollection();
1541     // extendedSelectors.got_line_feed = true;
1542
1543     SubSetMapPairs entries = subset_map.get_v(pSelector);
1544
1545     GroupByToAFunctor<Complex_Selector_Obj> extPairKeyFunctor;
1546     SubSetMapResults arr;
1547     group_by_to_a(entries, extPairKeyFunctor, arr);
1548
1549     SubSetMapLookups holder;
1550
1551
1552     for (SubSetMapResults::iterator groupedIter = arr.begin(), groupedIterEnd = arr.end(); groupedIter != groupedIterEnd; groupedIter++) {
1553       SubSetMapResult& groupedPair = *groupedIter;
1554
1555       Complex_Selector_Obj seq = groupedPair.first;
1556       SubSetMapPairs& group = groupedPair.second;
1557
1558       DEBUG_EXEC(EXTEND_COMPOUND, printComplexSelector(seq, "SEQ: "))
1559
1560 // changing this makes aua
1561       Compound_Selector_Obj pSels = SASS_MEMORY_NEW(Compound_Selector, pSelector->pstate());
1562       for (SubSetMapPairs::iterator groupIter = group.begin(), groupIterEnd = group.end(); groupIter != groupIterEnd; groupIter++) {
1563         SubSetMapPair& pair = *groupIter;
1564         Compound_Selector_Obj pCompound = pair.second;
1565         for (size_t index = 0; index < pCompound->length(); index++) {
1566           Simple_Selector_Obj pSimpleSelector = (*pCompound)[index];
1567           pSels->append(pSimpleSelector);
1568           pCompound->extended(true);
1569         }
1570       }
1571
1572       DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSels, "SELS: "))
1573
1574       Complex_Selector_Ptr pExtComplexSelector = seq;    // The selector up to where the @extend is (ie, the thing to merge)
1575
1576       // TODO: This can return a Compound_Selector with no elements. Should that just be returning NULL?
1577       // RUBY: self_without_sel = Sass::Util.array_minus(members, sels)
1578       Compound_Selector_Obj pSelectorWithoutExtendSelectors = pSelector->minus(pSels, ctx);
1579
1580       DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "MEMBERS: "))
1581       DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "SELF_WO_SEL: "))
1582
1583       Compound_Selector_Obj pInnermostCompoundSelector = pExtComplexSelector->last()->head();
1584
1585       if (!pInnermostCompoundSelector) {
1586         pInnermostCompoundSelector = SASS_MEMORY_NEW(Compound_Selector, pSelector->pstate());
1587       }
1588       Compound_Selector_Obj pUnifiedSelector = pInnermostCompoundSelector->unify_with(pSelectorWithoutExtendSelectors, ctx);
1589
1590       DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pInnermostCompoundSelector, "LHS: "))
1591       DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "RHS: "))
1592       DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pUnifiedSelector, "UNIFIED: "))
1593
1594       // RUBY: next unless unified
1595       if (!pUnifiedSelector || pUnifiedSelector->length() == 0) {
1596         continue;
1597       }
1598
1599       // TODO: implement the parent directive match (if necessary based on test failures)
1600       // next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
1601
1602       // TODO: This seems a little fishy to me. See if it causes any problems. From the ruby, we should be able to just
1603       // get rid of the last Compound_Selector and replace it with this one. I think the reason this code is more
1604       // complex is that Complex_Selector contains a combinator, but in ruby combinators have already been filtered
1605       // out and aren't operated on.
1606       Complex_Selector_Obj pNewSelector = SASS_MEMORY_CLONE(pExtComplexSelector); // ->first();
1607
1608       Complex_Selector_Obj pNewInnerMost = SASS_MEMORY_NEW(Complex_Selector, pSelector->pstate(), Complex_Selector::ANCESTOR_OF, pUnifiedSelector, NULL);
1609
1610       Complex_Selector::Combinator combinator = pNewSelector->clear_innermost();
1611       pNewSelector->set_innermost(pNewInnerMost, combinator);
1612
1613 #ifdef DEBUG
1614       ComplexSelectorSet debugSet;
1615       debugSet = pNewSelector->sources();
1616       if (debugSet.size() > 0) {
1617         throw std::runtime_error("The new selector should start with no sources. Something needs to be cloned to fix this.");
1618       }
1619       debugSet = pExtComplexSelector->sources();
1620       if (debugSet.size() > 0) {
1621         throw std::runtime_error("The extension selector from our subset map should not have sources. These will bleed to the new selector. Something needs to be cloned to fix this.");
1622       }
1623 #endif
1624
1625
1626       // if (pSelector && pSelector->has_line_feed()) pNewInnerMost->has_line_feed(true);
1627       // Set the sources on our new Complex_Selector to the sources of this simple sequence plus the thing we're extending.
1628       DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector, ctx))
1629
1630       DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet oldSet = pNewSelector->sources(); printSourcesSet(oldSet, ctx, "SOURCES NEW SEQ BEGIN: "))
1631
1632       // I actually want to create a copy here (performance!)
1633       ComplexSelectorSet newSourcesSet = pSelector->sources(); // XXX
1634       DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet, ctx, "SOURCES THIS EXTEND: "))
1635
1636       newSourcesSet.insert(pExtComplexSelector);
1637       DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet, ctx, "SOURCES WITH NEW SOURCE: "))
1638
1639       // RUBY: new_seq.add_sources!(sources + [seq])
1640       pNewSelector->addSources(newSourcesSet, ctx);
1641
1642       DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet newSet = pNewSelector->sources(); printSourcesSet(newSet, ctx, "SOURCES ON NEW SELECTOR AFTER ADD: "))
1643       DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(pSelector->sources(), ctx, "SOURCES THIS EXTEND WHICH SHOULD BE SAME STILL: "))
1644
1645
1646       if (pSels->has_line_feed()) pNewSelector->has_line_feed(true);
1647
1648       holder.push_back(std::make_pair(pSels, pNewSelector));
1649     }
1650
1651
1652     for (SubSetMapLookups::iterator holderIter = holder.begin(), holderIterEnd = holder.end(); holderIter != holderIterEnd; holderIter++) {
1653       SubSetMapLookup& pair = *holderIter;
1654
1655       Compound_Selector_Obj pSels = pair.first;
1656       Complex_Selector_Obj pNewSelector = pair.second;
1657
1658
1659       // RUBY??: next [] if seen.include?(sels)
1660       if (seen.find(*pSels) != seen.end()) {
1661         continue;
1662       }
1663
1664
1665       std::set<Compound_Selector> recurseSeen(seen);
1666       recurseSeen.insert(*pSels);
1667
1668
1669       DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND: " << complexSelectorToNode(pNewSelector, ctx))
1670       Node recurseExtendedSelectors = extendComplexSelector(pNewSelector, ctx, subset_map, recurseSeen, isReplace, false); // !:isOriginal
1671
1672       DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND RETURN: " << recurseExtendedSelectors)
1673
1674       for (NodeDeque::iterator iterator = recurseExtendedSelectors.collection()->begin(), endIterator = recurseExtendedSelectors.collection()->end();
1675            iterator != endIterator; ++iterator) {
1676         Node newSelector = *iterator;
1677
1678 //        DEBUG_PRINTLN(EXTEND_COMPOUND, "EXTENDED AT THIS POINT: " << extendedSelectors)
1679 //        DEBUG_PRINTLN(EXTEND_COMPOUND, "SELECTOR EXISTS ALREADY: " << newSelector << " " << extendedSelectors.contains(newSelector, false /*simpleSelectorOrderDependent*/));
1680
1681         if (!extendedSelectors.contains(newSelector, false /*simpleSelectorOrderDependent*/)) {
1682 //          DEBUG_PRINTLN(EXTEND_COMPOUND, "ADDING NEW SELECTOR")
1683           extendedSelectors.collection()->push_back(newSelector);
1684         }
1685       }
1686     }
1687
1688     DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND END: "))
1689
1690     return extendedSelectors;
1691   }
1692
1693
1694   static bool complexSelectorHasExtension(
1695     Complex_Selector_Ptr pComplexSelector,
1696     Context& ctx,
1697     Subset_Map& subset_map,
1698     std::set<Compound_Selector>& seen) {
1699
1700     bool hasExtension = false;
1701
1702     Complex_Selector_Obj pIter = pComplexSelector;
1703
1704     while (!hasExtension && pIter) {
1705       Compound_Selector_Obj pHead = pIter->head();
1706
1707       if (pHead) {
1708         SubSetMapPairs entries = subset_map.get_v(pHead);
1709         for (SubSetMapPair ext : entries) {
1710           // check if both selectors have the same media block parent
1711           // if (ext.first->media_block() == pComplexSelector->media_block()) continue;
1712           if (ext.second->media_block() == 0) continue;
1713           if (pHead->media_block() &&
1714               ext.second->media_block()->media_queries() &&
1715               pHead->media_block()->media_queries()
1716           ) {
1717             std::string query_left(ext.second->media_block()->media_queries()->to_string(ctx.c_options));
1718             std::string query_right(pHead->media_block()->media_queries()->to_string(ctx.c_options));
1719             if (query_left == query_right) continue;
1720           }
1721
1722           // fail if one goes across media block boundaries
1723           std::stringstream err;
1724           std::string cwd(Sass::File::get_cwd());
1725           ParserState pstate(ext.second->pstate());
1726           std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
1727           err << "You may not @extend an outer selector from within @media.\n";
1728           err << "You may only @extend selectors within the same directive.\n";
1729           err << "From \"@extend " << ext.second->to_string(ctx.c_options) << "\"";
1730           err << " on line " << pstate.line+1 << " of " << rel_path << "\n";
1731           error(err.str(), pComplexSelector->pstate());
1732         }
1733         if (entries.size() > 0) hasExtension = true;
1734       }
1735
1736       pIter = pIter->tail();
1737     }
1738
1739     return hasExtension;
1740   }
1741
1742
1743   /*
1744    This is the equivalent of ruby's Sequence.do_extend.
1745
1746    // TODO: I think I have some modified ruby code to put here. Check.
1747    */
1748   /*
1749    ISSUES:
1750    - check to automatically include combinators doesn't transfer over to libsass' data model where
1751      the combinator and compound selector are one unit
1752      next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
1753    */
1754   static Node extendComplexSelector(
1755     Complex_Selector_Ptr pComplexSelector,
1756     Context& ctx,
1757     Subset_Map& subset_map,
1758     std::set<Compound_Selector> seen, bool isReplace, bool isOriginal) {
1759
1760     Node complexSelector = complexSelectorToNode(pComplexSelector, ctx);
1761     DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX: " << complexSelector)
1762
1763     Node extendedNotExpanded = Node::createCollection();
1764
1765     for (NodeDeque::iterator complexSelIter = complexSelector.collection()->begin(),
1766                              complexSelIterEnd = complexSelector.collection()->end();
1767          complexSelIter != complexSelIterEnd; ++complexSelIter)
1768     {
1769
1770       Node& sseqOrOp = *complexSelIter;
1771
1772       DEBUG_PRINTLN(EXTEND_COMPLEX, "LOOP: " << sseqOrOp)
1773
1774       // If it's not a selector (meaning it's a combinator), just include it automatically
1775       // RUBY: next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
1776       if (!sseqOrOp.isSelector()) {
1777         // Wrap our Combinator in two collections to match ruby. This is essentially making a collection Node
1778         // with one collection child. The collection child represents a Complex_Selector that is only a combinator.
1779         Node outer = Node::createCollection();
1780         Node inner = Node::createCollection();
1781         outer.collection()->push_back(inner);
1782         inner.collection()->push_back(sseqOrOp);
1783         extendedNotExpanded.collection()->push_back(outer);
1784         continue;
1785       }
1786
1787       Compound_Selector_Obj pCompoundSelector = sseqOrOp.selector()->head();
1788
1789       // RUBY: extended = sseq_or_op.do_extend(extends, parent_directives, replace, seen)
1790       Node extended = extendCompoundSelector(pCompoundSelector, ctx, subset_map, seen, isReplace);
1791       if (sseqOrOp.got_line_feed) extended.got_line_feed = true;
1792       DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED: " << extended)
1793
1794
1795       // Prepend the Compound_Selector based on the choices logic; choices seems to be extend but with an ruby Array instead of a Sequence
1796       // due to the member mapping: choices = extended.map {|seq| seq.members}
1797       Complex_Selector_Obj pJustCurrentCompoundSelector = sseqOrOp.selector();
1798
1799       // RUBY: extended.first.add_sources!([self]) if original && !has_placeholder?
1800       if (isOriginal && !pComplexSelector->has_placeholder()) {
1801         ComplexSelectorSet srcset;
1802         srcset.insert(pComplexSelector);
1803         pJustCurrentCompoundSelector->addSources(srcset, ctx);
1804         DEBUG_PRINTLN(EXTEND_COMPLEX, "ADD SOURCES: " << *pComplexSelector)
1805       }
1806
1807       bool isSuperselector = false;
1808       for (NodeDeque::iterator iterator = extended.collection()->begin(), endIterator = extended.collection()->end();
1809            iterator != endIterator; ++iterator) {
1810         Node& childNode = *iterator;
1811         Complex_Selector_Obj pExtensionSelector = nodeToComplexSelector(childNode, ctx);
1812         if (pExtensionSelector->is_superselector_of(pJustCurrentCompoundSelector)) {
1813           isSuperselector = true;
1814           break;
1815         }
1816       }
1817
1818       if (!isSuperselector) {
1819         if (sseqOrOp.got_line_feed) pJustCurrentCompoundSelector->has_line_feed(sseqOrOp.got_line_feed);
1820         extended.collection()->push_front(complexSelectorToNode(pJustCurrentCompoundSelector, ctx));
1821       }
1822
1823       DEBUG_PRINTLN(EXTEND_COMPLEX, "CHOICES UNSHIFTED: " << extended)
1824
1825       // Aggregate our current extensions
1826       extendedNotExpanded.collection()->push_back(extended);
1827     }
1828
1829
1830     DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED NOT EXPANDED: " << extendedNotExpanded)
1831
1832
1833
1834     // Ruby Equivalent: paths
1835     Node paths = Sass::paths(extendedNotExpanded, ctx);
1836
1837     DEBUG_PRINTLN(EXTEND_COMPLEX, "PATHS: " << paths)
1838
1839
1840
1841     // Ruby Equivalent: weave
1842     Node weaves = Node::createCollection();
1843
1844     for (NodeDeque::iterator pathsIter = paths.collection()->begin(), pathsEndIter = paths.collection()->end(); pathsIter != pathsEndIter; ++pathsIter) {
1845       Node& path = *pathsIter;
1846       Node weaved = weave(path, ctx);
1847       weaved.got_line_feed = path.got_line_feed;
1848       weaves.collection()->push_back(weaved);
1849     }
1850
1851     DEBUG_PRINTLN(EXTEND_COMPLEX, "WEAVES: " << weaves)
1852
1853
1854
1855     // Ruby Equivalent: trim
1856     Node trimmed = trim(weaves, ctx, isReplace);
1857
1858     DEBUG_PRINTLN(EXTEND_COMPLEX, "TRIMMED: " << trimmed)
1859
1860
1861     // Ruby Equivalent: flatten
1862     Node extendedSelectors = flatten(trimmed, ctx, 1);
1863
1864     DEBUG_PRINTLN(EXTEND_COMPLEX, ">>>>> EXTENDED: " << extendedSelectors)
1865
1866
1867     DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX END: " << complexSelector)
1868
1869
1870     return extendedSelectors;
1871   }
1872
1873
1874
1875   /*
1876    This is the equivalent of ruby's CommaSequence.do_extend.
1877   */
1878   Selector_List_Ptr Extend::extendSelectorList(Selector_List_Obj pSelectorList, Context& ctx, Subset_Map& subset_map, bool isReplace, bool& extendedSomething) {
1879     std::set<Compound_Selector> seen;
1880     return extendSelectorList(pSelectorList, ctx, subset_map, isReplace, extendedSomething, seen);
1881   }
1882
1883   /*
1884    This is the equivalent of ruby's CommaSequence.do_extend.
1885   */
1886   Selector_List_Ptr Extend::extendSelectorList(Selector_List_Obj pSelectorList, Context& ctx, Subset_Map& subset_map, bool isReplace, bool& extendedSomething, std::set<Compound_Selector>& seen) {
1887
1888     Selector_List_Obj pNewSelectors = SASS_MEMORY_NEW(Selector_List, pSelectorList->pstate(), pSelectorList->length());
1889
1890     extendedSomething = false;
1891
1892     for (size_t index = 0, length = pSelectorList->length(); index < length; index++) {
1893       Complex_Selector_Obj pSelector = (*pSelectorList)[index];
1894
1895       // ruby sass seems to keep a list of things that have extensions and then only extend those. We don't currently do that.
1896       // Since it's not that expensive to check if an extension exists in the subset map and since it can be relatively expensive to
1897       // run through the extend code (which does a data model transformation), check if there is anything to extend before doing
1898       // the extend. We might be able to optimize extendComplexSelector, but this approach keeps us closer to ruby sass (which helps
1899       // when debugging).
1900       if (!complexSelectorHasExtension(pSelector, ctx, subset_map, seen)) {
1901         pNewSelectors->append(pSelector);
1902         continue;
1903       }
1904
1905       extendedSomething = true;
1906
1907       Node extendedSelectors = extendComplexSelector(pSelector, ctx, subset_map, seen, isReplace, true);
1908       if (!pSelector->has_placeholder()) {
1909         if (!extendedSelectors.contains(complexSelectorToNode(pSelector, ctx), true /*simpleSelectorOrderDependent*/)) {
1910           pNewSelectors->append(pSelector);
1911           continue;
1912         }
1913       }
1914
1915       for (NodeDeque::iterator iterator = extendedSelectors.collection()->begin(), iteratorBegin = extendedSelectors.collection()->begin(), iteratorEnd = extendedSelectors.collection()->end(); iterator != iteratorEnd; ++iterator) {
1916         // When it is a replace, skip the first one, unless there is only one
1917         if(isReplace && iterator == iteratorBegin && extendedSelectors.collection()->size() > 1 ) continue;
1918
1919         Node& childNode = *iterator;
1920         pNewSelectors->append(nodeToComplexSelector(childNode, ctx));
1921       }
1922     }
1923
1924     Remove_Placeholders remove_placeholders;
1925     // it seems that we have to remove the place holders early here
1926     // normally we do this as the very last step (compare to ruby sass)
1927     pNewSelectors = remove_placeholders.remove_placeholders(pNewSelectors);
1928
1929     // unwrap all wrapped selectors with inner lists
1930     for (Complex_Selector_Obj cur : pNewSelectors->elements()) {
1931       // process tails
1932       while (cur) {
1933         // process header
1934         if (cur->head() && seen.find(*cur->head()) == seen.end()) {
1935           std::set<Compound_Selector> recseen(seen);
1936           recseen.insert(*cur->head());
1937           // create a copy since we add multiple items if stuff get unwrapped
1938           Compound_Selector_Obj cpy_head = SASS_MEMORY_NEW(Compound_Selector, cur->pstate());
1939           for (Simple_Selector_Obj hs : *cur->head()) {
1940             if (Wrapped_Selector_Obj ws = Cast<Wrapped_Selector>(hs)) {
1941               ws->selector(SASS_MEMORY_CLONE(ws->selector()));
1942               if (Selector_List_Obj sl = Cast<Selector_List>(ws->selector())) {
1943                 // special case for ruby ass
1944                 if (sl->empty()) {
1945                   // this seems inconsistent but it is how ruby sass seems to remove parentheses
1946                   cpy_head->append(SASS_MEMORY_NEW(Element_Selector, hs->pstate(), ws->name()));
1947                 }
1948                 // has wrapped selectors
1949                 else {
1950                   // extend the inner list of wrapped selector
1951                   Selector_List_Obj ext_sl = extendSelectorList(sl, ctx, subset_map, recseen);
1952                   for (size_t i = 0; i < ext_sl->length(); i += 1) {
1953                     if (Complex_Selector_Obj ext_cs = ext_sl->at(i)) {
1954                       // create clones for wrapped selector and the inner list
1955                       Wrapped_Selector_Obj cpy_ws = SASS_MEMORY_COPY(ws);
1956                       Selector_List_Obj cpy_ws_sl = SASS_MEMORY_NEW(Selector_List, sl->pstate());
1957                       // remove parent selectors from inner selector
1958                       if (ext_cs->first() && ext_cs->first()->head()->length() > 0) {
1959                         Wrapped_Selector_Ptr ext_ws = Cast<Wrapped_Selector>(ext_cs->first()->head()->first());
1960                         if (ext_ws/* && ext_cs->length() == 1*/) {
1961                           Selector_List_Obj ws_cs = Cast<Selector_List>(ext_ws->selector());
1962                           Compound_Selector_Obj ws_ss = ws_cs->first()->head();
1963                           if (!(
1964                             Cast<Pseudo_Selector>(ws_ss->first()) ||
1965                             Cast<Element_Selector>(ws_ss->first()) ||
1966                             Cast<Placeholder_Selector>(ws_ss->first())
1967                           )) continue;
1968                         }
1969                         cpy_ws_sl->append(ext_cs->first());
1970                       }
1971                       // assign list to clone
1972                       cpy_ws->selector(cpy_ws_sl);
1973                       // append the clone
1974                       cpy_head->append(cpy_ws);
1975                     }
1976                   }
1977                 }
1978               } else {
1979                 cpy_head->append(hs);
1980               }
1981             } else {
1982               cpy_head->append(hs);
1983             }
1984           }
1985           // replace header
1986           cur->head(cpy_head);
1987         }
1988         // process tail
1989         cur = cur->tail();
1990       }
1991     }
1992     return pNewSelectors.detach();
1993
1994   }
1995
1996
1997   bool shouldExtendBlock(Block_Obj b) {
1998
1999     // If a block is empty, there's no reason to extend it since any rules placed on this block
2000     // won't have any output. The main benefit of this is for structures like:
2001     //
2002     //    .a {
2003     //      .b {
2004     //        x: y;
2005     //      }
2006     //    }
2007     //
2008     // We end up visiting two rulesets (one with the selector .a and the other with the selector .a .b).
2009     // In this case, we don't want to try to pull rules onto .a since they won't get output anyway since
2010     // there are no child statements. However .a .b should have extensions applied.
2011
2012     for (size_t i = 0, L = b->length(); i < L; ++i) {
2013       Statement_Obj stm = b->at(i);
2014
2015       if (Cast<Ruleset>(stm)) {
2016         // Do nothing. This doesn't count as a statement that causes extension since we'll
2017         // iterate over this rule set in a future visit and try to extend it.
2018       }
2019       else {
2020         return true;
2021       }
2022     }
2023
2024     return false;
2025
2026   }
2027
2028
2029   // Extend a ruleset by extending the selectors and updating them on the ruleset. The block's rules don't need to change.
2030   template <typename ObjectType>
2031   static void extendObjectWithSelectorAndBlock(ObjectType* pObject, Context& ctx, Subset_Map& subset_map) {
2032
2033     DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << Cast<Selector_List>(pObject->selector())->to_string(ctx.c_options))
2034
2035     // Ruby sass seems to filter nodes that don't have any content well before we get here. I'm not sure the repercussions
2036     // of doing so, so for now, let's just not extend things that won't be output later.
2037     if (!shouldExtendBlock(pObject->block())) {
2038       DEBUG_PRINTLN(EXTEND_OBJECT, "RETURNING WITHOUT EXTEND ATTEMPT")
2039       return;
2040     }
2041
2042     bool extendedSomething = false;
2043     Selector_List_Obj pNewSelectorList = Extend::extendSelectorList(Cast<Selector_List>(pObject->selector()), ctx, subset_map, false, extendedSomething);
2044
2045     if (extendedSomething && pNewSelectorList) {
2046       DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << Cast<Selector_List>(pObject->selector())->to_string(ctx.c_options))
2047       DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->to_string(ctx.c_options))
2048       pNewSelectorList->remove_parent_selectors();
2049       pObject->selector(pNewSelectorList);
2050     } else {
2051       DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND DID NOT TRY TO EXTEND ANYTHING")
2052     }
2053   }
2054
2055
2056
2057   Extend::Extend(Context& ctx, Subset_Map& ssm)
2058   : ctx(ctx), subset_map(ssm)
2059   { }
2060
2061   void Extend::operator()(Block_Ptr b)
2062   {
2063     for (size_t i = 0, L = b->length(); i < L; ++i) {
2064       Statement_Obj stm = b->at(i);
2065       stm->perform(this);
2066     }
2067     // do final check if everything was extended
2068     // we set `extended` flag on extended selectors
2069     if (b->is_root()) {
2070       // debug_subset_map(subset_map);
2071       for(auto const &it : subset_map.values()) {
2072         Complex_Selector_Ptr sel = NULL;
2073         Compound_Selector_Ptr ext = NULL;
2074         if (it.first) sel = it.first->first();
2075         if (it.second) ext = it.second;
2076         if (ext && (ext->extended() || ext->is_optional())) continue;
2077         std::string str_sel(sel->to_string({ NESTED, 5 }));
2078         std::string str_ext(ext->to_string({ NESTED, 5 }));
2079         // debug_ast(sel, "sel: ");
2080         // debug_ast(ext, "ext: ");
2081         error("\"" + str_sel + "\" failed to @extend \"" + str_ext + "\".\n"
2082               "The selector \"" + str_ext + "\" was not found.\n"
2083               "Use \"@extend " + str_ext + " !optional\" if the"
2084                 " extend should be able to fail.", ext->pstate());
2085       }
2086     }
2087
2088   }
2089
2090   void Extend::operator()(Ruleset_Ptr pRuleset)
2091   {
2092     extendObjectWithSelectorAndBlock( pRuleset, ctx, subset_map);
2093     pRuleset->block()->perform(this);
2094   }
2095
2096   void Extend::operator()(Supports_Block_Ptr pFeatureBlock)
2097   {
2098     pFeatureBlock->block()->perform(this);
2099   }
2100
2101   void Extend::operator()(Media_Block_Ptr pMediaBlock)
2102   {
2103     pMediaBlock->block()->perform(this);
2104   }
2105
2106   void Extend::operator()(Directive_Ptr a)
2107   {
2108     // Selector_List_Ptr ls = Cast<Selector_List>(a->selector());
2109     // selector_stack.push_back(ls);
2110     if (a->block()) a->block()->perform(this);
2111     // exp.selector_stack.pop_back();
2112   }
2113 }