sassc 1.11.4 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +2 -2
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/README.md +4 -1
  5. data/ext/libsass/.editorconfig +1 -1
  6. data/ext/libsass/.github/CONTRIBUTING.md +7 -7
  7. data/ext/libsass/.github/ISSUE_TEMPLATE.md +31 -6
  8. data/ext/libsass/.gitignore +3 -0
  9. data/ext/libsass/.travis.yml +37 -18
  10. data/ext/libsass/GNUmakefile.am +23 -37
  11. data/ext/libsass/Makefile +10 -6
  12. data/ext/libsass/Makefile.conf +3 -0
  13. data/ext/libsass/Readme.md +68 -63
  14. data/ext/libsass/appveyor.yml +7 -3
  15. data/ext/libsass/configure.ac +10 -14
  16. data/ext/libsass/docs/api-context-internal.md +29 -21
  17. data/ext/libsass/docs/api-context.md +26 -6
  18. data/ext/libsass/docs/api-doc.md +49 -16
  19. data/ext/libsass/docs/api-function-example.md +1 -1
  20. data/ext/libsass/docs/api-function.md +31 -7
  21. data/ext/libsass/docs/api-importer.md +19 -19
  22. data/ext/libsass/docs/api-value.md +4 -2
  23. data/ext/libsass/docs/build-on-windows.md +4 -4
  24. data/ext/libsass/docs/build-with-mingw.md +3 -3
  25. data/ext/libsass/docs/build.md +9 -9
  26. data/ext/libsass/docs/custom-functions-internal.md +10 -8
  27. data/ext/libsass/docs/implementations.md +20 -8
  28. data/ext/libsass/docs/unicode.md +16 -10
  29. data/ext/libsass/include/sass/base.h +0 -3
  30. data/ext/libsass/include/sass/context.h +20 -2
  31. data/ext/libsass/include/sass/functions.h +31 -0
  32. data/ext/libsass/include/sass/values.h +3 -1
  33. data/ext/libsass/include/sass/version.h +1 -1
  34. data/ext/libsass/include/sass/version.h.in +1 -1
  35. data/ext/libsass/include/sass2scss.h +1 -1
  36. data/ext/libsass/res/resource.rc +6 -6
  37. data/ext/libsass/script/ci-build-libsass +10 -5
  38. data/ext/libsass/script/ci-build-plugin +62 -0
  39. data/ext/libsass/script/ci-install-compiler +1 -1
  40. data/ext/libsass/script/ci-install-deps +4 -7
  41. data/ext/libsass/script/ci-report-coverage +13 -3
  42. data/ext/libsass/script/tap-driver +1 -1
  43. data/ext/libsass/script/tap-runner +1 -1
  44. data/ext/libsass/src/GNUmakefile.am +1 -1
  45. data/ext/libsass/src/ast.cpp +537 -762
  46. data/ext/libsass/src/ast.hpp +377 -419
  47. data/ext/libsass/src/ast_def_macros.hpp +26 -1
  48. data/ext/libsass/src/ast_fwd_decl.cpp +29 -0
  49. data/ext/libsass/src/ast_fwd_decl.hpp +94 -21
  50. data/ext/libsass/src/b64/encode.h +3 -1
  51. data/ext/libsass/src/backtrace.cpp +46 -0
  52. data/ext/libsass/src/backtrace.hpp +7 -54
  53. data/ext/libsass/src/bind.cpp +72 -50
  54. data/ext/libsass/src/bind.hpp +0 -1
  55. data/ext/libsass/src/cencode.c +6 -0
  56. data/ext/libsass/src/check_nesting.cpp +157 -135
  57. data/ext/libsass/src/check_nesting.hpp +11 -10
  58. data/ext/libsass/src/color_maps.cpp +10 -6
  59. data/ext/libsass/src/color_maps.hpp +6 -8
  60. data/ext/libsass/src/constants.cpp +4 -3
  61. data/ext/libsass/src/constants.hpp +4 -3
  62. data/ext/libsass/src/context.cpp +110 -47
  63. data/ext/libsass/src/context.hpp +11 -1
  64. data/ext/libsass/src/cssize.cpp +105 -94
  65. data/ext/libsass/src/cssize.hpp +4 -5
  66. data/ext/libsass/src/debugger.hpp +247 -244
  67. data/ext/libsass/src/emitter.cpp +30 -6
  68. data/ext/libsass/src/emitter.hpp +7 -0
  69. data/ext/libsass/src/environment.cpp +67 -16
  70. data/ext/libsass/src/environment.hpp +28 -7
  71. data/ext/libsass/src/error_handling.cpp +92 -64
  72. data/ext/libsass/src/error_handling.hpp +64 -43
  73. data/ext/libsass/src/eval.cpp +494 -544
  74. data/ext/libsass/src/eval.hpp +17 -23
  75. data/ext/libsass/src/expand.cpp +182 -154
  76. data/ext/libsass/src/expand.hpp +4 -5
  77. data/ext/libsass/src/extend.cpp +299 -291
  78. data/ext/libsass/src/extend.hpp +46 -11
  79. data/ext/libsass/src/file.cpp +103 -36
  80. data/ext/libsass/src/file.hpp +21 -4
  81. data/ext/libsass/src/functions.cpp +561 -312
  82. data/ext/libsass/src/functions.hpp +8 -5
  83. data/ext/libsass/src/inspect.cpp +108 -53
  84. data/ext/libsass/src/inspect.hpp +5 -2
  85. data/ext/libsass/src/lexer.cpp +15 -7
  86. data/ext/libsass/src/lexer.hpp +13 -4
  87. data/ext/libsass/src/listize.cpp +3 -2
  88. data/ext/libsass/src/listize.hpp +0 -1
  89. data/ext/libsass/src/memory/SharedPtr.cpp +16 -18
  90. data/ext/libsass/src/memory/SharedPtr.hpp +47 -43
  91. data/ext/libsass/src/node.cpp +34 -38
  92. data/ext/libsass/src/node.hpp +6 -8
  93. data/ext/libsass/src/operation.hpp +2 -2
  94. data/ext/libsass/src/operators.cpp +240 -0
  95. data/ext/libsass/src/operators.hpp +30 -0
  96. data/ext/libsass/src/output.cpp +22 -20
  97. data/ext/libsass/src/parser.cpp +719 -358
  98. data/ext/libsass/src/parser.hpp +57 -22
  99. data/ext/libsass/src/plugins.cpp +28 -10
  100. data/ext/libsass/src/position.cpp +21 -3
  101. data/ext/libsass/src/position.hpp +2 -1
  102. data/ext/libsass/src/prelexer.cpp +104 -19
  103. data/ext/libsass/src/prelexer.hpp +10 -3
  104. data/ext/libsass/src/remove_placeholders.cpp +9 -10
  105. data/ext/libsass/src/remove_placeholders.hpp +1 -5
  106. data/ext/libsass/src/sass.cpp +62 -4
  107. data/ext/libsass/src/sass.hpp +5 -2
  108. data/ext/libsass/src/sass_context.cpp +96 -58
  109. data/ext/libsass/src/sass_context.hpp +7 -5
  110. data/ext/libsass/src/sass_functions.cpp +63 -1
  111. data/ext/libsass/src/sass_functions.hpp +19 -1
  112. data/ext/libsass/src/sass_util.cpp +3 -3
  113. data/ext/libsass/src/sass_util.hpp +4 -4
  114. data/ext/libsass/src/sass_values.cpp +42 -39
  115. data/ext/libsass/src/sass_values.hpp +2 -1
  116. data/ext/libsass/src/source_map.cpp +16 -18
  117. data/ext/libsass/src/subset_map.cpp +6 -8
  118. data/ext/libsass/src/subset_map.hpp +6 -6
  119. data/ext/libsass/src/to_c.cpp +2 -2
  120. data/ext/libsass/src/to_value.cpp +8 -3
  121. data/ext/libsass/src/to_value.hpp +1 -0
  122. data/ext/libsass/src/units.cpp +349 -45
  123. data/ext/libsass/src/units.hpp +39 -22
  124. data/ext/libsass/src/utf8/checked.h +7 -0
  125. data/ext/libsass/src/utf8/unchecked.h +7 -0
  126. data/ext/libsass/src/utf8_string.cpp +1 -1
  127. data/ext/libsass/src/util.cpp +139 -45
  128. data/ext/libsass/src/util.hpp +4 -7
  129. data/ext/libsass/src/values.cpp +15 -23
  130. data/ext/libsass/win/libsass.sln +13 -2
  131. data/ext/libsass/win/libsass.sln.DotSettings +9 -0
  132. data/ext/libsass/win/libsass.targets +3 -0
  133. data/ext/libsass/win/libsass.vcxproj.filters +9 -0
  134. data/lib/sassc/version.rb +1 -1
  135. data/sassc.gemspec +1 -1
  136. data/test/native_test.rb +1 -1
  137. metadata +11 -4
@@ -18,9 +18,14 @@ if [ "x$TRAVIS_OS_NAME" == "x" ]; then export TRAVIS_OS_NAME=`uname -s | perl -n
18
18
 
19
19
  if [ "x$COVERAGE" == "xyes" ]; then
20
20
  COVERAGE_OPT="--enable-coverage"
21
- export EXTRA_CFLAGS="--coverage"
22
- export EXTRA_CXXFLAGS="--coverage"
23
- export EXTRA_LDFLAGS="--coverage"
21
+ export EXTRA_CFLAGS="-fprofile-arcs -ftest-coverage"
22
+ export EXTRA_CXXFLAGS="-fprofile-arcs -ftest-coverage"
23
+ if [ "$TRAVIS_OS_NAME" == "osx" ]; then
24
+ # osx doesn't seem to know gcov lib?
25
+ export EXTRA_LDFLAGS="--coverage"
26
+ else
27
+ export EXTRA_LDFLAGS="-lgcov --coverage"
28
+ fi
24
29
  else
25
30
  COVERAGE_OPT="--disable-coverage"
26
31
  fi
@@ -37,7 +42,7 @@ fi
37
42
  if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then
38
43
  MAKE_OPTS="$MAKE_OPTS -j1 V=1"
39
44
  else
40
- MAKE_OPTS="$MAKE_OPTS -j3 V=1"
45
+ MAKE_OPTS="$MAKE_OPTS -j5 V=1"
41
46
  fi
42
47
 
43
48
  if [ "x$PREFIX" == "x" ]; then
@@ -109,7 +114,7 @@ then
109
114
  then
110
115
  echo "Travis rate limit on github exceeded"
111
116
  echo "Retrying via 'special purpose proxy'"
112
- JSON=$(curl -L -sS http://libsass.ocbnet.ch/libsass-spec-pr.psgi/$TRAVIS_PULL_REQUEST)
117
+ JSON=$(curl -L -sS https://github-api-reverse-proxy.herokuapp.com/repos/sass/libsass/pulls/$TRAVIS_PULL_REQUEST)
113
118
  fi
114
119
 
115
120
  RE_SPEC_PR="sass\/sass-spec(#|\/pull\/)([0-9]+)"
@@ -0,0 +1,62 @@
1
+ #!/bin/bash
2
+
3
+ PLUGIN=$1
4
+ RUBY_BIN=ruby
5
+ SASS_SPEC_PATH=sass-spec
6
+ SASSC_BIN=sassc/bin/sassc
7
+ SASS_SPEC_SPEC_DIR=plugins/libsass-${PLUGIN}/test
8
+
9
+ if [ -e ./tester ] ; then
10
+ SASSC_BIN=./tester
11
+ fi
12
+
13
+ if [ -d ./build/lib ] ; then
14
+ cp -a build/lib lib
15
+ fi
16
+
17
+ if [ "x$1" == "x" ] ; then
18
+ echo "No plugin name given"
19
+ exit 1
20
+ fi
21
+
22
+ if [ "x$COVERAGE" == "0" ] ; then
23
+ unset COVERAGE
24
+ fi
25
+
26
+ export EXTRA_CFLAGS=""
27
+ export EXTRA_CXXFLAGS=""
28
+ if [ "$TRAVIS_OS_NAME" == "osx" ]; then
29
+ # osx doesn't seem to know gcov lib?
30
+ export EXTRA_LDFLAGS="--coverage"
31
+ else
32
+ export EXTRA_LDFLAGS="-lgcov --coverage"
33
+ fi
34
+
35
+ mkdir -p plugins
36
+ if [ ! -d plugins/libsass-${PLUGIN} ] ; then
37
+ git clone https://github.com/mgreter/libsass-${PLUGIN} plugins/libsass-${PLUGIN}
38
+ fi
39
+ if [ ! -d plugins/libsass-${PLUGIN}/build ] ; then
40
+ mkdir plugins/libsass-${PLUGIN}/build
41
+ fi
42
+ RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
43
+
44
+ cd plugins/libsass-${PLUGIN}/build
45
+ cmake -G "Unix Makefiles" -D LIBSASS_DIR="../../.." ..
46
+ RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
47
+ make VERBOSE=1 -j2
48
+ RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
49
+ cd ../../..
50
+
51
+ # glob only works on paths relative to imports
52
+ if [ "x$PLUGIN" == "xglob" ]; then
53
+ ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build ${SASS_SPEC_SPEC_DIR}/basic/input.scss > ${SASS_SPEC_SPEC_DIR}/basic/result.css
54
+ ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build ${SASS_SPEC_SPEC_DIR}/basic/input.scss --sourcemap > /dev/null
55
+ else
56
+ cat ${SASS_SPEC_SPEC_DIR}/basic/input.scss | ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build -I ${SASS_SPEC_SPEC_DIR}/basic > ${SASS_SPEC_SPEC_DIR}/basic/result.css
57
+ cat ${SASS_SPEC_SPEC_DIR}/basic/input.scss | ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build -I ${SASS_SPEC_SPEC_DIR}/basic --sourcemap > /dev/null
58
+ fi
59
+ RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
60
+
61
+ diff ${SASS_SPEC_SPEC_DIR}/basic/expected_output.css ${SASS_SPEC_SPEC_DIR}/basic/result.css
62
+ RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
@@ -3,4 +3,4 @@
3
3
  gem install minitest
4
4
  gem install minitap
5
5
 
6
- pip install --user 'requests[security]'
6
+ pip2 install --user 'requests[security]'
@@ -1,7 +1,7 @@
1
1
  #!/bin/bash
2
2
  if [ "x$COVERAGE" == "xyes" ]; then
3
- pip install --user gcovr
4
- pip install --user cpp-coveralls
3
+ pip2 install --user gcovr
4
+ pip2 install --user cpp-coveralls
5
5
  else
6
6
  echo "no dependencies to install"
7
7
  fi
@@ -15,9 +15,6 @@ if [ "x$AUTOTOOLS" == "xyes" ]; then
15
15
  sudo apt-get -qq install automake
16
16
  fi
17
17
 
18
- # https://github.com/sass/libsass/pull/2183
19
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
20
- brew uninstall libtool
21
- brew install libtool
22
- fi
23
18
  fi
19
+
20
+ exit 0
@@ -2,6 +2,12 @@
2
2
 
3
3
  if [ "x$COVERAGE" = "xyes" ]; then
4
4
 
5
+ # find / -name "gcovr"
6
+ # find / -name "coveralls"
7
+ # this is only needed for mac os x builds!
8
+ PATH=$PATH:/Users/travis/Library/Python/2.7/bin/
9
+
10
+
5
11
  # exclude some directories from profiling (.libs is from autotools)
6
12
  export EXCLUDE_COVERAGE="--exclude plugins
7
13
  --exclude sassc/sassc.c
@@ -21,10 +27,14 @@ if [ "x$COVERAGE" = "xyes" ]; then
21
27
  --exclude src/test
22
28
  --exclude src/posix
23
29
  --exclude src/debugger.hpp"
24
- # debug via gcovr
25
- gcov -v
30
+ # debug used gcov version
31
+ # option not available on mac
32
+ if [ "$TRAVIS_OS_NAME" != "osx" ]; then
33
+ gcov -v
34
+ fi
35
+ # create summarized report
26
36
  gcovr -r .
27
- # generate and submit report to coveralls.io
37
+ # submit report to coveralls.io
28
38
  coveralls $EXCLUDE_COVERAGE --gcov-options '\-lp'
29
39
 
30
40
  else
@@ -1,4 +1,4 @@
1
- #! /bin/sh
1
+ #!/usr/bin/env sh
2
2
  # Copyright (C) 2011-2013 Free Software Foundation, Inc.
3
3
  #
4
4
  # This program is free software; you can redistribute it and/or modify
@@ -1 +1 @@
1
- $@ | tapout tap
1
+ $@ $TEST_FLAGS --tap --silent | tapout tap
@@ -34,7 +34,7 @@ include $(top_srcdir)/Makefile.conf
34
34
 
35
35
  libsass_la_SOURCES = ${CSOURCES} ${SOURCES}
36
36
 
37
- libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 0:9:0
37
+ libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 1:0:0
38
38
 
39
39
  if ENABLE_TESTS
40
40
  if ENABLE_COVERAGE
@@ -2,6 +2,7 @@
2
2
  #include "ast.hpp"
3
3
  #include "context.hpp"
4
4
  #include "node.hpp"
5
+ #include "eval.hpp"
5
6
  #include "extend.hpp"
6
7
  #include "emitter.hpp"
7
8
  #include "color_maps.hpp"
@@ -18,80 +19,73 @@ namespace Sass {
18
19
 
19
20
  static Null sass_null(ParserState("null"));
20
21
 
21
- bool Supports_Operator::needs_parens(Supports_Condition_Obj cond) const {
22
- if (Supports_Operator_Obj op = SASS_MEMORY_CAST(Supports_Operator, cond)) {
23
- return op->operand() != operand();
22
+ bool Wrapped_Selector::find ( bool (*f)(AST_Node_Obj) )
23
+ {
24
+ // check children first
25
+ if (selector_) {
26
+ if (selector_->find(f)) return true;
24
27
  }
25
- return SASS_MEMORY_CAST(Supports_Negation, cond) != NULL;
26
- }
27
-
28
- bool Supports_Negation::needs_parens(Supports_Condition_Obj cond) const {
29
- return SASS_MEMORY_CAST(Supports_Negation, cond) ||
30
- SASS_MEMORY_CAST(Supports_Operator, cond);
28
+ // execute last
29
+ return f(this);
31
30
  }
32
31
 
33
- size_t HashExpression::operator() (Expression_Obj ex) const {
34
- return ex ? ex->hash() : 0;
32
+ bool Selector_List::find ( bool (*f)(AST_Node_Obj) )
33
+ {
34
+ // check children first
35
+ for (Complex_Selector_Obj sel : elements()) {
36
+ if (sel->find(f)) return true;
37
+ }
38
+ // execute last
39
+ return f(this);
35
40
  }
36
41
 
37
- size_t HashSimpleSelector::operator() (Simple_Selector_Obj ex) const {
38
- return ex ? ex->hash() : 0;
42
+ bool Compound_Selector::find ( bool (*f)(AST_Node_Obj) )
43
+ {
44
+ // check children first
45
+ for (Simple_Selector_Obj sel : elements()) {
46
+ if (sel->find(f)) return true;
47
+ }
48
+ // execute last
49
+ return f(this);
39
50
  }
40
51
 
41
-
42
- bool CompareExpression::operator()(const Expression_Obj& lhs, const Expression_Obj& rhs) const {
43
- return lhs && rhs && lhs->eq(*rhs);
52
+ bool Complex_Selector::find ( bool (*f)(AST_Node_Obj) )
53
+ {
54
+ // check children first
55
+ if (head_ && head_->find(f)) return true;
56
+ if (tail_ && tail_->find(f)) return true;
57
+ // execute last
58
+ return f(this);
44
59
  }
45
60
 
46
- bool CompareSimpleSelector::operator()(Simple_Selector_Obj lhs, Simple_Selector_Obj rhs) const {
47
- return &lhs && &rhs && *lhs == *rhs;
61
+ bool Supports_Operator::needs_parens(Supports_Condition_Obj cond) const {
62
+ if (Supports_Operator_Obj op = Cast<Supports_Operator>(cond)) {
63
+ return op->operand() != operand();
64
+ }
65
+ return Cast<Supports_Negation>(cond) != NULL;
48
66
  }
49
67
 
50
- std::string & str_ltrim(std::string & str)
51
- {
52
- auto it2 = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
53
- str.erase( str.begin() , it2);
54
- return str;
68
+ bool Supports_Negation::needs_parens(Supports_Condition_Obj cond) const {
69
+ return Cast<Supports_Negation>(cond) ||
70
+ Cast<Supports_Operator>(cond);
55
71
  }
56
72
 
57
- std::string & str_rtrim(std::string & str)
73
+ void str_rtrim(std::string& str, const std::string& delimiters = " \f\n\r\t\v")
58
74
  {
59
- auto it1 = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
60
- str.erase( it1.base() , str.end() );
61
- return str;
75
+ str.erase( str.find_last_not_of( delimiters ) + 1 );
62
76
  }
63
77
 
64
78
  void String_Constant::rtrim()
65
79
  {
66
- value_ = str_rtrim(value_);
67
- }
68
- void String_Constant::ltrim()
69
- {
70
- value_ = str_ltrim(value_);
71
- }
72
- void String_Constant::trim()
73
- {
74
- rtrim();
75
- ltrim();
80
+ str_rtrim(value_);
76
81
  }
77
82
 
78
83
  void String_Schema::rtrim()
79
84
  {
80
85
  if (!empty()) {
81
- if (String_Ptr str = SASS_MEMORY_CAST(String, last())) str->rtrim();
86
+ if (String_Ptr str = Cast<String>(last())) str->rtrim();
82
87
  }
83
88
  }
84
- void String_Schema::ltrim()
85
- {
86
- if (!empty()) {
87
- if (String_Ptr str = SASS_MEMORY_CAST(String, first())) str->ltrim();
88
- }
89
- }
90
- void String_Schema::trim()
91
- {
92
- rtrim();
93
- ltrim();
94
- }
95
89
 
96
90
  void Argument::set_delayed(bool delayed)
97
91
  {
@@ -111,7 +105,7 @@ namespace Sass {
111
105
  bool At_Root_Query::exclude(std::string str)
112
106
  {
113
107
  bool with = feature() && unquote(feature()->to_string()).compare("with") == 0;
114
- List_Ptr l = static_cast<List_Ptr>(&value());
108
+ List_Ptr l = static_cast<List_Ptr>(value().ptr());
115
109
  std::string v;
116
110
 
117
111
  if (with)
@@ -141,21 +135,20 @@ namespace Sass {
141
135
  pstate_.offset += pstate - pstate_ + pstate.offset;
142
136
  }
143
137
 
144
- void AST_Node::set_pstate_offset(const Offset& offset)
145
- {
146
- pstate_.offset = offset;
147
- }
148
-
149
- inline bool is_ns_eq(const std::string& l, const std::string& r)
138
+ bool Simple_Selector::is_ns_eq(const Simple_Selector& r) const
150
139
  {
151
- if (l.empty() && r.empty()) return true;
152
- else if (l.empty() && r == "*") return true;
153
- else if (r.empty() && l == "*") return true;
154
- else return l == r;
140
+ // https://github.com/sass/sass/issues/2229
141
+ if ((has_ns_ == r.has_ns_) ||
142
+ (has_ns_ && ns_.empty()) ||
143
+ (r.has_ns_ && r.ns_.empty())
144
+ ) {
145
+ if (ns_.empty() && r.ns() == "*") return false;
146
+ else if (r.ns().empty() && ns() == "*") return false;
147
+ else return ns() == r.ns();
148
+ }
149
+ return false;
155
150
  }
156
151
 
157
-
158
-
159
152
  bool Compound_Selector::operator< (const Compound_Selector& rhs) const
160
153
  {
161
154
  size_t L = std::min(length(), rhs.length());
@@ -173,7 +166,7 @@ namespace Sass {
173
166
  return length() < rhs.length();
174
167
  }
175
168
 
176
- bool Compound_Selector::has_parent_ref()
169
+ bool Compound_Selector::has_parent_ref() const
177
170
  {
178
171
  for (Simple_Selector_Obj s : *this) {
179
172
  if (s && s->has_parent_ref()) return true;
@@ -181,7 +174,7 @@ namespace Sass {
181
174
  return false;
182
175
  }
183
176
 
184
- bool Compound_Selector::has_real_parent_ref()
177
+ bool Compound_Selector::has_real_parent_ref() const
185
178
  {
186
179
  for (Simple_Selector_Obj s : *this) {
187
180
  if (s && s->has_real_parent_ref()) return true;
@@ -189,13 +182,13 @@ namespace Sass {
189
182
  return false;
190
183
  }
191
184
 
192
- bool Complex_Selector::has_parent_ref()
185
+ bool Complex_Selector::has_parent_ref() const
193
186
  {
194
187
  return (head() && head()->has_parent_ref()) ||
195
188
  (tail() && tail()->has_parent_ref());
196
189
  }
197
190
 
198
- bool Complex_Selector::has_real_parent_ref()
191
+ bool Complex_Selector::has_real_parent_ref() const
199
192
  {
200
193
  return (head() && head()->has_real_parent_ref()) ||
201
194
  (tail() && tail()->has_real_parent_ref());
@@ -206,25 +199,31 @@ namespace Sass {
206
199
  // const iterators for tails
207
200
  Complex_Selector_Ptr_Const l = this;
208
201
  Complex_Selector_Ptr_Const r = &rhs;
209
- Compound_Selector_Ptr l_h = l ? &l->head() : 0;
210
- Compound_Selector_Ptr r_h = r ? &r->head() : 0;
202
+ Compound_Selector_Ptr l_h = NULL;
203
+ Compound_Selector_Ptr r_h = NULL;
204
+ if (l) l_h = l->head();
205
+ if (r) r_h = r->head();
211
206
  // process all tails
212
207
  while (true)
213
208
  {
209
+ #ifdef DEBUG
214
210
  // skip empty ancestor first
215
211
  if (l && l->is_empty_ancestor())
216
212
  {
217
- l = &l->tail();
218
- l_h = l ? &l->head() : 0;
213
+ l_h = NULL;
214
+ l = l->tail();
215
+ if(l) l_h = l->head();
219
216
  continue;
220
217
  }
221
218
  // skip empty ancestor first
222
219
  if (r && r->is_empty_ancestor())
223
220
  {
224
- r = &r->tail();
225
- r_h = r ? &r->head() : 0;
221
+ r_h = NULL;
222
+ r = r->tail();
223
+ if (r) r_h = r->head();
226
224
  continue;
227
225
  }
226
+ #endif
228
227
  // check for valid selectors
229
228
  if (!l) return !!r;
230
229
  if (!r) return false;
@@ -235,11 +234,12 @@ namespace Sass {
235
234
  if (l->combinator() != r->combinator())
236
235
  { return l->combinator() < r->combinator(); }
237
236
  // advance to next tails
238
- l = &l->tail();
239
- r = &r->tail();
237
+ l = l->tail();
238
+ r = r->tail();
240
239
  // fetch the next headers
241
- l_h = l ? &l->head() : 0;
242
- r_h = r ? &r->head() : 0;
240
+ l_h = NULL; r_h = NULL;
241
+ if (l) l_h = l->head();
242
+ if (r) r_h = r->head();
243
243
  }
244
244
  // one side is null
245
245
  else if (!r_h) return true;
@@ -251,16 +251,16 @@ namespace Sass {
251
251
  if (l->combinator() != r->combinator())
252
252
  { return l->combinator() < r->combinator(); }
253
253
  // advance to next tails
254
- l = &l->tail();
255
- r = &r->tail();
254
+ l = l->tail();
255
+ r = r->tail();
256
256
  // fetch the next headers
257
- l_h = l ? &l->head() : 0;
258
- r_h = r ? &r->head() : 0;
257
+ l_h = NULL; r_h = NULL;
258
+ if (l) l_h = l->head();
259
+ if (r) r_h = r->head();
259
260
  }
260
261
  // heads are not equal
261
262
  else return *l_h < *r_h;
262
263
  }
263
- return true;
264
264
  }
265
265
 
266
266
  bool Complex_Selector::operator== (const Complex_Selector& rhs) const
@@ -268,25 +268,31 @@ namespace Sass {
268
268
  // const iterators for tails
269
269
  Complex_Selector_Ptr_Const l = this;
270
270
  Complex_Selector_Ptr_Const r = &rhs;
271
- Compound_Selector_Ptr l_h = l ? &l->head() : 0;
272
- Compound_Selector_Ptr r_h = r ? &r->head() : 0;
271
+ Compound_Selector_Ptr l_h = NULL;
272
+ Compound_Selector_Ptr r_h = NULL;
273
+ if (l) l_h = l->head();
274
+ if (r) r_h = r->head();
273
275
  // process all tails
274
276
  while (true)
275
277
  {
278
+ #ifdef DEBUG
276
279
  // skip empty ancestor first
277
280
  if (l && l->is_empty_ancestor())
278
281
  {
279
- l = &l->tail();
280
- l_h = l ? &l->head() : 0;
282
+ l_h = NULL;
283
+ l = l->tail();
284
+ if (l) l_h = l->head();
281
285
  continue;
282
286
  }
283
287
  // skip empty ancestor first
284
288
  if (r && r->is_empty_ancestor())
285
289
  {
286
- r = &r->tail();
287
- r_h = r ? &r->head() : 0;
290
+ r_h = NULL;
291
+ r = r->tail();
292
+ if (r) r_h = r->head();
288
293
  continue;
289
294
  }
295
+ #endif
290
296
  // check the pointers
291
297
  if (!r) return !l;
292
298
  if (!l) return !r;
@@ -297,27 +303,29 @@ namespace Sass {
297
303
  if (l->combinator() != r->combinator())
298
304
  { return l->combinator() < r->combinator(); }
299
305
  // advance to next tails
300
- l = &l->tail();
301
- r = &r->tail();
306
+ l = l->tail();
307
+ r = r->tail();
302
308
  // fetch the next heads
303
- l_h = l ? &l->head() : 0;
304
- r_h = r ? &r->head() : 0;
309
+ l_h = NULL; r_h = NULL;
310
+ if (l) l_h = l->head();
311
+ if (r) r_h = r->head();
305
312
  }
306
313
  // equals if other head is empty
307
314
  else if ((!l_h && !r_h) ||
308
315
  (!l_h && r_h->empty()) ||
309
316
  (!r_h && l_h->empty()) ||
310
- (*l_h == *r_h))
317
+ (l_h && r_h && *l_h == *r_h))
311
318
  {
312
319
  // check combinator after heads
313
320
  if (l->combinator() != r->combinator())
314
321
  { return l->combinator() == r->combinator(); }
315
322
  // advance to next tails
316
- l = &l->tail();
317
- r = &r->tail();
323
+ l = l->tail();
324
+ r = r->tail();
318
325
  // fetch the next heads
319
- l_h = l ? &l->head() : 0;
320
- r_h = r ? &r->head() : 0;
326
+ l_h = NULL; r_h = NULL;
327
+ if (l) l_h = l->head();
328
+ if (r) r_h = r->head();
321
329
  }
322
330
  // abort
323
331
  else break;
@@ -326,78 +334,105 @@ namespace Sass {
326
334
  return false;
327
335
  }
328
336
 
329
- Compound_Selector_Ptr Compound_Selector::unify_with(Compound_Selector_Ptr rhs, Context& ctx)
337
+ Compound_Selector_Ptr Compound_Selector::unify_with(Compound_Selector_Ptr rhs)
330
338
  {
331
339
  if (empty()) return rhs;
332
340
  Compound_Selector_Obj unified = SASS_MEMORY_COPY(rhs);
333
341
  for (size_t i = 0, L = length(); i < L; ++i)
334
342
  {
335
343
  if (unified.isNull()) break;
336
- unified = at(i)->unify_with(&unified, ctx);
344
+ unified = at(i)->unify_with(unified);
337
345
  }
338
346
  return unified.detach();
339
347
  }
340
348
 
341
- bool Selector::operator== (const Selector& rhs) const
349
+ bool Complex_Selector::operator== (const Selector& rhs) const
342
350
  {
343
- if (Selector_List_Ptr_Const sl = dynamic_cast<Selector_List_Ptr_Const>(this)) return *sl == rhs;
344
- if (Simple_Selector_Ptr_Const sp = dynamic_cast<Simple_Selector_Ptr_Const>(this)) return *sp == rhs;
351
+ if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this == *sl;
352
+ if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this == *sp;
353
+ if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
354
+ if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
345
355
  throw std::runtime_error("invalid selector base classes to compare");
346
- return false;
347
356
  }
348
357
 
349
- bool Selector::operator< (const Selector& rhs) const
358
+
359
+ bool Complex_Selector::operator< (const Selector& rhs) const
350
360
  {
351
- if (Selector_List_Ptr_Const sl = dynamic_cast<Selector_List_Ptr_Const>(this)) return *sl < rhs;
352
- if (Simple_Selector_Ptr_Const sp = dynamic_cast<Simple_Selector_Ptr_Const>(this)) return *sp < rhs;
361
+ if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this < *sl;
362
+ if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this < *sp;
363
+ if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
364
+ if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
365
+ throw std::runtime_error("invalid selector base classes to compare");
366
+ }
367
+
368
+ bool Compound_Selector::operator== (const Selector& rhs) const
369
+ {
370
+ if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this == *sl;
371
+ if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this == *sp;
372
+ if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
373
+ if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
374
+ throw std::runtime_error("invalid selector base classes to compare");
375
+ }
376
+
377
+ bool Compound_Selector::operator< (const Selector& rhs) const
378
+ {
379
+ if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this < *sl;
380
+ if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this < *sp;
381
+ if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
382
+ if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
383
+ throw std::runtime_error("invalid selector base classes to compare");
384
+ }
385
+
386
+ bool Selector_Schema::operator== (const Selector& rhs) const
387
+ {
388
+ if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this == *sl;
389
+ if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this == *sp;
390
+ if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
391
+ if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
392
+ throw std::runtime_error("invalid selector base classes to compare");
393
+ }
394
+
395
+ bool Selector_Schema::operator< (const Selector& rhs) const
396
+ {
397
+ if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this < *sl;
398
+ if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this < *sp;
399
+ if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
400
+ if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
353
401
  throw std::runtime_error("invalid selector base classes to compare");
354
- return false;
355
402
  }
356
403
 
357
404
  bool Simple_Selector::operator== (const Selector& rhs) const
358
405
  {
359
- if (Simple_Selector_Ptr_Const sp = dynamic_cast<Simple_Selector_Ptr_Const>(&rhs)) return *this == *sp;
406
+ if (Simple_Selector_Ptr_Const sp = Cast<Simple_Selector>(&rhs)) return *this == *sp;
360
407
  return false;
361
408
  }
362
409
 
363
410
  bool Simple_Selector::operator< (const Selector& rhs) const
364
411
  {
365
- if (Simple_Selector_Ptr_Const sp = dynamic_cast<Simple_Selector_Ptr_Const>(&rhs)) return *this < *sp;
412
+ if (Simple_Selector_Ptr_Const sp = Cast<Simple_Selector>(&rhs)) return *this < *sp;
366
413
  return false;
367
414
  }
368
415
 
369
416
  bool Simple_Selector::operator== (const Simple_Selector& rhs) const
370
417
  {
371
- Simple_Type type = simple_type();
372
- // dynamic cast is a bottleneck - use concrete type as types are final
373
- if (type == PSEUDO_SEL /* Pseudo_Selector_Ptr_Const lp = dynamic_cast<Pseudo_Selector_Ptr_Const>(this) */) {
374
- return *static_cast<Pseudo_Selector_Ptr_Const>(this) == rhs;
375
- }
376
- else if (type == WRAPPED_SEL /* Wrapped_Selector_Ptr_Const lw = dynamic_cast<Wrapped_Selector_Ptr_Const>(this) */) {
377
- return *static_cast<Wrapped_Selector_Ptr_Const>(this) == rhs;
378
- }
379
- else if (type == ATTR_SEL /* Attribute_Selector_Ptr_Const la = dynamic_cast<Attribute_Selector_Ptr_Const>(this) */) {
380
- return *static_cast<Attribute_Selector_Ptr_Const>(this) == rhs;
381
- }
418
+ // solve the double dispatch problem by using RTTI information via dynamic cast
419
+ if (const Pseudo_Selector* lhs = Cast<Pseudo_Selector>(this)) {return *lhs == rhs; }
420
+ else if (const Wrapped_Selector* lhs = Cast<Wrapped_Selector>(this)) {return *lhs == rhs; }
421
+ else if (const Element_Selector* lhs = Cast<Element_Selector>(this)) {return *lhs == rhs; }
422
+ else if (const Attribute_Selector* lhs = Cast<Attribute_Selector>(this)) {return *lhs == rhs; }
382
423
  else if (name_ == rhs.name_)
383
- { return is_ns_eq(ns_, rhs.ns_); }
424
+ { return is_ns_eq(rhs); }
384
425
  else return false;
385
426
  }
386
427
 
387
428
  bool Simple_Selector::operator< (const Simple_Selector& rhs) const
388
429
  {
389
- Simple_Type type = simple_type();
390
- // dynamic cast is a bottleneck - use concrete type as types are final
391
- if (type == PSEUDO_SEL /* Pseudo_Selector_Ptr_Const lp = dynamic_cast<Pseudo_Selector_Ptr_Const>(this) */) {
392
- return *static_cast<Pseudo_Selector_Ptr_Const>(this) < rhs;
393
- }
394
- else if (type == WRAPPED_SEL /* Wrapped_Selector_Ptr_Const lw = dynamic_cast<Wrapped_Selector_Ptr_Const>(this) */) {
395
- return *static_cast<Wrapped_Selector_Ptr_Const>(this) < rhs;
396
- }
397
- else if (type == ATTR_SEL /* Attribute_Selector_Ptr_Const la = dynamic_cast<Attribute_Selector_Ptr_Const>(this) */) {
398
- return *static_cast<Attribute_Selector_Ptr_Const>(this) < rhs;
399
- }
400
- if (is_ns_eq(ns_, rhs.ns_))
430
+ // solve the double dispatch problem by using RTTI information via dynamic cast
431
+ if (const Pseudo_Selector* lhs = Cast<Pseudo_Selector>(this)) {return *lhs < rhs; }
432
+ else if (const Wrapped_Selector* lhs = Cast<Wrapped_Selector>(this)) {return *lhs < rhs; }
433
+ else if (const Element_Selector* lhs = Cast<Element_Selector>(this)) {return *lhs < rhs; }
434
+ else if (const Attribute_Selector* lhs = Cast<Attribute_Selector>(this)) {return *lhs < rhs; }
435
+ if (is_ns_eq(rhs))
401
436
  { return name_ < rhs.name_; }
402
437
  return ns_ < rhs.ns_;
403
438
  }
@@ -405,19 +440,19 @@ namespace Sass {
405
440
  bool Selector_List::operator== (const Selector& rhs) const
406
441
  {
407
442
  // solve the double dispatch problem by using RTTI information via dynamic cast
408
- if (Selector_List_Ptr_Const ls = dynamic_cast<Selector_List_Ptr_Const>(&rhs)) { return *this == *ls; }
409
- else if (Complex_Selector_Ptr_Const ls = dynamic_cast<Complex_Selector_Ptr_Const>(&rhs)) { return *this == *ls; }
410
- else if (Compound_Selector_Ptr_Const ls = dynamic_cast<Compound_Selector_Ptr_Const>(&rhs)) { return *this == *ls; }
443
+ if (Selector_List_Ptr_Const sl = Cast<Selector_List>(&rhs)) { return *this == *sl; }
444
+ else if (Complex_Selector_Ptr_Const cpx = Cast<Complex_Selector>(&rhs)) { return *this == *cpx; }
445
+ else if (Compound_Selector_Ptr_Const cpd = Cast<Compound_Selector>(&rhs)) { return *this == *cpd; }
411
446
  // no compare method
412
447
  return this == &rhs;
413
448
  }
414
449
 
415
450
  // Selector lists can be compared to comma lists
416
- bool Selector_List::operator==(const Expression& rhs) const
451
+ bool Selector_List::operator== (const Expression& rhs) const
417
452
  {
418
453
  // solve the double dispatch problem by using RTTI information via dynamic cast
419
- if (List_Ptr_Const ls = dynamic_cast<List_Ptr_Const>(&rhs)) { return *this == *ls; }
420
- if (Selector_Ptr_Const ls = dynamic_cast<Selector_Ptr_Const>(&rhs)) { return *this == *ls; }
454
+ if (List_Ptr_Const ls = Cast<List>(&rhs)) { return *ls == *this; }
455
+ if (Selector_Ptr_Const ls = Cast<Selector>(&rhs)) { return *this == *ls; }
421
456
  // compare invalid (maybe we should error?)
422
457
  return false;
423
458
  }
@@ -431,8 +466,8 @@ namespace Sass {
431
466
  // create temporary vectors and sort them
432
467
  std::vector<Complex_Selector_Obj> l_lst = this->elements();
433
468
  std::vector<Complex_Selector_Obj> r_lst = rhs.elements();
434
- std::sort(l_lst.begin(), l_lst.end(), cmp_complex_selector());
435
- std::sort(r_lst.begin(), r_lst.end(), cmp_complex_selector());
469
+ std::sort(l_lst.begin(), l_lst.end(), OrderNodes());
470
+ std::sort(r_lst.begin(), r_lst.end(), OrderNodes());
436
471
  // process loop
437
472
  while (true)
438
473
  {
@@ -451,38 +486,38 @@ namespace Sass {
451
486
  // advance
452
487
  ++i; ++n;
453
488
  }
454
- // no mismatch
455
- return true;
489
+ // there is no break?!
456
490
  }
457
491
 
458
492
  bool Selector_List::operator< (const Selector& rhs) const
459
493
  {
460
- if (Selector_List_Ptr_Const sp = dynamic_cast<Selector_List_Ptr_Const>(&rhs)) return *this < *sp;
494
+ if (Selector_List_Ptr_Const sp = Cast<Selector_List>(&rhs)) return *this < *sp;
461
495
  return false;
462
496
  }
463
497
 
464
498
  bool Selector_List::operator< (const Selector_List& rhs) const
465
499
  {
466
- if (this->length() != rhs.length()) return false;
467
- for (size_t i = 0; i < rhs.length(); i ++) {
468
- if (!(*at(i) < *rhs.at(i))) return false;
500
+ size_t l = rhs.length();
501
+ if (length() < l) l = length();
502
+ for (size_t i = 0; i < l; i ++) {
503
+ if (*at(i) < *rhs.at(i)) return true;
469
504
  }
470
- return true;
505
+ return false;
471
506
  }
472
507
 
473
- Compound_Selector_Ptr Simple_Selector::unify_with(Compound_Selector_Ptr rhs, Context& ctx)
508
+ Compound_Selector_Ptr Simple_Selector::unify_with(Compound_Selector_Ptr rhs)
474
509
  {
475
510
  for (size_t i = 0, L = rhs->length(); i < L; ++i)
476
- { if (to_string(ctx.c_options) == rhs->at(i)->to_string(ctx.c_options)) return rhs; }
511
+ { if (to_string() == rhs->at(i)->to_string()) return rhs; }
477
512
 
478
513
  // check for pseudo elements because they are always last
479
514
  size_t i, L;
480
515
  bool found = false;
481
- if (typeid(*this) == typeid(Pseudo_Selector) || typeid(*this) == typeid(Wrapped_Selector))
516
+ if (typeid(*this) == typeid(Pseudo_Selector) || typeid(*this) == typeid(Wrapped_Selector) || typeid(*this) == typeid(Attribute_Selector))
482
517
  {
483
518
  for (i = 0, L = rhs->length(); i < L; ++i)
484
519
  {
485
- if ((SASS_MEMORY_CAST(Pseudo_Selector, (*rhs)[i]) || SASS_MEMORY_CAST(Wrapped_Selector, (*rhs)[i])) && (*rhs)[L-1]->is_pseudo_element())
520
+ if ((Cast<Pseudo_Selector>((*rhs)[i]) || Cast<Wrapped_Selector>((*rhs)[i]) || Cast<Attribute_Selector>((*rhs)[i])) && (*rhs)[L-1]->is_pseudo_element())
486
521
  { found = true; break; }
487
522
  }
488
523
  }
@@ -490,20 +525,20 @@ namespace Sass {
490
525
  {
491
526
  for (i = 0, L = rhs->length(); i < L; ++i)
492
527
  {
493
- if (SASS_MEMORY_CAST(Pseudo_Selector, (*rhs)[i]) || SASS_MEMORY_CAST(Wrapped_Selector, (*rhs)[i]))
528
+ if (Cast<Pseudo_Selector>((*rhs)[i]) || Cast<Wrapped_Selector>((*rhs)[i]) || Cast<Attribute_Selector>((*rhs)[i]))
494
529
  { found = true; break; }
495
530
  }
496
531
  }
497
532
  if (!found)
498
533
  {
499
534
  rhs->append(this);
500
- return rhs;
535
+ } else {
536
+ rhs->elements().insert(rhs->elements().begin() + i, this);
501
537
  }
502
- rhs->elements().insert(rhs->elements().begin() + i, this);
503
538
  return rhs;
504
539
  }
505
540
 
506
- Simple_Selector_Ptr Element_Selector::unify_with(Simple_Selector_Ptr rhs, Context& ctx)
541
+ Simple_Selector_Ptr Element_Selector::unify_with(Simple_Selector_Ptr rhs)
507
542
  {
508
543
  // check if ns can be extended
509
544
  // true for no ns or universal
@@ -534,7 +569,7 @@ namespace Sass {
534
569
  return this;
535
570
  }
536
571
 
537
- Compound_Selector_Ptr Element_Selector::unify_with(Compound_Selector_Ptr rhs, Context& ctx)
572
+ Compound_Selector_Ptr Element_Selector::unify_with(Compound_Selector_Ptr rhs)
538
573
  {
539
574
  // TODO: handle namespaces
540
575
 
@@ -544,18 +579,18 @@ namespace Sass {
544
579
  return rhs;
545
580
  }
546
581
 
547
- Simple_Selector_Ptr rhs_0 = &rhs->at(0);
582
+ Simple_Selector_Ptr rhs_0 = rhs->at(0);
548
583
  // otherwise, this is a tag name
549
584
  if (name() == "*")
550
585
  {
551
586
  if (typeid(*rhs_0) == typeid(Element_Selector))
552
587
  {
553
588
  // if rhs is universal, just return this tagname + rhs's qualifiers
554
- Element_Selector_Ptr ts = SASS_MEMORY_CAST_PTR(Element_Selector, rhs_0);
555
- rhs->at(0) = this->unify_with(ts, ctx);
589
+ Element_Selector_Ptr ts = Cast<Element_Selector>(rhs_0);
590
+ rhs->at(0) = this->unify_with(ts);
556
591
  return rhs;
557
592
  }
558
- else if (SASS_MEMORY_CAST_PTR(Class_Selector, rhs_0) || SASS_MEMORY_CAST_PTR(Id_Selector, rhs_0)) {
593
+ else if (Cast<Class_Selector>(rhs_0) || Cast<Id_Selector>(rhs_0)) {
559
594
  // qualifier is `.class`, so we can prefix with `ns|*.class`
560
595
  if (has_ns() && !rhs_0->has_ns()) {
561
596
  if (ns() != "*") rhs->elements().insert(rhs->begin(), this);
@@ -572,7 +607,7 @@ namespace Sass {
572
607
  // if rhs is universal, just return this tagname + rhs's qualifiers
573
608
  if (rhs_0->name() != "*" && rhs_0->ns() != "*" && rhs_0->name() != name()) return 0;
574
609
  // otherwise create new compound and unify first simple selector
575
- rhs->at(0) = this->unify_with(rhs_0, ctx);
610
+ rhs->at(0) = this->unify_with(rhs_0);
576
611
  return rhs;
577
612
 
578
613
  }
@@ -581,64 +616,61 @@ namespace Sass {
581
616
  return rhs;
582
617
  }
583
618
 
584
- Compound_Selector_Ptr Class_Selector::unify_with(Compound_Selector_Ptr rhs, Context& ctx)
619
+ Compound_Selector_Ptr Class_Selector::unify_with(Compound_Selector_Ptr rhs)
585
620
  {
586
621
  rhs->has_line_break(has_line_break());
587
- return Simple_Selector::unify_with(rhs, ctx);
622
+ return Simple_Selector::unify_with(rhs);
588
623
  }
589
624
 
590
- Compound_Selector_Ptr Id_Selector::unify_with(Compound_Selector_Ptr rhs, Context& ctx)
625
+ Compound_Selector_Ptr Id_Selector::unify_with(Compound_Selector_Ptr rhs)
591
626
  {
592
627
  for (size_t i = 0, L = rhs->length(); i < L; ++i)
593
628
  {
594
- if (Id_Selector_Ptr sel = SASS_MEMORY_CAST(Id_Selector, rhs->at(i))) {
629
+ if (Id_Selector_Ptr sel = Cast<Id_Selector>(rhs->at(i))) {
595
630
  if (sel->name() != name()) return 0;
596
631
  }
597
632
  }
598
633
  rhs->has_line_break(has_line_break());
599
- return Simple_Selector::unify_with(rhs, ctx);
634
+ return Simple_Selector::unify_with(rhs);
600
635
  }
601
636
 
602
- Compound_Selector_Ptr Pseudo_Selector::unify_with(Compound_Selector_Ptr rhs, Context& ctx)
637
+ Compound_Selector_Ptr Pseudo_Selector::unify_with(Compound_Selector_Ptr rhs)
603
638
  {
604
639
  if (is_pseudo_element())
605
640
  {
606
641
  for (size_t i = 0, L = rhs->length(); i < L; ++i)
607
642
  {
608
- if (Pseudo_Selector_Ptr sel = SASS_MEMORY_CAST(Pseudo_Selector, rhs->at(i))) {
643
+ if (Pseudo_Selector_Ptr sel = Cast<Pseudo_Selector>(rhs->at(i))) {
609
644
  if (sel->is_pseudo_element() && sel->name() != name()) return 0;
610
645
  }
611
646
  }
612
647
  }
613
- return Simple_Selector::unify_with(rhs, ctx);
648
+ return Simple_Selector::unify_with(rhs);
614
649
  }
615
650
 
616
651
  bool Attribute_Selector::operator< (const Attribute_Selector& rhs) const
617
652
  {
618
- if (is_ns_eq(ns(), rhs.ns())) {
653
+ if (is_ns_eq(rhs)) {
619
654
  if (name() == rhs.name()) {
620
655
  if (matcher() == rhs.matcher()) {
621
656
  bool no_lhs_val = value().isNull();
622
657
  bool no_rhs_val = rhs.value().isNull();
623
- if (no_lhs_val && no_rhs_val) {
624
- return true;
625
- }
626
- if (!no_lhs_val && !no_rhs_val) {
627
- return *value() < *rhs.value();
628
- }
658
+ if (no_lhs_val && no_rhs_val) return false; // equal
659
+ else if (no_lhs_val) return true; // lhs is null
660
+ else if (no_rhs_val) return false; // rhs is null
661
+ return *value() < *rhs.value(); // both are given
629
662
  } else { return matcher() < rhs.matcher(); }
630
663
  } else { return name() < rhs.name(); }
631
- }
632
- return false;
664
+ } else { return ns() < rhs.ns(); }
633
665
  }
634
666
 
635
667
  bool Attribute_Selector::operator< (const Simple_Selector& rhs) const
636
668
  {
637
- if (Attribute_Selector_Ptr_Const w = dynamic_cast<Attribute_Selector_Ptr_Const>(&rhs))
669
+ if (Attribute_Selector_Ptr_Const w = Cast<Attribute_Selector>(&rhs))
638
670
  {
639
671
  return *this < *w;
640
672
  }
641
- if (is_ns_eq(ns(), rhs.ns()))
673
+ if (is_ns_eq(rhs))
642
674
  { return name() < rhs.name(); }
643
675
  return ns() < rhs.ns();
644
676
  }
@@ -652,13 +684,13 @@ namespace Sass {
652
684
  if (no_lhs_val && no_rhs_val) {
653
685
  return (name() == rhs.name())
654
686
  && (matcher() == rhs.matcher())
655
- && (is_ns_eq(ns(), rhs.ns()));
687
+ && (is_ns_eq(rhs));
656
688
  }
657
689
  // both are defined, evaluate
658
690
  if (no_lhs_val == no_rhs_val) {
659
691
  return (name() == rhs.name())
660
692
  && (matcher() == rhs.matcher())
661
- && (is_ns_eq(ns(), rhs.ns()))
693
+ && (is_ns_eq(rhs))
662
694
  && (*value() == *rhs.value());
663
695
  }
664
696
  // not equal
@@ -668,97 +700,130 @@ namespace Sass {
668
700
 
669
701
  bool Attribute_Selector::operator== (const Simple_Selector& rhs) const
670
702
  {
671
- if (Attribute_Selector_Ptr_Const w = dynamic_cast<Attribute_Selector_Ptr_Const>(&rhs))
703
+ if (Attribute_Selector_Ptr_Const w = Cast<Attribute_Selector>(&rhs))
672
704
  {
673
- return *this == *w;
705
+ return is_ns_eq(rhs) &&
706
+ name() == rhs.name() &&
707
+ *this == *w;
708
+ }
709
+ return false;
710
+ }
711
+
712
+ bool Element_Selector::operator< (const Element_Selector& rhs) const
713
+ {
714
+ if (is_ns_eq(rhs))
715
+ { return name() < rhs.name(); }
716
+ return ns() < rhs.ns();
717
+ }
718
+
719
+ bool Element_Selector::operator< (const Simple_Selector& rhs) const
720
+ {
721
+ if (Element_Selector_Ptr_Const w = Cast<Element_Selector>(&rhs))
722
+ {
723
+ return *this < *w;
724
+ }
725
+ if (is_ns_eq(rhs))
726
+ { return name() < rhs.name(); }
727
+ return ns() < rhs.ns();
728
+ }
729
+
730
+ bool Element_Selector::operator== (const Element_Selector& rhs) const
731
+ {
732
+ return is_ns_eq(rhs) &&
733
+ name() == rhs.name();
734
+ }
735
+
736
+ bool Element_Selector::operator== (const Simple_Selector& rhs) const
737
+ {
738
+ if (Element_Selector_Ptr_Const w = Cast<Element_Selector>(&rhs))
739
+ {
740
+ return is_ns_eq(rhs) &&
741
+ name() == rhs.name() &&
742
+ *this == *w;
674
743
  }
675
- if (is_ns_eq(ns(), rhs.ns()))
676
- { return name() == rhs.name(); }
677
- return ns() == rhs.ns();
744
+ return false;
678
745
  }
679
746
 
680
747
  bool Pseudo_Selector::operator== (const Pseudo_Selector& rhs) const
681
748
  {
682
- if (is_ns_eq(ns(), rhs.ns()) && name() == rhs.name())
749
+ if (is_ns_eq(rhs) && name() == rhs.name())
683
750
  {
684
751
  String_Obj lhs_ex = expression();
685
752
  String_Obj rhs_ex = rhs.expression();
686
753
  if (rhs_ex && lhs_ex) return *lhs_ex == *rhs_ex;
687
- else return lhs_ex == rhs_ex;
754
+ else return lhs_ex.ptr() == rhs_ex.ptr();
688
755
  }
689
756
  else return false;
690
757
  }
691
758
 
692
759
  bool Pseudo_Selector::operator== (const Simple_Selector& rhs) const
693
760
  {
694
- if (Pseudo_Selector_Ptr_Const w = dynamic_cast<Pseudo_Selector_Ptr_Const>(&rhs))
761
+ if (Pseudo_Selector_Ptr_Const w = Cast<Pseudo_Selector>(&rhs))
695
762
  {
696
763
  return *this == *w;
697
764
  }
698
- if (is_ns_eq(ns(), rhs.ns()))
699
- { return name() == rhs.name(); }
700
- return ns() == rhs.ns();
765
+ return is_ns_eq(rhs) &&
766
+ name() == rhs.name();
701
767
  }
702
768
 
703
769
  bool Pseudo_Selector::operator< (const Pseudo_Selector& rhs) const
704
770
  {
705
- if (is_ns_eq(ns(), rhs.ns()) && name() == rhs.name())
771
+ if (is_ns_eq(rhs) && name() == rhs.name())
706
772
  {
707
773
  String_Obj lhs_ex = expression();
708
774
  String_Obj rhs_ex = rhs.expression();
709
775
  if (rhs_ex && lhs_ex) return *lhs_ex < *rhs_ex;
710
- else return lhs_ex < rhs_ex;
776
+ else return lhs_ex.ptr() < rhs_ex.ptr();
711
777
  }
712
- if (is_ns_eq(ns(), rhs.ns()))
778
+ if (is_ns_eq(rhs))
713
779
  { return name() < rhs.name(); }
714
780
  return ns() < rhs.ns();
715
781
  }
716
782
 
717
783
  bool Pseudo_Selector::operator< (const Simple_Selector& rhs) const
718
784
  {
719
- if (Pseudo_Selector_Ptr_Const w = dynamic_cast<Pseudo_Selector_Ptr_Const>(&rhs))
785
+ if (Pseudo_Selector_Ptr_Const w = Cast<Pseudo_Selector>(&rhs))
720
786
  {
721
787
  return *this < *w;
722
788
  }
723
- if (is_ns_eq(ns(), rhs.ns()))
789
+ if (is_ns_eq(rhs))
724
790
  { return name() < rhs.name(); }
725
791
  return ns() < rhs.ns();
726
792
  }
727
793
 
728
794
  bool Wrapped_Selector::operator== (const Wrapped_Selector& rhs) const
729
795
  {
730
- if (is_ns_eq(ns(), rhs.ns()) && name() == rhs.name())
796
+ if (is_ns_eq(rhs) && name() == rhs.name())
731
797
  { return *(selector()) == *(rhs.selector()); }
732
798
  else return false;
733
799
  }
734
800
 
735
801
  bool Wrapped_Selector::operator== (const Simple_Selector& rhs) const
736
802
  {
737
- if (Wrapped_Selector_Ptr_Const w = dynamic_cast<Wrapped_Selector_Ptr_Const>(&rhs))
803
+ if (Wrapped_Selector_Ptr_Const w = Cast<Wrapped_Selector>(&rhs))
738
804
  {
739
805
  return *this == *w;
740
806
  }
741
- if (is_ns_eq(ns(), rhs.ns()))
742
- { return name() == rhs.name(); }
743
- return ns() == rhs.ns();
807
+ return is_ns_eq(rhs) &&
808
+ name() == rhs.name();
744
809
  }
745
810
 
746
811
  bool Wrapped_Selector::operator< (const Wrapped_Selector& rhs) const
747
812
  {
748
- if (is_ns_eq(ns(), rhs.ns()) && name() == rhs.name())
813
+ if (is_ns_eq(rhs) && name() == rhs.name())
749
814
  { return *(selector()) < *(rhs.selector()); }
750
- if (is_ns_eq(ns(), rhs.ns()))
815
+ if (is_ns_eq(rhs))
751
816
  { return name() < rhs.name(); }
752
817
  return ns() < rhs.ns();
753
818
  }
754
819
 
755
820
  bool Wrapped_Selector::operator< (const Simple_Selector& rhs) const
756
821
  {
757
- if (Wrapped_Selector_Ptr_Const w = dynamic_cast<Wrapped_Selector_Ptr_Const>(&rhs))
822
+ if (Wrapped_Selector_Ptr_Const w = Cast<Wrapped_Selector>(&rhs))
758
823
  {
759
824
  return *this < *w;
760
825
  }
761
- if (is_ns_eq(ns(), rhs.ns()))
826
+ if (is_ns_eq(rhs))
762
827
  { return name() < rhs.name(); }
763
828
  return ns() < rhs.ns();
764
829
  }
@@ -767,28 +832,26 @@ namespace Sass {
767
832
  {
768
833
  if (this->name() != sub->name()) return false;
769
834
  if (this->name() == ":current") return false;
770
- if (Selector_List_Obj rhs_list = SASS_MEMORY_CAST(Selector_List, sub->selector())) {
771
- if (Selector_List_Obj lhs_list = SASS_MEMORY_CAST(Selector_List, selector())) {
835
+ if (Selector_List_Obj rhs_list = Cast<Selector_List>(sub->selector())) {
836
+ if (Selector_List_Obj lhs_list = Cast<Selector_List>(selector())) {
772
837
  return lhs_list->is_superselector_of(rhs_list);
773
838
  }
774
- error("is_superselector expected a Selector_List", sub->pstate());
775
- } else {
776
- error("is_superselector expected a Selector_List", sub->pstate());
777
839
  }
840
+ coreError("is_superselector expected a Selector_List", sub->pstate());
778
841
  return false;
779
842
  }
780
843
 
781
844
  bool Compound_Selector::is_superselector_of(Selector_List_Obj rhs, std::string wrapped)
782
845
  {
783
846
  for (Complex_Selector_Obj item : rhs->elements()) {
784
- if (is_superselector_of(&item, wrapped)) return true;
847
+ if (is_superselector_of(item, wrapped)) return true;
785
848
  }
786
849
  return false;
787
850
  }
788
851
 
789
852
  bool Compound_Selector::is_superselector_of(Complex_Selector_Obj rhs, std::string wrapped)
790
853
  {
791
- if (rhs->head()) return is_superselector_of(&rhs->head(), wrapped);
854
+ if (rhs->head()) return is_superselector_of(rhs->head(), wrapped);
792
855
  return false;
793
856
  }
794
857
 
@@ -821,6 +884,9 @@ namespace Sass {
821
884
  return false;
822
885
  }
823
886
 
887
+ // would like to replace this without stringification
888
+ // https://github.com/sass/sass/issues/2229
889
+ // SimpleSelectorSet lset, rset;
824
890
  std::set<std::string> lset, rset;
825
891
 
826
892
  if (lbase && rbase)
@@ -837,20 +903,20 @@ namespace Sass {
837
903
 
838
904
  for (size_t i = 0, iL = length(); i < iL; ++i)
839
905
  {
840
- Selector_Obj lhs = &(*this)[i];
906
+ Selector_Obj wlhs = (*this)[i];
841
907
  // very special case for wrapped matches selector
842
- if (Wrapped_Selector_Obj wrapped = SASS_MEMORY_CAST(Wrapped_Selector, lhs)) {
908
+ if (Wrapped_Selector_Obj wrapped = Cast<Wrapped_Selector>(wlhs)) {
843
909
  if (wrapped->name() == ":not") {
844
- if (Selector_List_Obj not_list = SASS_MEMORY_CAST(Selector_List, wrapped->selector())) {
910
+ if (Selector_List_Obj not_list = Cast<Selector_List>(wrapped->selector())) {
845
911
  if (not_list->is_superselector_of(rhs, wrapped->name())) return false;
846
912
  } else {
847
913
  throw std::runtime_error("wrapped not selector is not a list");
848
914
  }
849
915
  }
850
916
  if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") {
851
- lhs = wrapped->selector();
852
- if (Selector_List_Obj list = SASS_MEMORY_CAST(Selector_List, wrapped->selector())) {
853
- if (Compound_Selector_Obj comp = SASS_MEMORY_CAST(Compound_Selector, rhs)) {
917
+ wlhs = wrapped->selector();
918
+ if (Selector_List_Obj list = Cast<Selector_List>(wrapped->selector())) {
919
+ if (Compound_Selector_Obj comp = Cast<Compound_Selector>(rhs)) {
854
920
  if (!wrapping.empty() && wrapping != wrapped->name()) return false;
855
921
  if (wrapping.empty() || wrapping != wrapped->name()) {;
856
922
  if (list->is_superselector_of(comp, wrapped->name())) return true;
@@ -858,26 +924,25 @@ namespace Sass {
858
924
  }
859
925
  }
860
926
  }
861
- Simple_Selector_Ptr rhs_sel = rhs->elements().size() > i ? &(*rhs)[i] : 0;
862
- if (Wrapped_Selector_Ptr wrapped_r = dynamic_cast<Wrapped_Selector_Ptr>(rhs_sel)) {
927
+ Simple_Selector_Ptr rhs_sel = NULL;
928
+ if (rhs->elements().size() > i) rhs_sel = (*rhs)[i];
929
+ if (Wrapped_Selector_Ptr wrapped_r = Cast<Wrapped_Selector>(rhs_sel)) {
863
930
  if (wrapped->name() == wrapped_r->name()) {
864
931
  if (wrapped->is_superselector_of(wrapped_r)) {
865
932
  continue;
866
- rset.insert(lhs->to_string());
867
-
868
933
  }}
869
934
  }
870
935
  }
871
936
  // match from here on as strings
872
- lset.insert(lhs->to_string());
937
+ lset.insert(wlhs->to_string());
873
938
  }
874
939
 
875
940
  for (size_t n = 0, nL = rhs->length(); n < nL; ++n)
876
941
  {
877
- Selector_Obj r = &(*rhs)[n];
878
- if (Wrapped_Selector_Obj wrapped = SASS_MEMORY_CAST(Wrapped_Selector, r)) {
942
+ Selector_Obj r = (*rhs)[n];
943
+ if (Wrapped_Selector_Obj wrapped = Cast<Wrapped_Selector>(r)) {
879
944
  if (wrapped->name() == ":not") {
880
- if (Selector_List_Obj ls = SASS_MEMORY_CAST(Selector_List, wrapped->selector())) {
945
+ if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
881
946
  ls->remove_parent_selectors();
882
947
  if (is_superselector_of(ls, wrapped->name())) return false;
883
948
  }
@@ -886,7 +951,7 @@ namespace Sass {
886
951
  if (!wrapping.empty()) {
887
952
  if (wrapping != wrapped->name()) return false;
888
953
  }
889
- if (Selector_List_Obj ls = SASS_MEMORY_CAST(Selector_List, wrapped->selector())) {
954
+ if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
890
955
  ls->remove_parent_selectors();
891
956
  return (is_superselector_of(ls, wrapped->name()));
892
957
  }
@@ -915,7 +980,7 @@ namespace Sass {
915
980
  0);
916
981
  }
917
982
 
918
- Selector_List_Ptr Complex_Selector::unify_with(Complex_Selector_Ptr other, Context& ctx)
983
+ Selector_List_Ptr Complex_Selector::unify_with(Complex_Selector_Ptr other)
919
984
  {
920
985
 
921
986
  // get last tails (on the right side)
@@ -941,7 +1006,7 @@ namespace Sass {
941
1006
  SASS_ASSERT(r_last_head, "rhs head is null");
942
1007
 
943
1008
  // get the unification of the last compound selectors
944
- Compound_Selector_Obj unified = r_last_head->unify_with(&l_last_head, ctx);
1009
+ Compound_Selector_Obj unified = r_last_head->unify_with(l_last_head);
945
1010
 
946
1011
  // abort if we could not unify heads
947
1012
  if (unified == 0) return 0;
@@ -958,28 +1023,28 @@ namespace Sass {
958
1023
  }
959
1024
 
960
1025
  // create nodes from both selectors
961
- Node lhsNode = complexSelectorToNode(this, ctx);
962
- Node rhsNode = complexSelectorToNode(other, ctx);
1026
+ Node lhsNode = complexSelectorToNode(this);
1027
+ Node rhsNode = complexSelectorToNode(other);
963
1028
 
964
1029
  // overwrite universal base
965
1030
  if (!is_universal)
966
1031
  {
967
1032
  // create some temporaries to convert to node
968
1033
  Complex_Selector_Obj fake = unified->to_complex();
969
- Node unified_node = complexSelectorToNode(&fake, ctx);
1034
+ Node unified_node = complexSelectorToNode(fake);
970
1035
  // add to permutate the list?
971
1036
  rhsNode.plus(unified_node);
972
1037
  }
973
1038
 
974
1039
  // do some magic we inherit from node and extend
975
- Node node = Extend::subweave(lhsNode, rhsNode, ctx);
976
- Selector_List_Ptr result = SASS_MEMORY_NEW(Selector_List, pstate());
1040
+ Node node = subweave(lhsNode, rhsNode);
1041
+ Selector_List_Obj result = SASS_MEMORY_NEW(Selector_List, pstate());
977
1042
  NodeDequePtr col = node.collection(); // move from collection to list
978
1043
  for (NodeDeque::iterator it = col->begin(), end = col->end(); it != end; it++)
979
- { result->append(nodeToComplexSelector(Node::naiveTrim(*it, ctx), ctx)); }
1044
+ { result->append(nodeToComplexSelector(Node::naiveTrim(*it))); }
980
1045
 
981
1046
  // only return if list has some entries
982
- return result->length() ? result : 0;
1047
+ return result->length() ? result.detach() : 0;
983
1048
 
984
1049
  }
985
1050
 
@@ -992,8 +1057,8 @@ namespace Sass {
992
1057
  // create temporary vectors and sort them
993
1058
  std::vector<Simple_Selector_Obj> l_lst = this->elements();
994
1059
  std::vector<Simple_Selector_Obj> r_lst = rhs.elements();
995
- std::sort(l_lst.begin(), l_lst.end(), cmp_simple_selector());
996
- std::sort(r_lst.begin(), r_lst.end(), cmp_simple_selector());
1060
+ std::sort(l_lst.begin(), l_lst.end(), OrderNodes());
1061
+ std::sort(r_lst.begin(), r_lst.end(), OrderNodes());
997
1062
  // process loop
998
1063
  while (true)
999
1064
  {
@@ -1012,12 +1077,7 @@ namespace Sass {
1012
1077
  // advance now
1013
1078
  ++i; ++n;
1014
1079
  }
1015
- // no mismatch
1016
- return true;
1017
- }
1018
-
1019
- bool Complex_Selector_Pointer_Compare::operator() (const Complex_Selector_Obj& pLeft, const Complex_Selector_Obj& pRight) const {
1020
- return *pLeft < *pRight;
1080
+ // there is no break?!
1021
1081
  }
1022
1082
 
1023
1083
  bool Complex_Selector::is_superselector_of(Compound_Selector_Obj rhs, std::string wrapping)
@@ -1043,7 +1103,7 @@ namespace Sass {
1043
1103
  { return false; }
1044
1104
 
1045
1105
  if (l_len == 1)
1046
- { return lhs->head()->is_superselector_of(&rhs->last()->head(), wrapping); }
1106
+ { return lhs->head()->is_superselector_of(rhs->last()->head(), wrapping); }
1047
1107
 
1048
1108
  // we have to look one tail deeper, since we cary the
1049
1109
  // combinator around for it (which is important here)
@@ -1054,7 +1114,7 @@ namespace Sass {
1054
1114
  if (lhs_tail->head() && !rhs_tail->head()) return false;
1055
1115
  if (!lhs_tail->head() && rhs_tail->head()) return false;
1056
1116
  if (lhs_tail->head() && rhs_tail->head()) {
1057
- if (!lhs_tail->head()->is_superselector_of(&rhs_tail->head())) return false;
1117
+ if (!lhs_tail->head()->is_superselector_of(rhs_tail->head())) return false;
1058
1118
  }
1059
1119
  }
1060
1120
 
@@ -1063,7 +1123,7 @@ namespace Sass {
1063
1123
  for (size_t i = 0, L = rhs->length(); i < L; ++i) {
1064
1124
  if (i == L-1)
1065
1125
  { return false; }
1066
- if (lhs->head() && marker->head() && lhs->head()->is_superselector_of(&marker->head(), wrapping))
1126
+ if (lhs->head() && marker->head() && lhs->head()->is_superselector_of(marker->head(), wrapping))
1067
1127
  { found = true; break; }
1068
1128
  marker = marker->tail();
1069
1129
  }
@@ -1089,20 +1149,15 @@ namespace Sass {
1089
1149
  { return false; }
1090
1150
  if (!(lhs->combinator() == Complex_Selector::PRECEDES ? marker->combinator() != Complex_Selector::PARENT_OF : lhs->combinator() == marker->combinator()))
1091
1151
  { return false; }
1092
- return lhs->tail()->is_superselector_of(&marker->tail());
1152
+ return lhs->tail()->is_superselector_of(marker->tail());
1093
1153
  }
1094
1154
  else if (marker->combinator() != Complex_Selector::ANCESTOR_OF)
1095
1155
  {
1096
1156
  if (marker->combinator() != Complex_Selector::PARENT_OF)
1097
1157
  { return false; }
1098
- return lhs->tail()->is_superselector_of(&marker->tail());
1158
+ return lhs->tail()->is_superselector_of(marker->tail());
1099
1159
  }
1100
- else
1101
- {
1102
- return lhs->tail()->is_superselector_of(&marker->tail());
1103
- }
1104
- // catch-all
1105
- return false;
1160
+ return lhs->tail()->is_superselector_of(marker->tail());
1106
1161
  }
1107
1162
 
1108
1163
  size_t Complex_Selector::length() const
@@ -1112,20 +1167,11 @@ namespace Sass {
1112
1167
  return 1 + tail()->length();
1113
1168
  }
1114
1169
 
1115
- Complex_Selector_Obj Complex_Selector::context(Context& ctx)
1116
- {
1117
- if (!tail()) return 0;
1118
- if (!head()) return tail()->context(ctx);
1119
- Complex_Selector_Obj cpy = SASS_MEMORY_NEW(Complex_Selector, pstate(), combinator(), head(), tail()->context(ctx));
1120
- cpy->media_block(media_block());
1121
- return cpy;
1122
- }
1123
-
1124
1170
  // append another complex selector at the end
1125
1171
  // check if we need to append some headers
1126
1172
  // then we need to check for the combinator
1127
1173
  // only then we can safely set the new tail
1128
- void Complex_Selector::append(Context& ctx, Complex_Selector_Obj ss)
1174
+ void Complex_Selector::append(Complex_Selector_Obj ss, Backtraces& traces)
1129
1175
  {
1130
1176
 
1131
1177
  Complex_Selector_Obj t = ss->tail();
@@ -1139,47 +1185,49 @@ namespace Sass {
1139
1185
  // append old headers
1140
1186
  if (h && h->length()) {
1141
1187
  if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) {
1142
- error("Invalid parent selector", pstate_);
1188
+ traces.push_back(Backtrace(pstate()));
1189
+ throw Exception::InvalidParent(this, traces, ss);
1143
1190
  } else if (last()->head_ && last()->head_->length()) {
1144
1191
  Compound_Selector_Obj rh = last()->head();
1145
- size_t i = 0, L = h->length();
1146
- if (SASS_MEMORY_CAST(Element_Selector, h->first())) {
1147
- if (Class_Selector_Ptr sq = SASS_MEMORY_CAST(Class_Selector, rh->last())) {
1148
- Class_Selector_Ptr sqs = SASS_MEMORY_COPY(sq);
1192
+ size_t i;
1193
+ size_t L = h->length();
1194
+ if (Cast<Element_Selector>(h->first())) {
1195
+ if (Class_Selector_Ptr cs = Cast<Class_Selector>(rh->last())) {
1196
+ Class_Selector_Ptr sqs = SASS_MEMORY_COPY(cs);
1149
1197
  sqs->name(sqs->name() + (*h)[0]->name());
1150
1198
  sqs->pstate((*h)[0]->pstate());
1151
1199
  (*rh)[rh->length()-1] = sqs;
1152
1200
  rh->pstate(h->pstate());
1153
- for (i = 1; i < L; ++i) rh->append(&(*h)[i]);
1154
- } else if (Id_Selector_Ptr sq = SASS_MEMORY_CAST(Id_Selector, rh->last())) {
1155
- Id_Selector_Ptr sqs = SASS_MEMORY_COPY(sq);
1201
+ for (i = 1; i < L; ++i) rh->append((*h)[i]);
1202
+ } else if (Id_Selector_Ptr is = Cast<Id_Selector>(rh->last())) {
1203
+ Id_Selector_Ptr sqs = SASS_MEMORY_COPY(is);
1156
1204
  sqs->name(sqs->name() + (*h)[0]->name());
1157
1205
  sqs->pstate((*h)[0]->pstate());
1158
1206
  (*rh)[rh->length()-1] = sqs;
1159
1207
  rh->pstate(h->pstate());
1160
- for (i = 1; i < L; ++i) rh->append(&(*h)[i]);
1161
- } else if (Element_Selector_Ptr ts = SASS_MEMORY_CAST(Element_Selector, rh->last())) {
1208
+ for (i = 1; i < L; ++i) rh->append((*h)[i]);
1209
+ } else if (Element_Selector_Ptr ts = Cast<Element_Selector>(rh->last())) {
1162
1210
  Element_Selector_Ptr tss = SASS_MEMORY_COPY(ts);
1163
1211
  tss->name(tss->name() + (*h)[0]->name());
1164
1212
  tss->pstate((*h)[0]->pstate());
1165
1213
  (*rh)[rh->length()-1] = tss;
1166
1214
  rh->pstate(h->pstate());
1167
- for (i = 1; i < L; ++i) rh->append(&(*h)[i]);
1168
- } else if (Placeholder_Selector_Ptr ps = SASS_MEMORY_CAST(Placeholder_Selector, rh->last())) {
1215
+ for (i = 1; i < L; ++i) rh->append((*h)[i]);
1216
+ } else if (Placeholder_Selector_Ptr ps = Cast<Placeholder_Selector>(rh->last())) {
1169
1217
  Placeholder_Selector_Ptr pss = SASS_MEMORY_COPY(ps);
1170
1218
  pss->name(pss->name() + (*h)[0]->name());
1171
1219
  pss->pstate((*h)[0]->pstate());
1172
1220
  (*rh)[rh->length()-1] = pss;
1173
1221
  rh->pstate(h->pstate());
1174
- for (i = 1; i < L; ++i) rh->append(&(*h)[i]);
1222
+ for (i = 1; i < L; ++i) rh->append((*h)[i]);
1175
1223
  } else {
1176
- last()->head_->concat(&h);
1224
+ last()->head_->concat(h);
1177
1225
  }
1178
1226
  } else {
1179
- last()->head_->concat(&h);
1227
+ last()->head_->concat(h);
1180
1228
  }
1181
- } else {
1182
- last()->head_->concat(&h);
1229
+ } else if (last()->head_) {
1230
+ last()->head_->concat(h);
1183
1231
  }
1184
1232
  } else {
1185
1233
  // std::cerr << "has no or empty head\n";
@@ -1201,28 +1249,35 @@ namespace Sass {
1201
1249
  }
1202
1250
  }
1203
1251
 
1252
+ }
1204
1253
 
1254
+ Selector_List_Obj Selector_List::eval(Eval& eval)
1255
+ {
1256
+ Selector_List_Obj list = schema() ?
1257
+ eval(schema()) : eval(this);
1258
+ list->schema(schema());
1259
+ return list;
1205
1260
  }
1206
1261
 
1207
- Selector_List_Ptr Selector_List::resolve_parent_refs(Context& ctx, std::vector<Selector_List_Obj>& pstack, bool implicit_parent)
1262
+ Selector_List_Ptr Selector_List::resolve_parent_refs(std::vector<Selector_List_Obj>& pstack, Backtraces& traces, bool implicit_parent)
1208
1263
  {
1209
1264
  if (!this->has_parent_ref()) return this;
1210
1265
  Selector_List_Ptr ss = SASS_MEMORY_NEW(Selector_List, pstate());
1211
- Selector_List_Ptr ps = &pstack.back();
1266
+ Selector_List_Ptr ps = pstack.back();
1212
1267
  for (size_t pi = 0, pL = ps->length(); pi < pL; ++pi) {
1213
1268
  for (size_t si = 0, sL = this->length(); si < sL; ++si) {
1214
- Selector_List_Obj rv = at(si)->resolve_parent_refs(ctx, pstack, implicit_parent);
1215
- ss->concat(&rv);
1269
+ Selector_List_Obj rv = at(si)->resolve_parent_refs(pstack, traces, implicit_parent);
1270
+ ss->concat(rv);
1216
1271
  }
1217
1272
  }
1218
1273
  return ss;
1219
1274
  }
1220
1275
 
1221
- Selector_List_Ptr Complex_Selector::resolve_parent_refs(Context& ctx, std::vector<Selector_List_Obj>& pstack, bool implicit_parent)
1276
+ Selector_List_Ptr Complex_Selector::resolve_parent_refs(std::vector<Selector_List_Obj>& pstack, Backtraces& traces, bool implicit_parent)
1222
1277
  {
1223
1278
  Complex_Selector_Obj tail = this->tail();
1224
1279
  Compound_Selector_Obj head = this->head();
1225
- Selector_List_Ptr parents = &pstack.back();
1280
+ Selector_List_Ptr parents = pstack.back();
1226
1281
 
1227
1282
  if (!this->has_real_parent_ref() && !implicit_parent) {
1228
1283
  Selector_List_Ptr retval = SASS_MEMORY_NEW(Selector_List, pstate());
@@ -1231,14 +1286,14 @@ namespace Sass {
1231
1286
  }
1232
1287
 
1233
1288
  // first resolve_parent_refs the tail (which may return an expanded list)
1234
- Selector_List_Obj tails = tail ? tail->resolve_parent_refs(ctx, pstack, implicit_parent) : 0;
1289
+ Selector_List_Obj tails = tail ? tail->resolve_parent_refs(pstack, traces, implicit_parent) : 0;
1235
1290
 
1236
1291
  if (head && head->length() > 0) {
1237
1292
 
1238
1293
  Selector_List_Obj retval;
1239
1294
  // we have a parent selector in a simple compound list
1240
1295
  // mix parent complex selector into the compound list
1241
- if (SASS_MEMORY_CAST(Parent_Selector, (*head)[0])) {
1296
+ if (Cast<Parent_Selector>((*head)[0])) {
1242
1297
  retval = SASS_MEMORY_NEW(Selector_List, pstate());
1243
1298
 
1244
1299
  // it turns out that real parent references reach
@@ -1246,7 +1301,7 @@ namespace Sass {
1246
1301
  if (parents == NULL && head->has_real_parent_ref()) {
1247
1302
  int i = pstack.size() - 1;
1248
1303
  while (!parents && i > -1) {
1249
- parents = &pstack.at(i--);
1304
+ parents = pstack.at(i--);
1250
1305
  }
1251
1306
  }
1252
1307
 
@@ -1258,22 +1313,26 @@ namespace Sass {
1258
1313
  Complex_Selector_Obj parent = (*parents)[i];
1259
1314
  Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent);
1260
1315
  Complex_Selector_Obj ss = SASS_MEMORY_CLONE(this);
1261
- ss->tail(t ? SASS_MEMORY_CLONE(t) : 0);
1316
+ ss->tail(t ? SASS_MEMORY_CLONE(t) : NULL);
1262
1317
  Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
1263
1318
  // remove parent selector from sequence
1264
- if (h->length()) h->erase(h->begin());
1265
- ss->head(h->length() ? &h : 0);
1266
- // adjust for parent selector (1 char)
1267
1319
  if (h->length()) {
1268
- ParserState state(h->at(0)->pstate());
1269
- state.offset.column += 1;
1270
- state.column -= 1;
1271
- (*h)[0]->pstate(state);
1320
+ h->erase(h->begin());
1321
+ ss->head(h);
1322
+ } else {
1323
+ ss->head(NULL);
1272
1324
  }
1325
+ // adjust for parent selector (1 char)
1326
+ // if (h->length()) {
1327
+ // ParserState state(h->at(0)->pstate());
1328
+ // state.offset.column += 1;
1329
+ // state.column -= 1;
1330
+ // (*h)[0]->pstate(state);
1331
+ // }
1273
1332
  // keep old parser state
1274
1333
  s->pstate(pstate());
1275
1334
  // append new tail
1276
- s->append(ctx, ss);
1335
+ s->append(ss, traces);
1277
1336
  retval->append(s);
1278
1337
  }
1279
1338
  }
@@ -1288,26 +1347,31 @@ namespace Sass {
1288
1347
  // this is only if valid if the parent has no trailing op
1289
1348
  // otherwise we cannot append more simple selectors to head
1290
1349
  if (parent->last()->combinator() != ANCESTOR_OF) {
1291
- throw Exception::InvalidParent(&parent, &ss);
1350
+ traces.push_back(Backtrace(pstate()));
1351
+ throw Exception::InvalidParent(parent, traces, ss);
1292
1352
  }
1293
- ss->tail(tail ? SASS_MEMORY_CLONE(tail) : 0);
1353
+ ss->tail(tail ? SASS_MEMORY_CLONE(tail) : NULL);
1294
1354
  Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
1295
1355
  // remove parent selector from sequence
1296
- if (h->length()) h->erase(h->begin());
1297
- ss->head(h->length() ? &h : 0);
1356
+ if (h->length()) {
1357
+ h->erase(h->begin());
1358
+ ss->head(h);
1359
+ } else {
1360
+ ss->head(NULL);
1361
+ }
1298
1362
  // \/ IMO ruby sass bug \/
1299
1363
  ss->has_line_feed(false);
1300
1364
  // adjust for parent selector (1 char)
1301
- if (h->length()) {
1302
- ParserState state(h->at(0)->pstate());
1303
- state.offset.column += 1;
1304
- state.column -= 1;
1305
- (*h)[0]->pstate(state);
1306
- }
1365
+ // if (h->length()) {
1366
+ // ParserState state(h->at(0)->pstate());
1367
+ // state.offset.column += 1;
1368
+ // state.column -= 1;
1369
+ // (*h)[0]->pstate(state);
1370
+ // }
1307
1371
  // keep old parser state
1308
1372
  s->pstate(pstate());
1309
1373
  // append new tail
1310
- s->append(ctx, &ss);
1374
+ s->append(ss, traces);
1311
1375
  retval->append(s);
1312
1376
  }
1313
1377
  }
@@ -1320,7 +1384,7 @@ namespace Sass {
1320
1384
  cpy->tail(SASS_MEMORY_CLONE(tails->at(n)));
1321
1385
  cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
1322
1386
  for (size_t i = 1, L = this->head()->length(); i < L; ++i)
1323
- cpy->head()->append(&(*this->head())[i]);
1387
+ cpy->head()->append((*this->head())[i]);
1324
1388
  if (!cpy->head()->length()) cpy->head(0);
1325
1389
  retval->append(cpy->skip_empty_reference());
1326
1390
  }
@@ -1330,7 +1394,7 @@ namespace Sass {
1330
1394
  Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this);
1331
1395
  cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
1332
1396
  for (size_t i = 1, L = this->head()->length(); i < L; ++i)
1333
- cpy->head()->append(&(*this->head())[i]);
1397
+ cpy->head()->append((*this->head())[i]);
1334
1398
  if (!cpy->head()->length()) cpy->head(0);
1335
1399
  retval->append(cpy->skip_empty_reference());
1336
1400
  }
@@ -1338,13 +1402,13 @@ namespace Sass {
1338
1402
  }
1339
1403
  // no parent selector in head
1340
1404
  else {
1341
- retval = this->tails(ctx, &tails);
1405
+ retval = this->tails(tails);
1342
1406
  }
1343
1407
 
1344
1408
  for (Simple_Selector_Obj ss : head->elements()) {
1345
- if (Wrapped_Selector_Ptr ws = SASS_MEMORY_CAST(Wrapped_Selector, ss)) {
1346
- if (Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, ws->selector())) {
1347
- if (parents) ws->selector(sl->resolve_parent_refs(ctx, pstack, implicit_parent));
1409
+ if (Wrapped_Selector_Ptr ws = Cast<Wrapped_Selector>(ss)) {
1410
+ if (Selector_List_Ptr sl = Cast<Selector_List>(ws->selector())) {
1411
+ if (parents) ws->selector(sl->resolve_parent_refs(pstack, traces, implicit_parent));
1348
1412
  }
1349
1413
  }
1350
1414
  }
@@ -1353,15 +1417,10 @@ namespace Sass {
1353
1417
 
1354
1418
  }
1355
1419
  // has no head
1356
- else {
1357
- return this->tails(ctx, &tails);
1358
- }
1359
-
1360
- // unreachable
1361
- return 0;
1420
+ return this->tails(tails);
1362
1421
  }
1363
1422
 
1364
- Selector_List_Ptr Complex_Selector::tails(Context& ctx, Selector_List_Ptr tails)
1423
+ Selector_List_Ptr Complex_Selector::tails(Selector_List_Ptr tails)
1365
1424
  {
1366
1425
  Selector_List_Ptr rv = SASS_MEMORY_NEW(Selector_List, pstate_);
1367
1426
  if (tails && tails->length()) {
@@ -1389,21 +1448,27 @@ namespace Sass {
1389
1448
  // get the head
1390
1449
  head = cur->head_;
1391
1450
  // abort (and return) if it is not a parent selector
1392
- if (!head || head->length() != 1 || !SASS_MEMORY_CAST(Parent_Selector, (*head)[0])) {
1451
+ if (!head || head->length() != 1 || !Cast<Parent_Selector>((*head)[0])) {
1393
1452
  break;
1394
1453
  }
1395
1454
  // advance to next
1396
1455
  cur = cur->tail_;
1397
1456
  }
1398
1457
  // result
1399
- return &cur;
1458
+ return cur;
1400
1459
  }
1401
1460
 
1402
1461
  // return the last tail that is defined
1403
1462
  Complex_Selector_Obj Complex_Selector::last()
1404
1463
  {
1405
- // ToDo: implement with a while loop
1406
- return tail_? tail_->last() : this;
1464
+ Complex_Selector_Ptr cur = this;
1465
+ Complex_Selector_Ptr nxt = cur;
1466
+ // loop until last
1467
+ while (nxt) {
1468
+ cur = nxt;
1469
+ nxt = cur->tail();
1470
+ }
1471
+ return cur;
1407
1472
  }
1408
1473
 
1409
1474
  Complex_Selector::Combinator Complex_Selector::clear_innermost()
@@ -1474,7 +1539,31 @@ namespace Sass {
1474
1539
  }
1475
1540
  }
1476
1541
 
1477
- bool Selector_List::has_parent_ref()
1542
+ size_t Wrapped_Selector::hash()
1543
+ {
1544
+ if (hash_ == 0) {
1545
+ hash_combine(hash_, Simple_Selector::hash());
1546
+ if (selector_) hash_combine(hash_, selector_->hash());
1547
+ }
1548
+ return hash_;
1549
+ }
1550
+ bool Wrapped_Selector::has_parent_ref() const {
1551
+ // if (has_reference()) return true;
1552
+ if (!selector()) return false;
1553
+ return selector()->has_parent_ref();
1554
+ }
1555
+ bool Wrapped_Selector::has_real_parent_ref() const {
1556
+ // if (has_reference()) return true;
1557
+ if (!selector()) return false;
1558
+ return selector()->has_real_parent_ref();
1559
+ }
1560
+ unsigned long Wrapped_Selector::specificity() const
1561
+ {
1562
+ return selector_ ? selector_->specificity() : 0;
1563
+ }
1564
+
1565
+
1566
+ bool Selector_List::has_parent_ref() const
1478
1567
  {
1479
1568
  for (Complex_Selector_Obj s : elements()) {
1480
1569
  if (s && s->has_parent_ref()) return true;
@@ -1482,7 +1571,7 @@ namespace Sass {
1482
1571
  return false;
1483
1572
  }
1484
1573
 
1485
- bool Selector_List::has_real_parent_ref()
1574
+ bool Selector_List::has_real_parent_ref() const
1486
1575
  {
1487
1576
  for (Complex_Selector_Obj s : elements()) {
1488
1577
  if (s && s->has_real_parent_ref()) return true;
@@ -1490,18 +1579,18 @@ namespace Sass {
1490
1579
  return false;
1491
1580
  }
1492
1581
 
1493
- bool Selector_Schema::has_parent_ref()
1582
+ bool Selector_Schema::has_parent_ref() const
1494
1583
  {
1495
- if (String_Schema_Obj schema = SASS_MEMORY_CAST(String_Schema, contents())) {
1496
- return schema->length() > 0 && SASS_MEMORY_CAST(Parent_Selector, schema->at(0)) != NULL;
1584
+ if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
1585
+ return schema->length() > 0 && Cast<Parent_Selector>(schema->at(0)) != NULL;
1497
1586
  }
1498
1587
  return false;
1499
1588
  }
1500
1589
 
1501
- bool Selector_Schema::has_real_parent_ref()
1590
+ bool Selector_Schema::has_real_parent_ref() const
1502
1591
  {
1503
- if (String_Schema_Obj schema = SASS_MEMORY_CAST(String_Schema, contents())) {
1504
- Parent_Selector_Obj p = SASS_MEMORY_CAST(Parent_Selector, schema->at(0));
1592
+ if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
1593
+ Parent_Selector_Obj p = Cast<Parent_Selector>(schema->at(0));
1505
1594
  return schema->length() > 0 && p && p->is_real_parent_ref();
1506
1595
  }
1507
1596
  return false;
@@ -1518,7 +1607,7 @@ namespace Sass {
1518
1607
  {
1519
1608
  // Check every rhs selector against left hand list
1520
1609
  for(size_t i = 0, L = sub->length(); i < L; ++i) {
1521
- if (!is_superselector_of(&(*sub)[i], wrapping)) return false;
1610
+ if (!is_superselector_of((*sub)[i], wrapping)) return false;
1522
1611
  }
1523
1612
  return true;
1524
1613
  }
@@ -1529,7 +1618,7 @@ namespace Sass {
1529
1618
  {
1530
1619
  // Check every rhs selector against left hand list
1531
1620
  for(size_t i = 0, L = sub->length(); i < L; ++i) {
1532
- if (!is_superselector_of(&(*sub)[i], wrapping)) return false;
1621
+ if (!is_superselector_of((*sub)[i], wrapping)) return false;
1533
1622
  }
1534
1623
  return true;
1535
1624
  }
@@ -1556,18 +1645,18 @@ namespace Sass {
1556
1645
  return false;
1557
1646
  }
1558
1647
 
1559
- Selector_List_Ptr Selector_List::unify_with(Selector_List_Ptr rhs, Context& ctx) {
1648
+ Selector_List_Ptr Selector_List::unify_with(Selector_List_Ptr rhs) {
1560
1649
  std::vector<Complex_Selector_Obj> unified_complex_selectors;
1561
1650
  // Unify all of children with RHS's children, storing the results in `unified_complex_selectors`
1562
1651
  for (size_t lhs_i = 0, lhs_L = length(); lhs_i < lhs_L; ++lhs_i) {
1563
1652
  Complex_Selector_Obj seq1 = (*this)[lhs_i];
1564
1653
  for(size_t rhs_i = 0, rhs_L = rhs->length(); rhs_i < rhs_L; ++rhs_i) {
1565
- Complex_Selector_Ptr seq2 = &rhs->at(rhs_i);
1654
+ Complex_Selector_Ptr seq2 = rhs->at(rhs_i);
1566
1655
 
1567
- Selector_List_Obj result = seq1->unify_with(seq2, ctx);
1656
+ Selector_List_Obj result = seq1->unify_with(seq2);
1568
1657
  if( result ) {
1569
1658
  for(size_t i = 0, L = result->length(); i < L; ++i) {
1570
- unified_complex_selectors.push_back( &(*result)[i] );
1659
+ unified_complex_selectors.push_back( (*result)[i] );
1571
1660
  }
1572
1661
  }
1573
1662
  }
@@ -1581,7 +1670,7 @@ namespace Sass {
1581
1670
  return final_result;
1582
1671
  }
1583
1672
 
1584
- void Selector_List::populate_extends(Selector_List_Obj extendee, Context& ctx, Subset_Map& extends)
1673
+ void Selector_List::populate_extends(Selector_List_Obj extendee, Subset_Map& extends)
1585
1674
  {
1586
1675
 
1587
1676
  Selector_List_Ptr extender = this;
@@ -1594,7 +1683,7 @@ namespace Sass {
1594
1683
  Complex_Selector_Obj pIter = complex_sel;
1595
1684
  while (pIter) {
1596
1685
  Compound_Selector_Obj pHead = pIter->head();
1597
- if (pHead && SASS_MEMORY_CAST(Parent_Selector, pHead->elements()[0]) == NULL) {
1686
+ if (pHead && Cast<Parent_Selector>(pHead->elements()[0]) == NULL) {
1598
1687
  compound_sel = pHead;
1599
1688
  break;
1600
1689
  }
@@ -1603,32 +1692,24 @@ namespace Sass {
1603
1692
  }
1604
1693
 
1605
1694
  if (!pIter->head() || pIter->tail()) {
1606
- error("nested selectors may not be extended", c->pstate());
1695
+ coreError("nested selectors may not be extended", c->pstate());
1607
1696
  }
1608
1697
 
1609
1698
  compound_sel->is_optional(extendee->is_optional());
1610
1699
 
1611
1700
  for (size_t i = 0, L = extender->length(); i < L; ++i) {
1612
- extends.put(compound_sel, std::make_pair(&(*extender)[i], &compound_sel));
1701
+ extends.put(compound_sel, std::make_pair((*extender)[i], compound_sel));
1613
1702
  }
1614
1703
  }
1615
1704
  };
1616
1705
 
1617
- std::vector<std::string> Compound_Selector::to_str_vec()
1618
- {
1619
- std::vector<std::string> result(length());
1620
- for (size_t i = 0, L = length(); i < L; ++i)
1621
- { result.push_back((*this)[i]->to_string()); }
1622
- return result;
1623
- }
1624
-
1625
1706
  void Compound_Selector::append(Simple_Selector_Ptr element)
1626
1707
  {
1627
1708
  Vectorized<Simple_Selector_Obj>::append(element);
1628
1709
  pstate_.offset += element->pstate().offset;
1629
1710
  }
1630
1711
 
1631
- Compound_Selector_Ptr Compound_Selector::minus(Compound_Selector_Ptr rhs, Context& ctx)
1712
+ Compound_Selector_Ptr Compound_Selector::minus(Compound_Selector_Ptr rhs)
1632
1713
  {
1633
1714
  Compound_Selector_Ptr result = SASS_MEMORY_NEW(Compound_Selector, pstate());
1634
1715
  // result->has_parent_reference(has_parent_reference());
@@ -1637,24 +1718,24 @@ namespace Sass {
1637
1718
  for (size_t i = 0, L = length(); i < L; ++i)
1638
1719
  {
1639
1720
  bool found = false;
1640
- std::string thisSelector((*this)[i]->to_string(ctx.c_options));
1721
+ std::string thisSelector((*this)[i]->to_string());
1641
1722
  for (size_t j = 0, M = rhs->length(); j < M; ++j)
1642
1723
  {
1643
- if (thisSelector == (*rhs)[j]->to_string(ctx.c_options))
1724
+ if (thisSelector == (*rhs)[j]->to_string())
1644
1725
  {
1645
1726
  found = true;
1646
1727
  break;
1647
1728
  }
1648
1729
  }
1649
- if (!found) result->append(&(*this)[i]);
1730
+ if (!found) result->append((*this)[i]);
1650
1731
  }
1651
1732
 
1652
1733
  return result;
1653
1734
  }
1654
1735
 
1655
- void Compound_Selector::mergeSources(SourcesSet& sources, Context& ctx)
1736
+ void Compound_Selector::mergeSources(ComplexSelectorSet& sources)
1656
1737
  {
1657
- for (SourcesSet::iterator iterator = sources.begin(), endIterator = sources.end(); iterator != endIterator; ++iterator) {
1738
+ for (ComplexSelectorSet::iterator iterator = sources.begin(), endIterator = sources.end(); iterator != endIterator; ++iterator) {
1658
1739
  this->sources_.insert(SASS_MEMORY_CLONE(*iterator));
1659
1740
  }
1660
1741
  }
@@ -1686,38 +1767,38 @@ namespace Sass {
1686
1767
  void Arguments::adjust_after_pushing(Argument_Obj a)
1687
1768
  {
1688
1769
  if (!a->name().empty()) {
1689
- if (/* has_rest_argument_ || */ has_keyword_argument_) {
1690
- error("named arguments must precede variable-length argument", a->pstate());
1770
+ if (has_keyword_argument()) {
1771
+ coreError("named arguments must precede variable-length argument", a->pstate());
1691
1772
  }
1692
- has_named_arguments_ = true;
1773
+ has_named_arguments(true);
1693
1774
  }
1694
1775
  else if (a->is_rest_argument()) {
1695
- if (has_rest_argument_) {
1696
- error("functions and mixins may only be called with one variable-length argument", a->pstate());
1776
+ if (has_rest_argument()) {
1777
+ coreError("functions and mixins may only be called with one variable-length argument", a->pstate());
1697
1778
  }
1698
1779
  if (has_keyword_argument_) {
1699
- error("only keyword arguments may follow variable arguments", a->pstate());
1780
+ coreError("only keyword arguments may follow variable arguments", a->pstate());
1700
1781
  }
1701
- has_rest_argument_ = true;
1782
+ has_rest_argument(true);
1702
1783
  }
1703
1784
  else if (a->is_keyword_argument()) {
1704
- if (has_keyword_argument_) {
1705
- error("functions and mixins may only be called with one keyword argument", a->pstate());
1785
+ if (has_keyword_argument()) {
1786
+ coreError("functions and mixins may only be called with one keyword argument", a->pstate());
1706
1787
  }
1707
- has_keyword_argument_ = true;
1788
+ has_keyword_argument(true);
1708
1789
  }
1709
1790
  else {
1710
- if (has_rest_argument_) {
1711
- error("ordinal arguments must precede variable-length arguments", a->pstate());
1791
+ if (has_rest_argument()) {
1792
+ coreError("ordinal arguments must precede variable-length arguments", a->pstate());
1712
1793
  }
1713
- if (has_named_arguments_) {
1714
- error("ordinal arguments must precede named arguments", a->pstate());
1794
+ if (has_named_arguments()) {
1795
+ coreError("ordinal arguments must precede named arguments", a->pstate());
1715
1796
  }
1716
1797
  }
1717
1798
  }
1718
1799
 
1719
1800
  bool Ruleset::is_invisible() const {
1720
- if (Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, selector())) {
1801
+ if (Selector_List_Ptr sl = Cast<Selector_List>(selector())) {
1721
1802
  for (size_t i = 0, L = sl->length(); i < L; ++i)
1722
1803
  if (!(*sl)[i]->has_placeholder()) return false;
1723
1804
  }
@@ -1734,367 +1815,52 @@ namespace Sass {
1734
1815
 
1735
1816
  Number::Number(ParserState pstate, double val, std::string u, bool zero)
1736
1817
  : Value(pstate),
1818
+ Units(),
1737
1819
  value_(val),
1738
1820
  zero_(zero),
1739
- numerator_units_(std::vector<std::string>()),
1740
- denominator_units_(std::vector<std::string>()),
1741
1821
  hash_(0)
1742
1822
  {
1743
- size_t l = 0, r = 0;
1823
+ size_t l = 0;
1824
+ size_t r;
1744
1825
  if (!u.empty()) {
1745
1826
  bool nominator = true;
1746
1827
  while (true) {
1747
1828
  r = u.find_first_of("*/", l);
1748
1829
  std::string unit(u.substr(l, r == std::string::npos ? r : r - l));
1749
1830
  if (!unit.empty()) {
1750
- if (nominator) numerator_units_.push_back(unit);
1751
- else denominator_units_.push_back(unit);
1831
+ if (nominator) numerators.push_back(unit);
1832
+ else denominators.push_back(unit);
1752
1833
  }
1753
1834
  if (r == std::string::npos) break;
1754
1835
  // ToDo: should error for multiple slashes
1755
1836
  // if (!nominator && u[r] == '/') error(...)
1756
1837
  if (u[r] == '/')
1757
1838
  nominator = false;
1839
+ // strange math parsing?
1840
+ // else if (u[r] == '*')
1841
+ // nominator = true;
1758
1842
  l = r + 1;
1759
1843
  }
1760
1844
  }
1761
1845
  concrete_type(NUMBER);
1762
1846
  }
1763
1847
 
1764
- std::string Number::unit() const
1765
- {
1766
- std::string u;
1767
- for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
1768
- if (i) u += '*';
1769
- u += numerator_units_[i];
1770
- }
1771
- if (!denominator_units_.empty()) u += '/';
1772
- for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
1773
- if (i) u += '*';
1774
- u += denominator_units_[i];
1775
- }
1776
- return u;
1777
- }
1778
-
1779
- bool Number::is_valid_css_unit() const
1848
+ // cancel out unnecessary units
1849
+ void Number::reduce()
1780
1850
  {
1781
- return numerator_units().size() <= 1 &&
1782
- denominator_units().size() == 0;
1851
+ // apply conversion factor
1852
+ value_ *= this->Units::reduce();
1783
1853
  }
1784
1854
 
1785
- bool Number::is_unitless() const
1786
- { return numerator_units_.empty() && denominator_units_.empty(); }
1787
-
1788
- void Number::normalize(const std::string& prefered, bool strict)
1855
+ void Number::normalize()
1789
1856
  {
1790
-
1791
- // first make sure same units cancel each other out
1792
- // it seems that a map table will fit nicely to do this
1793
- // we basically construct exponents for each unit
1794
- // has the advantage that they will be pre-sorted
1795
- std::map<std::string, int> exponents;
1796
-
1797
- // initialize by summing up occurences in unit vectors
1798
- for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[numerator_units_[i]];
1799
- for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[denominator_units_[i]];
1800
-
1801
- // the final conversion factor
1802
- double factor = 1;
1803
-
1804
- // get the first entry of numerators
1805
- // forward it when entry is converted
1806
- std::vector<std::string>::iterator nom_it = numerator_units_.begin();
1807
- std::vector<std::string>::iterator nom_end = numerator_units_.end();
1808
- std::vector<std::string>::iterator denom_it = denominator_units_.begin();
1809
- std::vector<std::string>::iterator denom_end = denominator_units_.end();
1810
-
1811
- // main normalization loop
1812
- // should be close to optimal
1813
- while (denom_it != denom_end)
1814
- {
1815
- // get and increment afterwards
1816
- const std::string denom = *(denom_it ++);
1817
- // skip already canceled out unit
1818
- if (exponents[denom] >= 0) continue;
1819
- // skip all units we don't know how to convert
1820
- if (string_to_unit(denom) == UNKNOWN) continue;
1821
- // now search for nominator
1822
- while (nom_it != nom_end)
1823
- {
1824
- // get and increment afterwards
1825
- const std::string nom = *(nom_it ++);
1826
- // skip already canceled out unit
1827
- if (exponents[nom] <= 0) continue;
1828
- // skip all units we don't know how to convert
1829
- if (string_to_unit(nom) == UNKNOWN) continue;
1830
- // we now have two convertable units
1831
- // add factor for current conversion
1832
- factor *= conversion_factor(nom, denom, strict);
1833
- // update nominator/denominator exponent
1834
- -- exponents[nom]; ++ exponents[denom];
1835
- // inner loop done
1836
- break;
1837
- }
1838
- }
1839
-
1840
- // now we can build up the new unit arrays
1841
- numerator_units_.clear();
1842
- denominator_units_.clear();
1843
-
1844
- // build them by iterating over the exponents
1845
- for (auto exp : exponents)
1846
- {
1847
- // maybe there is more effecient way to push
1848
- // the same item multiple times to a vector?
1849
- for(size_t i = 0, S = abs(exp.second); i < S; ++i)
1850
- {
1851
- // opted to have these switches in the inner loop
1852
- // makes it more readable and should not cost much
1853
- if (!exp.first.empty()) {
1854
- if (exp.second < 0) denominator_units_.push_back(exp.first);
1855
- else if (exp.second > 0) numerator_units_.push_back(exp.first);
1856
- }
1857
- }
1858
- }
1859
-
1860
- // apply factor to value_
1861
- // best precision this way
1862
- value_ *= factor;
1863
-
1864
- // maybe convert to other unit
1865
- // easier implemented on its own
1866
- try { convert(prefered, strict); }
1867
- catch (incompatibleUnits& err)
1868
- { error(err.what(), pstate()); }
1869
- catch (...) { throw; }
1870
-
1871
- }
1872
-
1873
- // this does not cover all cases (multiple prefered units)
1874
- double Number::convert_factor(const Number& n) const
1875
- {
1876
-
1877
- // first make sure same units cancel each other out
1878
- // it seems that a map table will fit nicely to do this
1879
- // we basically construct exponents for each unit class
1880
- // std::map<std::string, int> exponents;
1881
- // initialize by summing up occurences in unit vectors
1882
- // for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[unit_to_class(numerator_units_[i])];
1883
- // for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[unit_to_class(denominator_units_[i])];
1884
-
1885
- std::vector<std::string> l_miss_nums(0);
1886
- std::vector<std::string> l_miss_dens(0);
1887
- // create copy since we need these for state keeping
1888
- std::vector<std::string> r_nums(n.numerator_units_);
1889
- std::vector<std::string> r_dens(n.denominator_units_);
1890
-
1891
- std::vector<std::string>::const_iterator l_num_it = numerator_units_.begin();
1892
- std::vector<std::string>::const_iterator l_num_end = numerator_units_.end();
1893
-
1894
- bool l_unitless = is_unitless();
1895
- bool r_unitless = n.is_unitless();
1896
-
1897
- // overall conversion
1898
- double factor = 1;
1899
-
1900
- // process all left numerators
1901
- while (l_num_it != l_num_end)
1902
- {
1903
- // get and increment afterwards
1904
- const std::string l_num = *(l_num_it ++);
1905
-
1906
- std::vector<std::string>::iterator r_num_it = r_nums.begin();
1907
- std::vector<std::string>::iterator r_num_end = r_nums.end();
1908
-
1909
- bool found = false;
1910
- // search for compatible numerator
1911
- while (r_num_it != r_num_end)
1912
- {
1913
- // get and increment afterwards
1914
- const std::string r_num = *(r_num_it);
1915
- // get possible converstion factor for units
1916
- double conversion = conversion_factor(l_num, r_num, false);
1917
- // skip incompatible numerator
1918
- if (conversion == 0) {
1919
- ++ r_num_it;
1920
- continue;
1921
- }
1922
- // apply to global factor
1923
- factor *= conversion;
1924
- // remove item from vector
1925
- r_nums.erase(r_num_it);
1926
- // found numerator
1927
- found = true;
1928
- break;
1929
- }
1930
- // maybe we did not find any
1931
- // left numerator is leftover
1932
- if (!found) l_miss_nums.push_back(l_num);
1933
- }
1934
-
1935
- std::vector<std::string>::const_iterator l_den_it = denominator_units_.begin();
1936
- std::vector<std::string>::const_iterator l_den_end = denominator_units_.end();
1937
-
1938
- // process all left denominators
1939
- while (l_den_it != l_den_end)
1940
- {
1941
- // get and increment afterwards
1942
- const std::string l_den = *(l_den_it ++);
1943
-
1944
- std::vector<std::string>::iterator r_den_it = r_dens.begin();
1945
- std::vector<std::string>::iterator r_den_end = r_dens.end();
1946
-
1947
- bool found = false;
1948
- // search for compatible denominator
1949
- while (r_den_it != r_den_end)
1950
- {
1951
- // get and increment afterwards
1952
- const std::string r_den = *(r_den_it);
1953
- // get possible converstion factor for units
1954
- double conversion = conversion_factor(l_den, r_den, false);
1955
- // skip incompatible denominator
1956
- if (conversion == 0) {
1957
- ++ r_den_it;
1958
- continue;
1959
- }
1960
- // apply to global factor
1961
- factor *= conversion;
1962
- // remove item from vector
1963
- r_dens.erase(r_den_it);
1964
- // found denominator
1965
- found = true;
1966
- break;
1967
- }
1968
- // maybe we did not find any
1969
- // left denominator is leftover
1970
- if (!found) l_miss_dens.push_back(l_den);
1971
- }
1972
-
1973
- // check left-overs (ToDo: might cancel out)
1974
- if (l_miss_nums.size() > 0 && !r_unitless) {
1975
- throw Exception::IncompatibleUnits(n, *this);
1976
- }
1977
- if (l_miss_dens.size() > 0 && !r_unitless) {
1978
- throw Exception::IncompatibleUnits(n, *this);
1979
- }
1980
- if (r_nums.size() > 0 && !l_unitless) {
1981
- throw Exception::IncompatibleUnits(n, *this);
1982
- }
1983
- if (r_dens.size() > 0 && !l_unitless) {
1984
- throw Exception::IncompatibleUnits(n, *this);
1985
- }
1986
-
1987
- return factor;
1988
- }
1989
-
1990
- // this does not cover all cases (multiple prefered units)
1991
- bool Number::convert(const std::string& prefered, bool strict)
1992
- {
1993
- // no conversion if unit is empty
1994
- if (prefered.empty()) return true;
1995
-
1996
- // first make sure same units cancel each other out
1997
- // it seems that a map table will fit nicely to do this
1998
- // we basically construct exponents for each unit
1999
- // has the advantage that they will be pre-sorted
2000
- std::map<std::string, int> exponents;
2001
-
2002
- // initialize by summing up occurences in unit vectors
2003
- for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[numerator_units_[i]];
2004
- for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[denominator_units_[i]];
2005
-
2006
- // the final conversion factor
2007
- double factor = 1;
2008
-
2009
- std::vector<std::string>::iterator denom_it = denominator_units_.begin();
2010
- std::vector<std::string>::iterator denom_end = denominator_units_.end();
2011
-
2012
- // main normalization loop
2013
- // should be close to optimal
2014
- while (denom_it != denom_end)
2015
- {
2016
- // get and increment afterwards
2017
- const std::string denom = *(denom_it ++);
2018
- // check if conversion is needed
2019
- if (denom == prefered) continue;
2020
- // skip already canceled out unit
2021
- if (exponents[denom] >= 0) continue;
2022
- // skip all units we don't know how to convert
2023
- if (string_to_unit(denom) == UNKNOWN) continue;
2024
- // we now have two convertable units
2025
- // add factor for current conversion
2026
- factor *= conversion_factor(denom, prefered, strict);
2027
- // update nominator/denominator exponent
2028
- ++ exponents[denom]; -- exponents[prefered];
2029
- }
2030
-
2031
- std::vector<std::string>::iterator nom_it = numerator_units_.begin();
2032
- std::vector<std::string>::iterator nom_end = numerator_units_.end();
2033
-
2034
- // now search for nominator
2035
- while (nom_it != nom_end)
2036
- {
2037
- // get and increment afterwards
2038
- const std::string nom = *(nom_it ++);
2039
- // check if conversion is needed
2040
- if (nom == prefered) continue;
2041
- // skip already canceled out unit
2042
- if (exponents[nom] <= 0) continue;
2043
- // skip all units we don't know how to convert
2044
- if (string_to_unit(nom) == UNKNOWN) continue;
2045
- // we now have two convertable units
2046
- // add factor for current conversion
2047
- factor *= conversion_factor(nom, prefered, strict);
2048
- // update nominator/denominator exponent
2049
- -- exponents[nom]; ++ exponents[prefered];
2050
- }
2051
-
2052
- // now we can build up the new unit arrays
2053
- numerator_units_.clear();
2054
- denominator_units_.clear();
2055
-
2056
- // build them by iterating over the exponents
2057
- for (auto exp : exponents)
2058
- {
2059
- // maybe there is more effecient way to push
2060
- // the same item multiple times to a vector?
2061
- for(size_t i = 0, S = abs(exp.second); i < S; ++i)
2062
- {
2063
- // opted to have these switches in the inner loop
2064
- // makes it more readable and should not cost much
2065
- if (!exp.first.empty()) {
2066
- if (exp.second < 0) denominator_units_.push_back(exp.first);
2067
- else if (exp.second > 0) numerator_units_.push_back(exp.first);
2068
- }
2069
- }
2070
- }
2071
-
2072
- // apply factor to value_
2073
- // best precision this way
2074
- value_ *= factor;
2075
-
2076
- // success?
2077
- return true;
2078
-
2079
- }
2080
-
2081
- // useful for making one number compatible with another
2082
- std::string Number::find_convertible_unit() const
2083
- {
2084
- for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
2085
- std::string u(numerator_units_[i]);
2086
- if (string_to_unit(u) != UNKNOWN) return u;
2087
- }
2088
- for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
2089
- std::string u(denominator_units_[i]);
2090
- if (string_to_unit(u) != UNKNOWN) return u;
2091
- }
2092
- return std::string();
1857
+ // apply conversion factor
1858
+ value_ *= this->Units::normalize();
2093
1859
  }
2094
1860
 
2095
1861
  bool Custom_Warning::operator== (const Expression& rhs) const
2096
1862
  {
2097
- if (Custom_Warning_Ptr_Const r = dynamic_cast<Custom_Warning_Ptr_Const>(&rhs)) {
1863
+ if (Custom_Warning_Ptr_Const r = Cast<Custom_Warning>(&rhs)) {
2098
1864
  return message() == r->message();
2099
1865
  }
2100
1866
  return false;
@@ -2102,67 +1868,59 @@ namespace Sass {
2102
1868
 
2103
1869
  bool Custom_Error::operator== (const Expression& rhs) const
2104
1870
  {
2105
- if (Custom_Error_Ptr_Const r = dynamic_cast<Custom_Error_Ptr_Const>(&rhs)) {
1871
+ if (Custom_Error_Ptr_Const r = Cast<Custom_Error>(&rhs)) {
2106
1872
  return message() == r->message();
2107
1873
  }
2108
1874
  return false;
2109
1875
  }
2110
1876
 
2111
- bool Number::eq (const Expression& rhs) const
1877
+ bool Number::operator== (const Expression& rhs) const
2112
1878
  {
2113
- if (Number_Ptr_Const r = dynamic_cast<Number_Ptr_Const>(&rhs)) {
2114
- size_t lhs_units = numerator_units_.size() + denominator_units_.size();
2115
- size_t rhs_units = r->numerator_units_.size() + r->denominator_units_.size();
2116
- if (!lhs_units && !rhs_units) {
2117
- return std::fabs(value() - r->value()) < NUMBER_EPSILON;
2118
- }
2119
- return (numerator_units_ == r->numerator_units_) &&
2120
- (denominator_units_ == r->denominator_units_) &&
2121
- std::fabs(value() - r->value()) < NUMBER_EPSILON;
1879
+ if (auto rhsnr = Cast<Number>(&rhs)) {
1880
+ return *this == *rhsnr;
2122
1881
  }
2123
1882
  return false;
2124
1883
  }
2125
1884
 
2126
- bool Number::operator== (const Expression& rhs) const
1885
+ bool Number::operator== (const Number& rhs) const
2127
1886
  {
2128
- if (Number_Ptr_Const r = dynamic_cast<Number_Ptr_Const>(&rhs)) {
2129
- size_t lhs_units = numerator_units_.size() + denominator_units_.size();
2130
- size_t rhs_units = r->numerator_units_.size() + r->denominator_units_.size();
2131
- // unitless and only having one unit seems equivalent (will change in future)
2132
- if (!lhs_units || !rhs_units) {
2133
- return std::fabs(value() - r->value()) < NUMBER_EPSILON;
2134
- }
2135
- return (numerator_units_ == r->numerator_units_) &&
2136
- (denominator_units_ == r->denominator_units_) &&
2137
- std::fabs(value() - r->value()) < NUMBER_EPSILON;
1887
+ Number l(*this), r(rhs); l.reduce(); r.reduce();
1888
+ size_t lhs_units = l.numerators.size() + l.denominators.size();
1889
+ size_t rhs_units = r.numerators.size() + r.denominators.size();
1890
+ // unitless and only having one unit seems equivalent (will change in future)
1891
+ if (!lhs_units || !rhs_units) {
1892
+ return NEAR_EQUAL(l.value(), r.value());
2138
1893
  }
2139
- return false;
1894
+ l.normalize(); r.normalize();
1895
+ Units &lhs_unit = l, &rhs_unit = r;
1896
+ return lhs_unit == rhs_unit &&
1897
+ NEAR_EQUAL(l.value(), r.value());
2140
1898
  }
2141
1899
 
2142
1900
  bool Number::operator< (const Number& rhs) const
2143
1901
  {
2144
- size_t lhs_units = numerator_units_.size() + denominator_units_.size();
2145
- size_t rhs_units = rhs.numerator_units_.size() + rhs.denominator_units_.size();
1902
+ Number l(*this), r(rhs); l.reduce(); r.reduce();
1903
+ size_t lhs_units = l.numerators.size() + l.denominators.size();
1904
+ size_t rhs_units = r.numerators.size() + r.denominators.size();
2146
1905
  // unitless and only having one unit seems equivalent (will change in future)
2147
1906
  if (!lhs_units || !rhs_units) {
2148
- return value() < rhs.value();
1907
+ return l.value() < r.value();
2149
1908
  }
2150
-
2151
- Number tmp_r(&rhs); // copy
2152
- tmp_r.normalize(find_convertible_unit());
2153
- std::string l_unit(unit());
2154
- std::string r_unit(tmp_r.unit());
2155
- if (unit() != tmp_r.unit()) {
2156
- error("cannot compare numbers with incompatible units", pstate());
1909
+ l.normalize(); r.normalize();
1910
+ Units &lhs_unit = l, &rhs_unit = r;
1911
+ if (!(lhs_unit == rhs_unit)) {
1912
+ /* ToDo: do we always get usefull backtraces? */
1913
+ throw Exception::IncompatibleUnits(rhs, *this);
2157
1914
  }
2158
- return value() < tmp_r.value();
1915
+ return lhs_unit < rhs_unit ||
1916
+ l.value() < r.value();
2159
1917
  }
2160
1918
 
2161
1919
  bool String_Quoted::operator== (const Expression& rhs) const
2162
1920
  {
2163
- if (String_Quoted_Ptr_Const qstr = dynamic_cast<String_Quoted_Ptr_Const>(&rhs)) {
1921
+ if (String_Quoted_Ptr_Const qstr = Cast<String_Quoted>(&rhs)) {
2164
1922
  return (value() == qstr->value());
2165
- } else if (String_Constant_Ptr_Const cstr = dynamic_cast<String_Constant_Ptr_Const>(&rhs)) {
1923
+ } else if (String_Constant_Ptr_Const cstr = Cast<String_Constant>(&rhs)) {
2166
1924
  return (value() == cstr->value());
2167
1925
  }
2168
1926
  return false;
@@ -2174,9 +1932,9 @@ namespace Sass {
2174
1932
 
2175
1933
  bool String_Constant::operator== (const Expression& rhs) const
2176
1934
  {
2177
- if (String_Quoted_Ptr_Const qstr = dynamic_cast<String_Quoted_Ptr_Const>(&rhs)) {
1935
+ if (String_Quoted_Ptr_Const qstr = Cast<String_Quoted>(&rhs)) {
2178
1936
  return (value() == qstr->value());
2179
- } else if (String_Constant_Ptr_Const cstr = dynamic_cast<String_Constant_Ptr_Const>(&rhs)) {
1937
+ } else if (String_Constant_Ptr_Const cstr = Cast<String_Constant>(&rhs)) {
2180
1938
  return (value() == cstr->value());
2181
1939
  }
2182
1940
  return false;
@@ -2193,7 +1951,7 @@ namespace Sass {
2193
1951
 
2194
1952
  bool String_Schema::operator== (const Expression& rhs) const
2195
1953
  {
2196
- if (String_Schema_Ptr_Const r = dynamic_cast<String_Schema_Ptr_Const>(&rhs)) {
1954
+ if (String_Schema_Ptr_Const r = Cast<String_Schema>(&rhs)) {
2197
1955
  if (length() != r->length()) return false;
2198
1956
  for (size_t i = 0, L = length(); i < L; ++i) {
2199
1957
  Expression_Obj rv = (*r)[i];
@@ -2208,7 +1966,7 @@ namespace Sass {
2208
1966
 
2209
1967
  bool Boolean::operator== (const Expression& rhs) const
2210
1968
  {
2211
- if (Boolean_Ptr_Const r = dynamic_cast<Boolean_Ptr_Const>(&rhs)) {
1969
+ if (Boolean_Ptr_Const r = Cast<Boolean>(&rhs)) {
2212
1970
  return (value() == r->value());
2213
1971
  }
2214
1972
  return false;
@@ -2216,7 +1974,7 @@ namespace Sass {
2216
1974
 
2217
1975
  bool Color::operator== (const Expression& rhs) const
2218
1976
  {
2219
- if (Color_Ptr_Const r = dynamic_cast<Color_Ptr_Const>(&rhs)) {
1977
+ if (Color_Ptr_Const r = Cast<Color>(&rhs)) {
2220
1978
  return r_ == r->r() &&
2221
1979
  g_ == r->g() &&
2222
1980
  b_ == r->b() &&
@@ -2227,9 +1985,10 @@ namespace Sass {
2227
1985
 
2228
1986
  bool List::operator== (const Expression& rhs) const
2229
1987
  {
2230
- if (List_Ptr_Const r = dynamic_cast<List_Ptr_Const>(&rhs)) {
1988
+ if (List_Ptr_Const r = Cast<List>(&rhs)) {
2231
1989
  if (length() != r->length()) return false;
2232
1990
  if (separator() != r->separator()) return false;
1991
+ if (is_bracketed() != r->is_bracketed()) return false;
2233
1992
  for (size_t i = 0, L = length(); i < L; ++i) {
2234
1993
  Expression_Obj rv = r->at(i);
2235
1994
  Expression_Obj lv = this->at(i);
@@ -2243,7 +2002,7 @@ namespace Sass {
2243
2002
 
2244
2003
  bool Map::operator== (const Expression& rhs) const
2245
2004
  {
2246
- if (Map_Ptr_Const r = dynamic_cast<Map_Ptr_Const>(&rhs)) {
2005
+ if (Map_Ptr_Const r = Cast<Map>(&rhs)) {
2247
2006
  if (length() != r->length()) return false;
2248
2007
  for (auto key : keys()) {
2249
2008
  Expression_Obj lv = at(key);
@@ -2261,13 +2020,23 @@ namespace Sass {
2261
2020
  return rhs.concrete_type() == NULL_VAL;
2262
2021
  }
2263
2022
 
2023
+ bool Function::operator== (const Expression& rhs) const
2024
+ {
2025
+ if (Function_Ptr_Const r = Cast<Function>(&rhs)) {
2026
+ Definition_Ptr_Const d1 = Cast<Definition>(definition());
2027
+ Definition_Ptr_Const d2 = Cast<Definition>(r->definition());
2028
+ return d1 && d2 && d1 == d2 && is_css() == r->is_css();
2029
+ }
2030
+ return false;
2031
+ }
2032
+
2264
2033
  size_t List::size() const {
2265
2034
  if (!is_arglist_) return length();
2266
2035
  // arglist expects a list of arguments
2267
2036
  // so we need to break before keywords
2268
2037
  for (size_t i = 0, L = length(); i < L; ++i) {
2269
2038
  Expression_Obj obj = this->at(i);
2270
- if (Argument* arg = dynamic_cast<Argument*>(&obj)) {
2039
+ if (Argument_Ptr arg = Cast<Argument>(obj)) {
2271
2040
  if (!arg->name().empty()) return i;
2272
2041
  }
2273
2042
  }
@@ -2290,7 +2059,7 @@ namespace Sass {
2290
2059
  return is_interpolant() || (right() && right()->is_right_interpolant());
2291
2060
  }
2292
2061
 
2293
- std::string AST_Node::to_string(Sass_Inspect_Options opt) const
2062
+ const std::string AST_Node::to_string(Sass_Inspect_Options opt) const
2294
2063
  {
2295
2064
  Sass_Output_Options out(opt);
2296
2065
  Emitter emitter(out);
@@ -2301,7 +2070,7 @@ namespace Sass {
2301
2070
  return i.get_buffer();
2302
2071
  }
2303
2072
 
2304
- std::string AST_Node::to_string() const
2073
+ const std::string AST_Node::to_string() const
2305
2074
  {
2306
2075
  return to_string({ NESTED, 5 });
2307
2076
  }
@@ -2316,33 +2085,40 @@ namespace Sass {
2316
2085
  return quote(value_, '*');
2317
2086
  }
2318
2087
 
2088
+ bool Declaration::is_invisible() const
2089
+ {
2090
+ if (is_custom_property()) return false;
2091
+
2092
+ return !(value_ && value_->concrete_type() != Expression::NULL_VAL);
2093
+ }
2094
+
2319
2095
  //////////////////////////////////////////////////////////////////////////////////////////
2320
2096
  // Additional method on Lists to retrieve values directly or from an encompassed Argument.
2321
2097
  //////////////////////////////////////////////////////////////////////////////////////////
2322
2098
  Expression_Obj List::value_at_index(size_t i) {
2323
2099
  Expression_Obj obj = this->at(i);
2324
2100
  if (is_arglist_) {
2325
- if (Argument* arg = dynamic_cast<Argument*>(&obj)) {
2101
+ if (Argument_Ptr arg = Cast<Argument>(obj)) {
2326
2102
  return arg->value();
2327
2103
  } else {
2328
- return &obj;
2104
+ return obj;
2329
2105
  }
2330
2106
  } else {
2331
- return &obj;
2107
+ return obj;
2332
2108
  }
2333
2109
  }
2334
2110
 
2335
2111
  //////////////////////////////////////////////////////////////////////////////////////////
2336
2112
  // Convert map to (key, value) list.
2337
2113
  //////////////////////////////////////////////////////////////////////////////////////////
2338
- List_Obj Map::to_list(Context& ctx, ParserState& pstate) {
2114
+ List_Obj Map::to_list(ParserState& pstate) {
2339
2115
  List_Obj ret = SASS_MEMORY_NEW(List, pstate, length(), SASS_COMMA);
2340
2116
 
2341
2117
  for (auto key : keys()) {
2342
2118
  List_Obj l = SASS_MEMORY_NEW(List, pstate, 2);
2343
- l->append(&key);
2119
+ l->append(key);
2344
2120
  l->append(at(key));
2345
- ret->append(&l);
2121
+ ret->append(l);
2346
2122
  }
2347
2123
 
2348
2124
  return ret;
@@ -2396,6 +2172,7 @@ namespace Sass {
2396
2172
  IMPLEMENT_AST_OPERATORS(Custom_Error);
2397
2173
  IMPLEMENT_AST_OPERATORS(List);
2398
2174
  IMPLEMENT_AST_OPERATORS(Map);
2175
+ IMPLEMENT_AST_OPERATORS(Function);
2399
2176
  IMPLEMENT_AST_OPERATORS(Number);
2400
2177
  IMPLEMENT_AST_OPERATORS(Binary_Expression);
2401
2178
  IMPLEMENT_AST_OPERATORS(String_Schema);
@@ -2439,7 +2216,6 @@ namespace Sass {
2439
2216
  IMPLEMENT_AST_OPERATORS(Function_Call_Schema);
2440
2217
  IMPLEMENT_AST_OPERATORS(Block);
2441
2218
  IMPLEMENT_AST_OPERATORS(Content);
2442
- IMPLEMENT_AST_OPERATORS(Textual);
2443
2219
  IMPLEMENT_AST_OPERATORS(Trace);
2444
2220
  IMPLEMENT_AST_OPERATORS(Keyframe_Rule);
2445
2221
  IMPLEMENT_AST_OPERATORS(Bubble);
@@ -2447,5 +2223,4 @@ namespace Sass {
2447
2223
  IMPLEMENT_AST_OPERATORS(Placeholder_Selector);
2448
2224
  IMPLEMENT_AST_OPERATORS(Definition);
2449
2225
  IMPLEMENT_AST_OPERATORS(Declaration);
2450
-
2451
2226
  }