sassc 2.0.1 → 2.1.0.pre1

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 (200) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +1 -1
  4. data/.travis.yml +7 -3
  5. data/CHANGELOG.md +3 -0
  6. data/CODE_OF_CONDUCT.md +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +23 -8
  9. data/ext/extconf.rb +39 -0
  10. data/ext/libsass/.gitignore +1 -0
  11. data/ext/libsass/GNUmakefile.am +23 -39
  12. data/ext/libsass/Makefile +56 -91
  13. data/ext/libsass/Makefile.conf +16 -2
  14. data/ext/libsass/configure.ac +8 -12
  15. data/ext/libsass/include/sass/base.h +1 -0
  16. data/ext/libsass/include/sass/context.h +1 -1
  17. data/ext/libsass/src/GNUmakefile.am +1 -5
  18. data/ext/libsass/src/ast.cpp +747 -2010
  19. data/ext/libsass/src/ast.hpp +239 -2383
  20. data/ext/libsass/src/{to_c.cpp → ast2c.cpp} +22 -16
  21. data/ext/libsass/src/ast2c.hpp +39 -0
  22. data/ext/libsass/src/ast_def_macros.hpp +62 -10
  23. data/ext/libsass/src/ast_fwd_decl.cpp +1 -0
  24. data/ext/libsass/src/ast_fwd_decl.hpp +43 -165
  25. data/ext/libsass/src/ast_sel_cmp.cpp +909 -0
  26. data/ext/libsass/src/ast_sel_unify.cpp +280 -0
  27. data/ext/libsass/src/ast_selectors.cpp +1475 -0
  28. data/ext/libsass/src/ast_selectors.hpp +568 -0
  29. data/ext/libsass/src/ast_supports.cpp +130 -0
  30. data/ext/libsass/src/ast_supports.hpp +121 -0
  31. data/ext/libsass/src/ast_values.cpp +967 -0
  32. data/ext/libsass/src/ast_values.hpp +489 -0
  33. data/ext/libsass/src/backtrace.cpp +4 -0
  34. data/ext/libsass/src/base64vlq.cpp +3 -0
  35. data/ext/libsass/src/bind.cpp +18 -17
  36. data/ext/libsass/src/bind.hpp +3 -1
  37. data/ext/libsass/src/c2ast.cpp +64 -0
  38. data/ext/libsass/src/c2ast.hpp +14 -0
  39. data/ext/libsass/src/cencode.c +2 -2
  40. data/ext/libsass/src/check_nesting.cpp +52 -56
  41. data/ext/libsass/src/check_nesting.hpp +35 -34
  42. data/ext/libsass/src/color_maps.cpp +156 -153
  43. data/ext/libsass/src/color_maps.hpp +152 -152
  44. data/ext/libsass/src/constants.cpp +15 -0
  45. data/ext/libsass/src/constants.hpp +13 -0
  46. data/ext/libsass/src/context.cpp +24 -14
  47. data/ext/libsass/src/context.hpp +6 -6
  48. data/ext/libsass/src/cssize.cpp +69 -71
  49. data/ext/libsass/src/cssize.hpp +50 -50
  50. data/ext/libsass/src/debugger.hpp +117 -110
  51. data/ext/libsass/src/emitter.cpp +13 -12
  52. data/ext/libsass/src/emitter.hpp +13 -9
  53. data/ext/libsass/src/environment.cpp +15 -1
  54. data/ext/libsass/src/environment.hpp +6 -0
  55. data/ext/libsass/src/error_handling.cpp +36 -59
  56. data/ext/libsass/src/error_handling.hpp +29 -16
  57. data/ext/libsass/src/eval.cpp +302 -323
  58. data/ext/libsass/src/eval.hpp +64 -55
  59. data/ext/libsass/src/expand.cpp +94 -88
  60. data/ext/libsass/src/expand.hpp +33 -37
  61. data/ext/libsass/src/extend.cpp +38 -36
  62. data/ext/libsass/src/extend.hpp +15 -15
  63. data/ext/libsass/src/file.cpp +34 -2
  64. data/ext/libsass/src/fn_colors.cpp +594 -0
  65. data/ext/libsass/src/fn_colors.hpp +85 -0
  66. data/ext/libsass/src/fn_lists.cpp +284 -0
  67. data/ext/libsass/src/fn_lists.hpp +34 -0
  68. data/ext/libsass/src/fn_maps.cpp +94 -0
  69. data/ext/libsass/src/fn_maps.hpp +30 -0
  70. data/ext/libsass/src/fn_miscs.cpp +256 -0
  71. data/ext/libsass/src/fn_miscs.hpp +40 -0
  72. data/ext/libsass/src/fn_numbers.cpp +220 -0
  73. data/ext/libsass/src/fn_numbers.hpp +45 -0
  74. data/ext/libsass/src/fn_selectors.cpp +235 -0
  75. data/ext/libsass/src/fn_selectors.hpp +35 -0
  76. data/ext/libsass/src/fn_strings.cpp +254 -0
  77. data/ext/libsass/src/fn_strings.hpp +34 -0
  78. data/ext/libsass/src/fn_utils.cpp +156 -0
  79. data/ext/libsass/src/fn_utils.hpp +56 -0
  80. data/ext/libsass/src/inspect.cpp +101 -152
  81. data/ext/libsass/src/inspect.hpp +69 -73
  82. data/ext/libsass/src/json.cpp +2 -2
  83. data/ext/libsass/src/lexer.cpp +6 -3
  84. data/ext/libsass/src/listize.cpp +9 -11
  85. data/ext/libsass/src/listize.hpp +11 -7
  86. data/ext/libsass/src/memory/SharedPtr.cpp +2 -83
  87. data/ext/libsass/src/memory/SharedPtr.hpp +127 -143
  88. data/ext/libsass/src/node.cpp +13 -10
  89. data/ext/libsass/src/node.hpp +3 -3
  90. data/ext/libsass/src/operation.hpp +184 -144
  91. data/ext/libsass/src/operators.cpp +43 -17
  92. data/ext/libsass/src/operators.hpp +5 -5
  93. data/ext/libsass/src/output.cpp +21 -18
  94. data/ext/libsass/src/output.hpp +14 -21
  95. data/ext/libsass/src/parser.cpp +215 -183
  96. data/ext/libsass/src/parser.hpp +28 -24
  97. data/ext/libsass/src/plugins.cpp +5 -1
  98. data/ext/libsass/src/position.cpp +3 -0
  99. data/ext/libsass/src/prelexer.cpp +9 -3
  100. data/ext/libsass/src/prelexer.hpp +9 -9
  101. data/ext/libsass/src/remove_placeholders.cpp +14 -11
  102. data/ext/libsass/src/remove_placeholders.hpp +8 -9
  103. data/ext/libsass/src/sass.cpp +9 -3
  104. data/ext/libsass/src/sass.hpp +12 -9
  105. data/ext/libsass/src/sass2scss.cpp +45 -14
  106. data/ext/libsass/src/sass_context.cpp +18 -15
  107. data/ext/libsass/src/sass_functions.cpp +6 -3
  108. data/ext/libsass/src/sass_functions.hpp +1 -1
  109. data/ext/libsass/src/sass_util.cpp +3 -0
  110. data/ext/libsass/src/sass_values.cpp +21 -13
  111. data/ext/libsass/src/source_map.cpp +5 -2
  112. data/ext/libsass/src/source_map.hpp +2 -2
  113. data/ext/libsass/src/subset_map.cpp +4 -1
  114. data/ext/libsass/src/to_value.cpp +23 -21
  115. data/ext/libsass/src/to_value.hpp +18 -22
  116. data/ext/libsass/src/units.cpp +4 -0
  117. data/ext/libsass/src/units.hpp +1 -0
  118. data/ext/libsass/src/utf8/checked.h +12 -10
  119. data/ext/libsass/src/utf8/core.h +3 -0
  120. data/ext/libsass/src/utf8_string.cpp +3 -0
  121. data/ext/libsass/src/util.cpp +67 -75
  122. data/ext/libsass/src/util.hpp +64 -19
  123. data/ext/libsass/src/util_string.cpp +75 -0
  124. data/ext/libsass/src/util_string.hpp +19 -0
  125. data/ext/libsass/src/values.cpp +22 -13
  126. data/ext/libsass/src/values.hpp +2 -2
  127. data/ext/libsass/win/libsass.targets +30 -4
  128. data/ext/libsass/win/libsass.vcxproj.filters +82 -4
  129. data/lib/sassc.rb +24 -0
  130. data/lib/sassc/engine.rb +2 -2
  131. data/lib/sassc/native.rb +8 -1
  132. data/lib/sassc/version.rb +1 -1
  133. data/sassc.gemspec +19 -11
  134. data/test/engine_test.rb +26 -1
  135. data/test/native_test.rb +1 -1
  136. metadata +66 -72
  137. data/ext/Rakefile +0 -3
  138. data/ext/libsass/.github/CONTRIBUTING.md +0 -65
  139. data/ext/libsass/.github/ISSUE_TEMPLATE.md +0 -54
  140. data/ext/libsass/.travis.yml +0 -64
  141. data/ext/libsass/Readme.md +0 -104
  142. data/ext/libsass/SECURITY.md +0 -10
  143. data/ext/libsass/appveyor.yml +0 -91
  144. data/ext/libsass/docs/README.md +0 -20
  145. data/ext/libsass/docs/api-context-example.md +0 -45
  146. data/ext/libsass/docs/api-context-internal.md +0 -163
  147. data/ext/libsass/docs/api-context.md +0 -295
  148. data/ext/libsass/docs/api-doc.md +0 -215
  149. data/ext/libsass/docs/api-function-example.md +0 -67
  150. data/ext/libsass/docs/api-function-internal.md +0 -8
  151. data/ext/libsass/docs/api-function.md +0 -74
  152. data/ext/libsass/docs/api-importer-example.md +0 -112
  153. data/ext/libsass/docs/api-importer-internal.md +0 -20
  154. data/ext/libsass/docs/api-importer.md +0 -86
  155. data/ext/libsass/docs/api-value-example.md +0 -55
  156. data/ext/libsass/docs/api-value-internal.md +0 -76
  157. data/ext/libsass/docs/api-value.md +0 -154
  158. data/ext/libsass/docs/build-on-darwin.md +0 -27
  159. data/ext/libsass/docs/build-on-gentoo.md +0 -55
  160. data/ext/libsass/docs/build-on-windows.md +0 -139
  161. data/ext/libsass/docs/build-shared-library.md +0 -35
  162. data/ext/libsass/docs/build-with-autotools.md +0 -78
  163. data/ext/libsass/docs/build-with-makefiles.md +0 -68
  164. data/ext/libsass/docs/build-with-mingw.md +0 -107
  165. data/ext/libsass/docs/build-with-visual-studio.md +0 -90
  166. data/ext/libsass/docs/build.md +0 -97
  167. data/ext/libsass/docs/compatibility-plan.md +0 -48
  168. data/ext/libsass/docs/contributing.md +0 -17
  169. data/ext/libsass/docs/custom-functions-internal.md +0 -122
  170. data/ext/libsass/docs/dev-ast-memory.md +0 -223
  171. data/ext/libsass/docs/implementations.md +0 -56
  172. data/ext/libsass/docs/plugins.md +0 -47
  173. data/ext/libsass/docs/setup-environment.md +0 -68
  174. data/ext/libsass/docs/source-map-internals.md +0 -51
  175. data/ext/libsass/docs/trace.md +0 -26
  176. data/ext/libsass/docs/triage.md +0 -17
  177. data/ext/libsass/docs/unicode.md +0 -39
  178. data/ext/libsass/extconf.rb +0 -6
  179. data/ext/libsass/script/bootstrap +0 -13
  180. data/ext/libsass/script/branding +0 -10
  181. data/ext/libsass/script/ci-build-libsass +0 -134
  182. data/ext/libsass/script/ci-build-plugin +0 -62
  183. data/ext/libsass/script/ci-install-compiler +0 -6
  184. data/ext/libsass/script/ci-install-deps +0 -20
  185. data/ext/libsass/script/ci-report-coverage +0 -42
  186. data/ext/libsass/script/spec +0 -5
  187. data/ext/libsass/script/tap-driver +0 -652
  188. data/ext/libsass/script/tap-runner +0 -1
  189. data/ext/libsass/script/test-leaks.pl +0 -103
  190. data/ext/libsass/src/functions.cpp +0 -2234
  191. data/ext/libsass/src/functions.hpp +0 -198
  192. data/ext/libsass/src/to_c.hpp +0 -39
  193. data/ext/libsass/test/test_node.cpp +0 -94
  194. data/ext/libsass/test/test_paths.cpp +0 -28
  195. data/ext/libsass/test/test_selector_difference.cpp +0 -25
  196. data/ext/libsass/test/test_specificity.cpp +0 -25
  197. data/ext/libsass/test/test_subset_map.cpp +0 -472
  198. data/ext/libsass/test/test_superselector.cpp +0 -69
  199. data/ext/libsass/test/test_unification.cpp +0 -31
  200. data/lib/tasks/libsass.rb +0 -33
@@ -7,16 +7,29 @@
7
7
 
8
8
  SOURCES = \
9
9
  ast.cpp \
10
+ ast_values.cpp \
11
+ ast_supports.cpp \
12
+ ast_sel_cmp.cpp \
13
+ ast_sel_unify.cpp \
14
+ ast_selectors.cpp \
10
15
  node.cpp \
11
16
  context.cpp \
12
17
  constants.cpp \
13
- functions.cpp \
18
+ fn_utils.cpp \
19
+ fn_miscs.cpp \
20
+ fn_maps.cpp \
21
+ fn_lists.cpp \
22
+ fn_colors.cpp \
23
+ fn_numbers.cpp \
24
+ fn_strings.cpp \
25
+ fn_selectors.cpp \
14
26
  color_maps.cpp \
15
27
  environment.cpp \
16
28
  ast_fwd_decl.cpp \
17
29
  bind.cpp \
18
30
  file.cpp \
19
31
  util.cpp \
32
+ util_string.cpp \
20
33
  json.cpp \
21
34
  units.cpp \
22
35
  values.cpp \
@@ -43,7 +56,8 @@ SOURCES = \
43
56
  sass2scss.cpp \
44
57
  backtrace.cpp \
45
58
  operators.cpp \
46
- to_c.cpp \
59
+ ast2c.cpp \
60
+ c2ast.cpp \
47
61
  to_value.cpp \
48
62
  source_map.cpp \
49
63
  subset_map.cpp \
@@ -9,6 +9,7 @@ AC_CONFIG_MACRO_DIR([m4])
9
9
  AC_CONFIG_HEADERS([src/config.h])
10
10
  AC_CONFIG_FILES([include/sass/version.h])
11
11
  AC_CONFIG_AUX_DIR([script])
12
+
12
13
  # These are flags passed to automake
13
14
  # Though they look like gcc flags!
14
15
  AM_INIT_AUTOMAKE([foreign parallel-tests -Wall])
@@ -93,21 +94,16 @@ the --with-sass-spec-dir=<dir> argument.
93
94
  ;;
94
95
  esac
95
96
  AC_SUBST(SASS_SPEC_PATH)
96
-
97
- # TODO: Remove this when automake requirements are 1.12+
98
- AC_MSG_CHECKING([whether we can use TAP mode])
99
- tmp=`$AWK '/TEST_LOG_DRIVER/' $srcdir/GNUmakefile.in`
100
- if test "x$tmp" != "x"; then
101
- use_tap=yes
102
- else
103
- use_tap=no
104
- fi
105
- AC_MSG_RESULT([$use_tap])
106
-
97
+ else
98
+ # we do not really need these paths for non test build
99
+ # but automake may error if we do not define them here
100
+ SASS_SPEC_PATH=sass-spec
101
+ SASS_SASSC_PATH=sassc
102
+ AC_SUBST(SASS_SPEC_PATH)
103
+ AC_SUBST(SASS_SASSC_PATH)
107
104
  fi
108
105
 
109
106
  AM_CONDITIONAL(ENABLE_TESTS, test "x$enable_tests" = "xyes")
110
- AM_CONDITIONAL(USE_TAP, test "x$use_tap" = "xyes")
111
107
 
112
108
  AC_ARG_ENABLE([coverage],
113
109
  [AS_HELP_STRING([--enable-coverage],
@@ -1,6 +1,7 @@
1
1
  #ifndef SASS_BASE_H
2
2
  #define SASS_BASE_H
3
3
 
4
+ // #define DEBUG
4
5
  // #define DEBUG_SHARED_PTR
5
6
 
6
7
  #ifdef _MSC_VER
@@ -43,7 +43,7 @@ ADDAPI struct Sass_Compiler* ADDCALL sass_make_file_compiler (struct Sass_File_C
43
43
  ADDAPI struct Sass_Compiler* ADDCALL sass_make_data_compiler (struct Sass_Data_Context* data_ctx);
44
44
 
45
45
  // Execute the different compilation steps individually
46
- // Usefull if you only want to query the included files
46
+ // Useful if you only want to query the included files
47
47
  ADDAPI int ADDCALL sass_compiler_parse(struct Sass_Compiler* compiler);
48
48
  ADDAPI int ADDCALL sass_compiler_execute(struct Sass_Compiler* compiler);
49
49
 
@@ -13,11 +13,7 @@ AM_CFLAGS = $(AM_COPT)
13
13
  AM_CXXFLAGS = $(AM_COPT)
14
14
  AM_LDFLAGS = $(AM_COPT) $(AM_COVLDFLAGS)
15
15
 
16
- if COMPILER_IS_MINGW32
17
- AM_CXXFLAGS += -std=gnu++0x
18
- else
19
- AM_CXXFLAGS += -std=c++0x
20
- endif
16
+ AM_CXXFLAGS += -std=c++11
21
17
 
22
18
  EXTRA_DIST = \
23
19
  COPYING \
@@ -19,1725 +19,678 @@ namespace Sass {
19
19
 
20
20
  static Null sass_null(ParserState("null"));
21
21
 
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;
27
- }
28
- // execute last
29
- return f(this);
30
- }
31
-
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);
40
- }
41
-
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);
50
- }
51
-
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);
59
- }
60
-
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;
66
- }
67
-
68
- bool Supports_Negation::needs_parens(Supports_Condition_Obj cond) const {
69
- return Cast<Supports_Negation>(cond) ||
70
- Cast<Supports_Operator>(cond);
71
- }
72
-
73
- void str_rtrim(std::string& str, const std::string& delimiters = " \f\n\r\t\v")
74
- {
75
- str.erase( str.find_last_not_of( delimiters ) + 1 );
76
- }
77
-
78
- void String_Constant::rtrim()
79
- {
80
- str_rtrim(value_);
81
- }
82
-
83
- void String_Schema::rtrim()
84
- {
85
- if (!empty()) {
86
- if (String_Ptr str = Cast<String>(last())) str->rtrim();
87
- }
88
- }
89
-
90
- void Argument::set_delayed(bool delayed)
91
- {
92
- if (value_) value_->set_delayed(delayed);
93
- is_delayed(delayed);
94
- }
95
-
96
- void Arguments::set_delayed(bool delayed)
97
- {
98
- for (Argument_Obj arg : elements()) {
99
- if (arg) arg->set_delayed(delayed);
100
- }
101
- is_delayed(delayed);
102
- }
103
-
104
-
105
- bool At_Root_Query::exclude(std::string str)
106
- {
107
- bool with = feature() && unquote(feature()->to_string()).compare("with") == 0;
108
- List_Ptr l = static_cast<List_Ptr>(value().ptr());
109
- std::string v;
110
-
111
- if (with)
112
- {
113
- if (!l || l->length() == 0) return str.compare("rule") != 0;
114
- for (size_t i = 0, L = l->length(); i < L; ++i)
115
- {
116
- v = unquote((*l)[i]->to_string());
117
- if (v.compare("all") == 0 || v == str) return false;
118
- }
119
- return true;
120
- }
121
- else
122
- {
123
- if (!l || !l->length()) return str.compare("rule") == 0;
124
- for (size_t i = 0, L = l->length(); i < L; ++i)
125
- {
126
- v = unquote((*l)[i]->to_string());
127
- if (v.compare("all") == 0 || v == str) return true;
128
- }
129
- return false;
130
- }
131
- }
22
+ const char* sass_op_to_name(enum Sass_OP op) {
23
+ switch (op) {
24
+ case AND: return "and";
25
+ case OR: return "or";
26
+ case EQ: return "eq";
27
+ case NEQ: return "neq";
28
+ case GT: return "gt";
29
+ case GTE: return "gte";
30
+ case LT: return "lt";
31
+ case LTE: return "lte";
32
+ case ADD: return "plus";
33
+ case SUB: return "minus";
34
+ case MUL: return "times";
35
+ case DIV: return "div";
36
+ case MOD: return "mod";
37
+ // this is only used internally!
38
+ case NUM_OPS: return "[OPS]";
39
+ default: return "invalid";
40
+ }
41
+ }
42
+
43
+ const char* sass_op_separator(enum Sass_OP op) {
44
+ switch (op) {
45
+ case AND: return "&&";
46
+ case OR: return "||";
47
+ case EQ: return "==";
48
+ case NEQ: return "!=";
49
+ case GT: return ">";
50
+ case GTE: return ">=";
51
+ case LT: return "<";
52
+ case LTE: return "<=";
53
+ case ADD: return "+";
54
+ case SUB: return "-";
55
+ case MUL: return "*";
56
+ case DIV: return "/";
57
+ case MOD: return "%";
58
+ // this is only used internally!
59
+ case NUM_OPS: return "[OPS]";
60
+ default: return "invalid";
61
+ }
62
+ }
63
+
64
+ /////////////////////////////////////////////////////////////////////////
65
+ /////////////////////////////////////////////////////////////////////////
132
66
 
133
67
  void AST_Node::update_pstate(const ParserState& pstate)
134
68
  {
135
69
  pstate_.offset += pstate - pstate_ + pstate.offset;
136
70
  }
137
71
 
138
- bool Simple_Selector::is_ns_eq(const Simple_Selector& r) const
139
- {
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;
150
- }
151
-
152
- bool Compound_Selector::operator< (const Compound_Selector& rhs) const
153
- {
154
- size_t L = std::min(length(), rhs.length());
155
- for (size_t i = 0; i < L; ++i)
156
- {
157
- Simple_Selector_Obj l = (*this)[i];
158
- Simple_Selector_Obj r = rhs[i];
159
- if (!l && !r) return false;
160
- else if (!r) return false;
161
- else if (!l) return true;
162
- else if (*l != *r)
163
- { return *l < *r; }
164
- }
165
- // just compare the length now
166
- return length() < rhs.length();
167
- }
168
-
169
- bool Compound_Selector::has_parent_ref() const
170
- {
171
- for (Simple_Selector_Obj s : *this) {
172
- if (s && s->has_parent_ref()) return true;
173
- }
174
- return false;
175
- }
176
-
177
- bool Compound_Selector::has_real_parent_ref() const
178
- {
179
- for (Simple_Selector_Obj s : *this) {
180
- if (s && s->has_real_parent_ref()) return true;
181
- }
182
- return false;
183
- }
184
-
185
- bool Complex_Selector::has_parent_ref() const
186
- {
187
- return (head() && head()->has_parent_ref()) ||
188
- (tail() && tail()->has_parent_ref());
189
- }
190
-
191
- bool Complex_Selector::has_real_parent_ref() const
192
- {
193
- return (head() && head()->has_real_parent_ref()) ||
194
- (tail() && tail()->has_real_parent_ref());
195
- }
196
-
197
- bool Complex_Selector::operator< (const Complex_Selector& rhs) const
198
- {
199
- // const iterators for tails
200
- Complex_Selector_Ptr_Const l = this;
201
- Complex_Selector_Ptr_Const r = &rhs;
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();
206
- // process all tails
207
- while (true)
208
- {
209
- #ifdef DEBUG
210
- // skip empty ancestor first
211
- if (l && l->is_empty_ancestor())
212
- {
213
- l_h = NULL;
214
- l = l->tail();
215
- if(l) l_h = l->head();
216
- continue;
217
- }
218
- // skip empty ancestor first
219
- if (r && r->is_empty_ancestor())
220
- {
221
- r_h = NULL;
222
- r = r->tail();
223
- if (r) r_h = r->head();
224
- continue;
225
- }
226
- #endif
227
- // check for valid selectors
228
- if (!l) return !!r;
229
- if (!r) return false;
230
- // both are null
231
- else if (!l_h && !r_h)
232
- {
233
- // check combinator after heads
234
- if (l->combinator() != r->combinator())
235
- { return l->combinator() < r->combinator(); }
236
- // advance to next tails
237
- l = l->tail();
238
- r = r->tail();
239
- // fetch the next headers
240
- l_h = NULL; r_h = NULL;
241
- if (l) l_h = l->head();
242
- if (r) r_h = r->head();
243
- }
244
- // one side is null
245
- else if (!r_h) return true;
246
- else if (!l_h) return false;
247
- // heads ok and equal
248
- else if (*l_h == *r_h)
249
- {
250
- // check combinator after heads
251
- if (l->combinator() != r->combinator())
252
- { return l->combinator() < r->combinator(); }
253
- // advance to next tails
254
- l = l->tail();
255
- r = r->tail();
256
- // fetch the next headers
257
- l_h = NULL; r_h = NULL;
258
- if (l) l_h = l->head();
259
- if (r) r_h = r->head();
260
- }
261
- // heads are not equal
262
- else return *l_h < *r_h;
263
- }
264
- }
265
-
266
- bool Complex_Selector::operator== (const Complex_Selector& rhs) const
267
- {
268
- // const iterators for tails
269
- Complex_Selector_Ptr_Const l = this;
270
- Complex_Selector_Ptr_Const r = &rhs;
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();
275
- // process all tails
276
- while (true)
277
- {
278
- #ifdef DEBUG
279
- // skip empty ancestor first
280
- if (l && l->is_empty_ancestor())
281
- {
282
- l_h = NULL;
283
- l = l->tail();
284
- if (l) l_h = l->head();
285
- continue;
286
- }
287
- // skip empty ancestor first
288
- if (r && r->is_empty_ancestor())
289
- {
290
- r_h = NULL;
291
- r = r->tail();
292
- if (r) r_h = r->head();
293
- continue;
294
- }
295
- #endif
296
- // check the pointers
297
- if (!r) return !l;
298
- if (!l) return !r;
299
- // both are null
300
- if (!l_h && !r_h)
301
- {
302
- // check combinator after heads
303
- if (l->combinator() != r->combinator())
304
- { return l->combinator() < r->combinator(); }
305
- // advance to next tails
306
- l = l->tail();
307
- r = r->tail();
308
- // fetch the next heads
309
- l_h = NULL; r_h = NULL;
310
- if (l) l_h = l->head();
311
- if (r) r_h = r->head();
312
- }
313
- // equals if other head is empty
314
- else if ((!l_h && !r_h) ||
315
- (!l_h && r_h->empty()) ||
316
- (!r_h && l_h->empty()) ||
317
- (l_h && r_h && *l_h == *r_h))
318
- {
319
- // check combinator after heads
320
- if (l->combinator() != r->combinator())
321
- { return l->combinator() == r->combinator(); }
322
- // advance to next tails
323
- l = l->tail();
324
- r = r->tail();
325
- // fetch the next heads
326
- l_h = NULL; r_h = NULL;
327
- if (l) l_h = l->head();
328
- if (r) r_h = r->head();
329
- }
330
- // abort
331
- else break;
332
- }
333
- // unreachable
334
- return false;
335
- }
336
-
337
- Compound_Selector_Ptr Compound_Selector::unify_with(Compound_Selector_Ptr rhs)
338
- {
339
- if (empty()) return rhs;
340
- Compound_Selector_Obj unified = SASS_MEMORY_COPY(rhs);
341
- for (size_t i = 0, L = length(); i < L; ++i)
342
- {
343
- if (unified.isNull()) break;
344
- unified = at(i)->unify_with(unified);
345
- }
346
- return unified.detach();
347
- }
348
-
349
- bool Complex_Selector::operator== (const Selector& rhs) const
350
- {
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;
355
- throw std::runtime_error("invalid selector base classes to compare");
356
- }
357
-
358
-
359
- bool Complex_Selector::operator< (const Selector& rhs) const
360
- {
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;
401
- throw std::runtime_error("invalid selector base classes to compare");
402
- }
403
-
404
- bool Simple_Selector::operator== (const Selector& rhs) const
405
- {
406
- if (Simple_Selector_Ptr_Const sp = Cast<Simple_Selector>(&rhs)) return *this == *sp;
407
- return false;
408
- }
409
-
410
- bool Simple_Selector::operator< (const Selector& rhs) const
411
- {
412
- if (Simple_Selector_Ptr_Const sp = Cast<Simple_Selector>(&rhs)) return *this < *sp;
413
- return false;
414
- }
415
-
416
- bool Simple_Selector::operator== (const Simple_Selector& rhs) const
417
- {
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; }
423
- else if (name_ == rhs.name_)
424
- { return is_ns_eq(rhs); }
425
- else return false;
426
- }
427
-
428
- bool Simple_Selector::operator< (const Simple_Selector& rhs) const
429
- {
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))
436
- { return name_ < rhs.name_; }
437
- return ns_ < rhs.ns_;
438
- }
439
-
440
- bool Selector_List::operator== (const Selector& rhs) const
441
- {
442
- // solve the double dispatch problem by using RTTI information via dynamic cast
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; }
446
- // no compare method
447
- return this == &rhs;
448
- }
449
-
450
- // Selector lists can be compared to comma lists
451
- bool Selector_List::operator== (const Expression& rhs) const
452
- {
453
- // solve the double dispatch problem by using RTTI information via dynamic cast
454
- if (List_Ptr_Const ls = Cast<List>(&rhs)) { return *ls == *this; }
455
- if (Selector_Ptr_Const ls = Cast<Selector>(&rhs)) { return *this == *ls; }
456
- // compare invalid (maybe we should error?)
457
- return false;
458
- }
459
-
460
- bool Selector_List::operator== (const Selector_List& rhs) const
461
- {
462
- // for array access
463
- size_t i = 0, n = 0;
464
- size_t iL = length();
465
- size_t nL = rhs.length();
466
- // create temporary vectors and sort them
467
- std::vector<Complex_Selector_Obj> l_lst = this->elements();
468
- std::vector<Complex_Selector_Obj> r_lst = rhs.elements();
469
- std::sort(l_lst.begin(), l_lst.end(), OrderNodes());
470
- std::sort(r_lst.begin(), r_lst.end(), OrderNodes());
471
- // process loop
472
- while (true)
473
- {
474
- // first check for valid index
475
- if (i == iL) return iL == nL;
476
- else if (n == nL) return iL == nL;
477
- // the access the vector items
478
- Complex_Selector_Obj l = l_lst[i];
479
- Complex_Selector_Obj r = r_lst[n];
480
- // skip nulls
481
- if (!l) ++i;
482
- else if (!r) ++n;
483
- // do the check
484
- else if (*l != *r)
485
- { return false; }
486
- // advance
487
- ++i; ++n;
488
- }
489
- // there is no break?!
490
- }
491
-
492
- bool Selector_List::operator< (const Selector& rhs) const
493
- {
494
- if (Selector_List_Ptr_Const sp = Cast<Selector_List>(&rhs)) return *this < *sp;
495
- return false;
496
- }
497
-
498
- bool Selector_List::operator< (const Selector_List& rhs) const
499
- {
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;
504
- }
505
- return false;
506
- }
507
-
508
- Compound_Selector_Ptr Simple_Selector::unify_with(Compound_Selector_Ptr rhs)
509
- {
510
- for (size_t i = 0, L = rhs->length(); i < L; ++i)
511
- { if (to_string() == rhs->at(i)->to_string()) return rhs; }
512
-
513
- // check for pseudo elements because they are always last
514
- size_t i, L;
515
- bool found = false;
516
- if (typeid(*this) == typeid(Pseudo_Selector) || typeid(*this) == typeid(Wrapped_Selector) || typeid(*this) == typeid(Attribute_Selector))
517
- {
518
- for (i = 0, L = rhs->length(); i < L; ++i)
519
- {
520
- if ((Cast<Pseudo_Selector>((*rhs)[i]) || Cast<Wrapped_Selector>((*rhs)[i]) || Cast<Attribute_Selector>((*rhs)[i])) && (*rhs)[L-1]->is_pseudo_element())
521
- { found = true; break; }
522
- }
523
- }
524
- else
525
- {
526
- for (i = 0, L = rhs->length(); i < L; ++i)
527
- {
528
- if (Cast<Pseudo_Selector>((*rhs)[i]) || Cast<Wrapped_Selector>((*rhs)[i]) || Cast<Attribute_Selector>((*rhs)[i]))
529
- { found = true; break; }
530
- }
531
- }
532
- if (!found)
533
- {
534
- rhs->append(this);
535
- } else {
536
- rhs->elements().insert(rhs->elements().begin() + i, this);
537
- }
538
- return rhs;
539
- }
540
-
541
- Simple_Selector_Ptr Element_Selector::unify_with(Simple_Selector_Ptr rhs)
542
- {
543
- // check if ns can be extended
544
- // true for no ns or universal
545
- if (has_universal_ns())
546
- {
547
- // but dont extend with universal
548
- // true for valid ns and universal
549
- if (!rhs->is_universal_ns())
550
- {
551
- // overwrite the name if star is given as name
552
- if (this->name() == "*") { this->name(rhs->name()); }
553
- // now overwrite the namespace name and flag
554
- this->ns(rhs->ns()); this->has_ns(rhs->has_ns());
555
- // return copy
556
- return this;
557
- }
558
- }
559
- // namespace may changed, check the name now
560
- // overwrite star (but not with another star)
561
- if (name() == "*" && rhs->name() != "*")
562
- {
563
- // simply set the new name
564
- this->name(rhs->name());
565
- // return copy
566
- return this;
567
- }
568
- // return original
569
- return this;
570
- }
571
-
572
- Compound_Selector_Ptr Element_Selector::unify_with(Compound_Selector_Ptr rhs)
573
- {
574
- // TODO: handle namespaces
575
-
576
- // if the rhs is empty, just return a copy of this
577
- if (rhs->length() == 0) {
578
- rhs->append(this);
579
- return rhs;
580
- }
581
-
582
- Simple_Selector_Ptr rhs_0 = rhs->at(0);
583
- // otherwise, this is a tag name
584
- if (name() == "*")
585
- {
586
- if (typeid(*rhs_0) == typeid(Element_Selector))
587
- {
588
- // if rhs is universal, just return this tagname + rhs's qualifiers
589
- Element_Selector_Ptr ts = Cast<Element_Selector>(rhs_0);
590
- rhs->at(0) = this->unify_with(ts);
591
- return rhs;
592
- }
593
- else if (Cast<Class_Selector>(rhs_0) || Cast<Id_Selector>(rhs_0)) {
594
- // qualifier is `.class`, so we can prefix with `ns|*.class`
595
- if (has_ns() && !rhs_0->has_ns()) {
596
- if (ns() != "*") rhs->elements().insert(rhs->begin(), this);
597
- }
598
- return rhs;
599
- }
600
-
601
-
602
- return rhs;
603
- }
604
-
605
- if (typeid(*rhs_0) == typeid(Element_Selector))
606
- {
607
- // if rhs is universal, just return this tagname + rhs's qualifiers
608
- if (rhs_0->name() != "*" && rhs_0->ns() != "*" && rhs_0->name() != name()) return 0;
609
- // otherwise create new compound and unify first simple selector
610
- rhs->at(0) = this->unify_with(rhs_0);
611
- return rhs;
612
-
613
- }
614
- // else it's a tag name and a bunch of qualifiers -- just append them
615
- if (name() != "*") rhs->elements().insert(rhs->begin(), this);
616
- return rhs;
617
- }
618
-
619
- Compound_Selector_Ptr Class_Selector::unify_with(Compound_Selector_Ptr rhs)
620
- {
621
- rhs->has_line_break(has_line_break());
622
- return Simple_Selector::unify_with(rhs);
623
- }
624
-
625
- Compound_Selector_Ptr Id_Selector::unify_with(Compound_Selector_Ptr rhs)
626
- {
627
- for (size_t i = 0, L = rhs->length(); i < L; ++i)
628
- {
629
- if (Id_Selector_Ptr sel = Cast<Id_Selector>(rhs->at(i))) {
630
- if (sel->name() != name()) return 0;
631
- }
632
- }
633
- rhs->has_line_break(has_line_break());
634
- return Simple_Selector::unify_with(rhs);
635
- }
636
-
637
- Compound_Selector_Ptr Pseudo_Selector::unify_with(Compound_Selector_Ptr rhs)
638
- {
639
- if (is_pseudo_element())
640
- {
641
- for (size_t i = 0, L = rhs->length(); i < L; ++i)
642
- {
643
- if (Pseudo_Selector_Ptr sel = Cast<Pseudo_Selector>(rhs->at(i))) {
644
- if (sel->is_pseudo_element() && sel->name() != name()) return 0;
645
- }
646
- }
647
- }
648
- return Simple_Selector::unify_with(rhs);
649
- }
650
-
651
- bool Attribute_Selector::operator< (const Attribute_Selector& rhs) const
652
- {
653
- if (is_ns_eq(rhs)) {
654
- if (name() == rhs.name()) {
655
- if (matcher() == rhs.matcher()) {
656
- bool no_lhs_val = value().isNull();
657
- bool no_rhs_val = rhs.value().isNull();
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
662
- } else { return matcher() < rhs.matcher(); }
663
- } else { return name() < rhs.name(); }
664
- } else { return ns() < rhs.ns(); }
665
- }
666
-
667
- bool Attribute_Selector::operator< (const Simple_Selector& rhs) const
668
- {
669
- if (Attribute_Selector_Ptr_Const w = Cast<Attribute_Selector>(&rhs))
670
- {
671
- return *this < *w;
672
- }
673
- if (is_ns_eq(rhs))
674
- { return name() < rhs.name(); }
675
- return ns() < rhs.ns();
676
- }
677
-
678
- bool Attribute_Selector::operator== (const Attribute_Selector& rhs) const
679
- {
680
- // get optional value state
681
- bool no_lhs_val = value().isNull();
682
- bool no_rhs_val = rhs.value().isNull();
683
- // both are null, therefore equal
684
- if (no_lhs_val && no_rhs_val) {
685
- return (name() == rhs.name())
686
- && (matcher() == rhs.matcher())
687
- && (is_ns_eq(rhs));
688
- }
689
- // both are defined, evaluate
690
- if (no_lhs_val == no_rhs_val) {
691
- return (name() == rhs.name())
692
- && (matcher() == rhs.matcher())
693
- && (is_ns_eq(rhs))
694
- && (*value() == *rhs.value());
695
- }
696
- // not equal
697
- return false;
698
-
699
- }
700
-
701
- bool Attribute_Selector::operator== (const Simple_Selector& rhs) const
702
- {
703
- if (Attribute_Selector_Ptr_Const w = Cast<Attribute_Selector>(&rhs))
704
- {
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;
743
- }
744
- return false;
745
- }
746
-
747
- bool Pseudo_Selector::operator== (const Pseudo_Selector& rhs) const
748
- {
749
- if (is_ns_eq(rhs) && name() == rhs.name())
750
- {
751
- String_Obj lhs_ex = expression();
752
- String_Obj rhs_ex = rhs.expression();
753
- if (rhs_ex && lhs_ex) return *lhs_ex == *rhs_ex;
754
- else return lhs_ex.ptr() == rhs_ex.ptr();
755
- }
756
- else return false;
757
- }
758
-
759
- bool Pseudo_Selector::operator== (const Simple_Selector& rhs) const
760
- {
761
- if (Pseudo_Selector_Ptr_Const w = Cast<Pseudo_Selector>(&rhs))
762
- {
763
- return *this == *w;
764
- }
765
- return is_ns_eq(rhs) &&
766
- name() == rhs.name();
767
- }
768
-
769
- bool Pseudo_Selector::operator< (const Pseudo_Selector& rhs) const
770
- {
771
- if (is_ns_eq(rhs) && name() == rhs.name())
772
- {
773
- String_Obj lhs_ex = expression();
774
- String_Obj rhs_ex = rhs.expression();
775
- if (rhs_ex && lhs_ex) return *lhs_ex < *rhs_ex;
776
- else return lhs_ex.ptr() < rhs_ex.ptr();
777
- }
778
- if (is_ns_eq(rhs))
779
- { return name() < rhs.name(); }
780
- return ns() < rhs.ns();
781
- }
782
-
783
- bool Pseudo_Selector::operator< (const Simple_Selector& rhs) const
784
- {
785
- if (Pseudo_Selector_Ptr_Const w = Cast<Pseudo_Selector>(&rhs))
786
- {
787
- return *this < *w;
788
- }
789
- if (is_ns_eq(rhs))
790
- { return name() < rhs.name(); }
791
- return ns() < rhs.ns();
792
- }
793
-
794
- bool Wrapped_Selector::operator== (const Wrapped_Selector& rhs) const
795
- {
796
- if (is_ns_eq(rhs) && name() == rhs.name())
797
- { return *(selector()) == *(rhs.selector()); }
798
- else return false;
799
- }
800
-
801
- bool Wrapped_Selector::operator== (const Simple_Selector& rhs) const
802
- {
803
- if (Wrapped_Selector_Ptr_Const w = Cast<Wrapped_Selector>(&rhs))
804
- {
805
- return *this == *w;
806
- }
807
- return is_ns_eq(rhs) &&
808
- name() == rhs.name();
809
- }
810
-
811
- bool Wrapped_Selector::operator< (const Wrapped_Selector& rhs) const
812
- {
813
- if (is_ns_eq(rhs) && name() == rhs.name())
814
- { return *(selector()) < *(rhs.selector()); }
815
- if (is_ns_eq(rhs))
816
- { return name() < rhs.name(); }
817
- return ns() < rhs.ns();
818
- }
819
-
820
- bool Wrapped_Selector::operator< (const Simple_Selector& rhs) const
821
- {
822
- if (Wrapped_Selector_Ptr_Const w = Cast<Wrapped_Selector>(&rhs))
823
- {
824
- return *this < *w;
825
- }
826
- if (is_ns_eq(rhs))
827
- { return name() < rhs.name(); }
828
- return ns() < rhs.ns();
829
- }
830
-
831
- bool Wrapped_Selector::is_superselector_of(Wrapped_Selector_Obj sub)
832
- {
833
- if (this->name() != sub->name()) return false;
834
- if (this->name() == ":current") return false;
835
- if (Selector_List_Obj rhs_list = Cast<Selector_List>(sub->selector())) {
836
- if (Selector_List_Obj lhs_list = Cast<Selector_List>(selector())) {
837
- return lhs_list->is_superselector_of(rhs_list);
838
- }
839
- }
840
- coreError("is_superselector expected a Selector_List", sub->pstate());
841
- return false;
842
- }
843
-
844
- bool Compound_Selector::is_superselector_of(Selector_List_Obj rhs, std::string wrapped)
845
- {
846
- for (Complex_Selector_Obj item : rhs->elements()) {
847
- if (is_superselector_of(item, wrapped)) return true;
848
- }
849
- return false;
850
- }
851
-
852
- bool Compound_Selector::is_superselector_of(Complex_Selector_Obj rhs, std::string wrapped)
853
- {
854
- if (rhs->head()) return is_superselector_of(rhs->head(), wrapped);
855
- return false;
856
- }
857
-
858
- bool Compound_Selector::is_superselector_of(Compound_Selector_Obj rhs, std::string wrapping)
859
- {
860
- Compound_Selector_Ptr lhs = this;
861
- Simple_Selector_Ptr lbase = lhs->base();
862
- Simple_Selector_Ptr rbase = rhs->base();
863
-
864
- // Check if pseudo-elements are the same between the selectors
865
-
866
- std::set<std::string> lpsuedoset, rpsuedoset;
867
- for (size_t i = 0, L = length(); i < L; ++i)
868
- {
869
- if ((*this)[i]->is_pseudo_element()) {
870
- std::string pseudo((*this)[i]->to_string());
871
- pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
872
- lpsuedoset.insert(pseudo);
873
- }
874
- }
875
- for (size_t i = 0, L = rhs->length(); i < L; ++i)
876
- {
877
- if ((*rhs)[i]->is_pseudo_element()) {
878
- std::string pseudo((*rhs)[i]->to_string());
879
- pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
880
- rpsuedoset.insert(pseudo);
881
- }
882
- }
883
- if (lpsuedoset != rpsuedoset) {
884
- return false;
885
- }
886
-
887
- // would like to replace this without stringification
888
- // https://github.com/sass/sass/issues/2229
889
- // SimpleSelectorSet lset, rset;
890
- std::set<std::string> lset, rset;
891
-
892
- if (lbase && rbase)
893
- {
894
- if (lbase->to_string() == rbase->to_string()) {
895
- for (size_t i = 1, L = length(); i < L; ++i)
896
- { lset.insert((*this)[i]->to_string()); }
897
- for (size_t i = 1, L = rhs->length(); i < L; ++i)
898
- { rset.insert((*rhs)[i]->to_string()); }
899
- return includes(rset.begin(), rset.end(), lset.begin(), lset.end());
900
- }
901
- return false;
902
- }
903
-
904
- for (size_t i = 0, iL = length(); i < iL; ++i)
905
- {
906
- Selector_Obj wlhs = (*this)[i];
907
- // very special case for wrapped matches selector
908
- if (Wrapped_Selector_Obj wrapped = Cast<Wrapped_Selector>(wlhs)) {
909
- if (wrapped->name() == ":not") {
910
- if (Selector_List_Obj not_list = Cast<Selector_List>(wrapped->selector())) {
911
- if (not_list->is_superselector_of(rhs, wrapped->name())) return false;
912
- } else {
913
- throw std::runtime_error("wrapped not selector is not a list");
914
- }
915
- }
916
- if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") {
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)) {
920
- if (!wrapping.empty() && wrapping != wrapped->name()) return false;
921
- if (wrapping.empty() || wrapping != wrapped->name()) {;
922
- if (list->is_superselector_of(comp, wrapped->name())) return true;
923
- }
924
- }
925
- }
926
- }
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)) {
930
- if (wrapped->name() == wrapped_r->name()) {
931
- if (wrapped->is_superselector_of(wrapped_r)) {
932
- continue;
933
- }}
934
- }
935
- }
936
- // match from here on as strings
937
- lset.insert(wlhs->to_string());
938
- }
939
-
940
- for (size_t n = 0, nL = rhs->length(); n < nL; ++n)
941
- {
942
- Selector_Obj r = (*rhs)[n];
943
- if (Wrapped_Selector_Obj wrapped = Cast<Wrapped_Selector>(r)) {
944
- if (wrapped->name() == ":not") {
945
- if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
946
- ls->remove_parent_selectors();
947
- if (is_superselector_of(ls, wrapped->name())) return false;
948
- }
949
- }
950
- if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") {
951
- if (!wrapping.empty()) {
952
- if (wrapping != wrapped->name()) return false;
953
- }
954
- if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
955
- ls->remove_parent_selectors();
956
- return (is_superselector_of(ls, wrapped->name()));
957
- }
958
- }
959
- }
960
- rset.insert(r->to_string());
961
- }
962
-
963
- //for (auto l : lset) { cerr << "l: " << l << endl; }
964
- //for (auto r : rset) { cerr << "r: " << r << endl; }
965
-
966
- if (lset.empty()) return true;
967
- // return true if rset contains all the elements of lset
968
- return includes(rset.begin(), rset.end(), lset.begin(), lset.end());
969
-
970
- }
971
-
972
- // create complex selector (ancestor of) from compound selector
973
- Complex_Selector_Obj Compound_Selector::to_complex()
974
- {
975
- // create an intermediate complex selector
976
- return SASS_MEMORY_NEW(Complex_Selector,
977
- pstate(),
978
- Complex_Selector::ANCESTOR_OF,
979
- this,
980
- 0);
981
- }
982
-
983
- Selector_List_Ptr Complex_Selector::unify_with(Complex_Selector_Ptr other)
984
- {
985
-
986
- // get last tails (on the right side)
987
- Complex_Selector_Obj l_last = this->last();
988
- Complex_Selector_Obj r_last = other->last();
989
-
990
- // check valid pointers (assertion)
991
- SASS_ASSERT(l_last, "lhs is null");
992
- SASS_ASSERT(r_last, "rhs is null");
993
-
994
- // Not sure about this check, but closest way I could check
995
- // was to see if this is a ruby 'SimpleSequence' equivalent.
996
- // It seems to do the job correctly as some specs react to this
997
- if (l_last->combinator() != Combinator::ANCESTOR_OF) return 0;
998
- if (r_last->combinator() != Combinator::ANCESTOR_OF ) return 0;
999
-
1000
- // get the headers for the last tails
1001
- Compound_Selector_Obj l_last_head = l_last->head();
1002
- Compound_Selector_Obj r_last_head = r_last->head();
1003
-
1004
- // check valid head pointers (assertion)
1005
- SASS_ASSERT(l_last_head, "lhs head is null");
1006
- SASS_ASSERT(r_last_head, "rhs head is null");
1007
-
1008
- // get the unification of the last compound selectors
1009
- Compound_Selector_Obj unified = r_last_head->unify_with(l_last_head);
1010
-
1011
- // abort if we could not unify heads
1012
- if (unified == 0) return 0;
1013
-
1014
- // check for universal (star: `*`) selector
1015
- bool is_universal = l_last_head->is_universal() ||
1016
- r_last_head->is_universal();
1017
-
1018
- if (is_universal)
1019
- {
1020
- // move the head
1021
- l_last->head(0);
1022
- r_last->head(unified);
1023
- }
1024
-
1025
- // create nodes from both selectors
1026
- Node lhsNode = complexSelectorToNode(this);
1027
- Node rhsNode = complexSelectorToNode(other);
1028
-
1029
- // overwrite universal base
1030
- if (!is_universal)
1031
- {
1032
- // create some temporaries to convert to node
1033
- Complex_Selector_Obj fake = unified->to_complex();
1034
- Node unified_node = complexSelectorToNode(fake);
1035
- // add to permutate the list?
1036
- rhsNode.plus(unified_node);
1037
- }
1038
-
1039
- // do some magic we inherit from node and extend
1040
- Node node = subweave(lhsNode, rhsNode);
1041
- Selector_List_Obj result = SASS_MEMORY_NEW(Selector_List, pstate());
1042
- NodeDequePtr col = node.collection(); // move from collection to list
1043
- for (NodeDeque::iterator it = col->begin(), end = col->end(); it != end; it++)
1044
- { result->append(nodeToComplexSelector(Node::naiveTrim(*it))); }
1045
-
1046
- // only return if list has some entries
1047
- return result->length() ? result.detach() : 0;
1048
-
1049
- }
1050
-
1051
- bool Compound_Selector::operator== (const Compound_Selector& rhs) const
1052
- {
1053
- // for array access
1054
- size_t i = 0, n = 0;
1055
- size_t iL = length();
1056
- size_t nL = rhs.length();
1057
- // create temporary vectors and sort them
1058
- std::vector<Simple_Selector_Obj> l_lst = this->elements();
1059
- std::vector<Simple_Selector_Obj> r_lst = rhs.elements();
1060
- std::sort(l_lst.begin(), l_lst.end(), OrderNodes());
1061
- std::sort(r_lst.begin(), r_lst.end(), OrderNodes());
1062
- // process loop
1063
- while (true)
1064
- {
1065
- // first check for valid index
1066
- if (i == iL) return iL == nL;
1067
- else if (n == nL) return iL == nL;
1068
- // the access the vector items
1069
- Simple_Selector_Obj l = l_lst[i];
1070
- Simple_Selector_Obj r = r_lst[n];
1071
- // skip nulls
1072
- if (!l) ++i;
1073
- if (!r) ++n;
1074
- // do the check now
1075
- else if (*l != *r)
1076
- { return false; }
1077
- // advance now
1078
- ++i; ++n;
1079
- }
1080
- // there is no break?!
1081
- }
1082
-
1083
- bool Complex_Selector::is_superselector_of(Compound_Selector_Obj rhs, std::string wrapping)
1084
- {
1085
- return last()->head() && last()->head()->is_superselector_of(rhs, wrapping);
1086
- }
1087
-
1088
- bool Complex_Selector::is_superselector_of(Complex_Selector_Obj rhs, std::string wrapping)
1089
- {
1090
- Complex_Selector_Ptr lhs = this;
1091
- // check for selectors with leading or trailing combinators
1092
- if (!lhs->head() || !rhs->head())
1093
- { return false; }
1094
- Complex_Selector_Obj l_innermost = lhs->innermost();
1095
- if (l_innermost->combinator() != Complex_Selector::ANCESTOR_OF)
1096
- { return false; }
1097
- Complex_Selector_Obj r_innermost = rhs->innermost();
1098
- if (r_innermost->combinator() != Complex_Selector::ANCESTOR_OF)
1099
- { return false; }
1100
- // more complex (i.e., longer) selectors are always more specific
1101
- size_t l_len = lhs->length(), r_len = rhs->length();
1102
- if (l_len > r_len)
1103
- { return false; }
1104
-
1105
- if (l_len == 1)
1106
- { return lhs->head()->is_superselector_of(rhs->last()->head(), wrapping); }
1107
-
1108
- // we have to look one tail deeper, since we cary the
1109
- // combinator around for it (which is important here)
1110
- if (rhs->tail() && lhs->tail() && combinator() != Complex_Selector::ANCESTOR_OF) {
1111
- Complex_Selector_Obj lhs_tail = lhs->tail();
1112
- Complex_Selector_Obj rhs_tail = rhs->tail();
1113
- if (lhs_tail->combinator() != rhs_tail->combinator()) return false;
1114
- if (lhs_tail->head() && !rhs_tail->head()) return false;
1115
- if (!lhs_tail->head() && rhs_tail->head()) return false;
1116
- if (lhs_tail->head() && rhs_tail->head()) {
1117
- if (!lhs_tail->head()->is_superselector_of(rhs_tail->head())) return false;
1118
- }
1119
- }
1120
-
1121
- bool found = false;
1122
- Complex_Selector_Obj marker = rhs;
1123
- for (size_t i = 0, L = rhs->length(); i < L; ++i) {
1124
- if (i == L-1)
1125
- { return false; }
1126
- if (lhs->head() && marker->head() && lhs->head()->is_superselector_of(marker->head(), wrapping))
1127
- { found = true; break; }
1128
- marker = marker->tail();
1129
- }
1130
- if (!found)
1131
- { return false; }
1132
-
1133
- /*
1134
- Hmm, I hope I have the logic right:
1135
-
1136
- if lhs has a combinator:
1137
- if !(marker has a combinator) return false
1138
- if !(lhs.combinator == '~' ? marker.combinator != '>' : lhs.combinator == marker.combinator) return false
1139
- return lhs.tail-without-innermost.is_superselector_of(marker.tail-without-innermost)
1140
- else if marker has a combinator:
1141
- if !(marker.combinator == ">") return false
1142
- return lhs.tail.is_superselector_of(marker.tail)
1143
- else
1144
- return lhs.tail.is_superselector_of(marker.tail)
1145
- */
1146
- if (lhs->combinator() != Complex_Selector::ANCESTOR_OF)
1147
- {
1148
- if (marker->combinator() == Complex_Selector::ANCESTOR_OF)
1149
- { return false; }
1150
- if (!(lhs->combinator() == Complex_Selector::PRECEDES ? marker->combinator() != Complex_Selector::PARENT_OF : lhs->combinator() == marker->combinator()))
1151
- { return false; }
1152
- return lhs->tail()->is_superselector_of(marker->tail());
1153
- }
1154
- else if (marker->combinator() != Complex_Selector::ANCESTOR_OF)
1155
- {
1156
- if (marker->combinator() != Complex_Selector::PARENT_OF)
1157
- { return false; }
1158
- return lhs->tail()->is_superselector_of(marker->tail());
1159
- }
1160
- return lhs->tail()->is_superselector_of(marker->tail());
1161
- }
1162
-
1163
- size_t Complex_Selector::length() const
1164
- {
1165
- // TODO: make this iterative
1166
- if (!tail()) return 1;
1167
- return 1 + tail()->length();
1168
- }
1169
-
1170
- // append another complex selector at the end
1171
- // check if we need to append some headers
1172
- // then we need to check for the combinator
1173
- // only then we can safely set the new tail
1174
- void Complex_Selector::append(Complex_Selector_Obj ss, Backtraces& traces)
1175
- {
1176
-
1177
- Complex_Selector_Obj t = ss->tail();
1178
- Combinator c = ss->combinator();
1179
- String_Obj r = ss->reference();
1180
- Compound_Selector_Obj h = ss->head();
1181
-
1182
- if (ss->has_line_feed()) has_line_feed(true);
1183
- if (ss->has_line_break()) has_line_break(true);
1184
-
1185
- // append old headers
1186
- if (h && h->length()) {
1187
- if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) {
1188
- traces.push_back(Backtrace(pstate()));
1189
- throw Exception::InvalidParent(this, traces, ss);
1190
- } else if (last()->head_ && last()->head_->length()) {
1191
- Compound_Selector_Obj rh = last()->head();
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);
1197
- sqs->name(sqs->name() + (*h)[0]->name());
1198
- sqs->pstate((*h)[0]->pstate());
1199
- (*rh)[rh->length()-1] = sqs;
1200
- rh->pstate(h->pstate());
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);
1204
- sqs->name(sqs->name() + (*h)[0]->name());
1205
- sqs->pstate((*h)[0]->pstate());
1206
- (*rh)[rh->length()-1] = sqs;
1207
- rh->pstate(h->pstate());
1208
- for (i = 1; i < L; ++i) rh->append((*h)[i]);
1209
- } else if (Element_Selector_Ptr ts = Cast<Element_Selector>(rh->last())) {
1210
- Element_Selector_Ptr tss = SASS_MEMORY_COPY(ts);
1211
- tss->name(tss->name() + (*h)[0]->name());
1212
- tss->pstate((*h)[0]->pstate());
1213
- (*rh)[rh->length()-1] = tss;
1214
- rh->pstate(h->pstate());
1215
- for (i = 1; i < L; ++i) rh->append((*h)[i]);
1216
- } else if (Placeholder_Selector_Ptr ps = Cast<Placeholder_Selector>(rh->last())) {
1217
- Placeholder_Selector_Ptr pss = SASS_MEMORY_COPY(ps);
1218
- pss->name(pss->name() + (*h)[0]->name());
1219
- pss->pstate((*h)[0]->pstate());
1220
- (*rh)[rh->length()-1] = pss;
1221
- rh->pstate(h->pstate());
1222
- for (i = 1; i < L; ++i) rh->append((*h)[i]);
1223
- } else {
1224
- last()->head_->concat(h);
1225
- }
1226
- } else {
1227
- last()->head_->concat(h);
1228
- }
1229
- } else if (last()->head_) {
1230
- last()->head_->concat(h);
1231
- }
1232
- } else {
1233
- // std::cerr << "has no or empty head\n";
1234
- }
1235
-
1236
- if (last()) {
1237
- if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) {
1238
- Complex_Selector_Ptr inter = SASS_MEMORY_NEW(Complex_Selector, pstate());
1239
- inter->reference(r);
1240
- inter->combinator(c);
1241
- inter->tail(t);
1242
- last()->tail(inter);
1243
- } else {
1244
- if (last()->combinator() == ANCESTOR_OF) {
1245
- last()->combinator(c);
1246
- last()->reference(r);
1247
- }
1248
- last()->tail(t);
1249
- }
1250
- }
1251
-
1252
- }
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;
1260
- }
1261
-
1262
- Selector_List_Ptr Selector_List::resolve_parent_refs(std::vector<Selector_List_Obj>& pstack, Backtraces& traces, bool implicit_parent)
1263
- {
1264
- if (!this->has_parent_ref()) return this;
1265
- Selector_List_Ptr ss = SASS_MEMORY_NEW(Selector_List, pstate());
1266
- Selector_List_Ptr ps = pstack.back();
1267
- for (size_t pi = 0, pL = ps->length(); pi < pL; ++pi) {
1268
- for (size_t si = 0, sL = this->length(); si < sL; ++si) {
1269
- Selector_List_Obj rv = at(si)->resolve_parent_refs(pstack, traces, implicit_parent);
1270
- ss->concat(rv);
1271
- }
1272
- }
1273
- return ss;
1274
- }
1275
-
1276
- Selector_List_Ptr Complex_Selector::resolve_parent_refs(std::vector<Selector_List_Obj>& pstack, Backtraces& traces, bool implicit_parent)
1277
- {
1278
- Complex_Selector_Obj tail = this->tail();
1279
- Compound_Selector_Obj head = this->head();
1280
- Selector_List_Ptr parents = pstack.back();
1281
-
1282
- if (!this->has_real_parent_ref() && !implicit_parent) {
1283
- Selector_List_Ptr retval = SASS_MEMORY_NEW(Selector_List, pstate());
1284
- retval->append(this);
1285
- return retval;
1286
- }
1287
-
1288
- // first resolve_parent_refs the tail (which may return an expanded list)
1289
- Selector_List_Obj tails = tail ? tail->resolve_parent_refs(pstack, traces, implicit_parent) : 0;
1290
-
1291
- if (head && head->length() > 0) {
1292
-
1293
- Selector_List_Obj retval;
1294
- // we have a parent selector in a simple compound list
1295
- // mix parent complex selector into the compound list
1296
- if (Cast<Parent_Selector>((*head)[0])) {
1297
- retval = SASS_MEMORY_NEW(Selector_List, pstate());
1298
-
1299
- // it turns out that real parent references reach
1300
- // across @at-root rules, which comes unexpected
1301
- if (parents == NULL && head->has_real_parent_ref()) {
1302
- int i = pstack.size() - 1;
1303
- while (!parents && i > -1) {
1304
- parents = pstack.at(i--);
1305
- }
1306
- }
1307
-
1308
- if (parents && parents->length()) {
1309
- if (tails && tails->length() > 0) {
1310
- for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
1311
- for (size_t i = 0, iL = parents->length(); i < iL; ++i) {
1312
- Complex_Selector_Obj t = (*tails)[n];
1313
- Complex_Selector_Obj parent = (*parents)[i];
1314
- Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent);
1315
- Complex_Selector_Obj ss = SASS_MEMORY_CLONE(this);
1316
- ss->tail(t ? SASS_MEMORY_CLONE(t) : NULL);
1317
- Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
1318
- // remove parent selector from sequence
1319
- if (h->length()) {
1320
- h->erase(h->begin());
1321
- ss->head(h);
1322
- } else {
1323
- ss->head(NULL);
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
- // }
1332
- // keep old parser state
1333
- s->pstate(pstate());
1334
- // append new tail
1335
- s->append(ss, traces);
1336
- retval->append(s);
1337
- }
1338
- }
1339
- }
1340
- // have no tails but parents
1341
- // loop above is inside out
1342
- else {
1343
- for (size_t i = 0, iL = parents->length(); i < iL; ++i) {
1344
- Complex_Selector_Obj parent = (*parents)[i];
1345
- Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent);
1346
- Complex_Selector_Obj ss = SASS_MEMORY_CLONE(this);
1347
- // this is only if valid if the parent has no trailing op
1348
- // otherwise we cannot append more simple selectors to head
1349
- if (parent->last()->combinator() != ANCESTOR_OF) {
1350
- traces.push_back(Backtrace(pstate()));
1351
- throw Exception::InvalidParent(parent, traces, ss);
1352
- }
1353
- ss->tail(tail ? SASS_MEMORY_CLONE(tail) : NULL);
1354
- Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
1355
- // remove parent selector from sequence
1356
- if (h->length()) {
1357
- h->erase(h->begin());
1358
- ss->head(h);
1359
- } else {
1360
- ss->head(NULL);
1361
- }
1362
- // \/ IMO ruby sass bug \/
1363
- ss->has_line_feed(false);
1364
- // adjust for parent selector (1 char)
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
- // }
1371
- // keep old parser state
1372
- s->pstate(pstate());
1373
- // append new tail
1374
- s->append(ss, traces);
1375
- retval->append(s);
1376
- }
1377
- }
1378
- }
1379
- // have no parent but some tails
1380
- else {
1381
- if (tails && tails->length() > 0) {
1382
- for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
1383
- Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this);
1384
- cpy->tail(SASS_MEMORY_CLONE(tails->at(n)));
1385
- cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
1386
- for (size_t i = 1, L = this->head()->length(); i < L; ++i)
1387
- cpy->head()->append((*this->head())[i]);
1388
- if (!cpy->head()->length()) cpy->head(0);
1389
- retval->append(cpy->skip_empty_reference());
1390
- }
1391
- }
1392
- // have no parent nor tails
1393
- else {
1394
- Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this);
1395
- cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
1396
- for (size_t i = 1, L = this->head()->length(); i < L; ++i)
1397
- cpy->head()->append((*this->head())[i]);
1398
- if (!cpy->head()->length()) cpy->head(0);
1399
- retval->append(cpy->skip_empty_reference());
1400
- }
1401
- }
1402
- }
1403
- // no parent selector in head
1404
- else {
1405
- retval = this->tails(tails);
1406
- }
1407
-
1408
- for (Simple_Selector_Obj ss : head->elements()) {
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));
1412
- }
1413
- }
1414
- }
1415
-
1416
- return retval.detach();
1417
-
1418
- }
1419
- // has no head
1420
- return this->tails(tails);
1421
- }
1422
-
1423
- Selector_List_Ptr Complex_Selector::tails(Selector_List_Ptr tails)
1424
- {
1425
- Selector_List_Ptr rv = SASS_MEMORY_NEW(Selector_List, pstate_);
1426
- if (tails && tails->length()) {
1427
- for (size_t i = 0, iL = tails->length(); i < iL; ++i) {
1428
- Complex_Selector_Obj pr = SASS_MEMORY_CLONE(this);
1429
- pr->tail(tails->at(i));
1430
- rv->append(pr);
1431
- }
1432
- }
1433
- else {
1434
- rv->append(this);
1435
- }
1436
- return rv;
1437
- }
1438
-
1439
- // return the last tail that is defined
1440
- Complex_Selector_Obj Complex_Selector::first()
1441
- {
1442
- // declare variables used in loop
1443
- Complex_Selector_Obj cur = this;
1444
- Compound_Selector_Obj head;
1445
- // processing loop
1446
- while (cur)
1447
- {
1448
- // get the head
1449
- head = cur->head_;
1450
- // abort (and return) if it is not a parent selector
1451
- if (!head || head->length() != 1 || !Cast<Parent_Selector>((*head)[0])) {
1452
- break;
1453
- }
1454
- // advance to next
1455
- cur = cur->tail_;
1456
- }
1457
- // result
1458
- return cur;
1459
- }
1460
-
1461
- // return the last tail that is defined
1462
- Complex_Selector_Obj Complex_Selector::last()
1463
- {
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;
1472
- }
1473
-
1474
- Complex_Selector::Combinator Complex_Selector::clear_innermost()
1475
- {
1476
- Combinator c;
1477
- if (!tail() || tail()->tail() == 0)
1478
- { c = combinator(); combinator(ANCESTOR_OF); tail(0); }
1479
- else
1480
- { c = tail()->clear_innermost(); }
1481
- return c;
1482
- }
1483
-
1484
- void Complex_Selector::set_innermost(Complex_Selector_Obj val, Combinator c)
1485
- {
1486
- if (!tail())
1487
- { tail(val); combinator(c); }
1488
- else
1489
- { tail()->set_innermost(val, c); }
1490
- }
1491
-
1492
- void Complex_Selector::cloneChildren()
1493
- {
1494
- if (head()) head(SASS_MEMORY_CLONE(head()));
1495
- if (tail()) tail(SASS_MEMORY_CLONE(tail()));
1496
- }
1497
-
1498
- void Compound_Selector::cloneChildren()
72
+ const std::string AST_Node::to_string(Sass_Inspect_Options opt) const
1499
73
  {
1500
- for (size_t i = 0, l = length(); i < l; i++) {
1501
- at(i) = SASS_MEMORY_CLONE(at(i));
1502
- }
74
+ Sass_Output_Options out(opt);
75
+ Emitter emitter(out);
76
+ Inspect i(emitter);
77
+ i.in_declaration = true;
78
+ // ToDo: inspect should be const
79
+ const_cast<AST_Node*>(this)->perform(&i);
80
+ return i.get_buffer();
1503
81
  }
1504
82
 
1505
- void Selector_List::cloneChildren()
83
+ const std::string AST_Node::to_string() const
1506
84
  {
1507
- for (size_t i = 0, l = length(); i < l; i++) {
1508
- at(i) = SASS_MEMORY_CLONE(at(i));
1509
- }
85
+ return to_string({ NESTED, 5 });
1510
86
  }
1511
87
 
1512
- void Wrapped_Selector::cloneChildren()
1513
- {
1514
- selector(SASS_MEMORY_CLONE(selector()));
1515
- }
88
+ /////////////////////////////////////////////////////////////////////////
89
+ /////////////////////////////////////////////////////////////////////////
1516
90
 
1517
- // remove parent selector references
1518
- // basically unwraps parsed selectors
1519
- void Selector_List::remove_parent_selectors()
91
+ Expression_Obj Hashed::at(Expression_Obj k) const
1520
92
  {
1521
- // Check every rhs selector against left hand list
1522
- for(size_t i = 0, L = length(); i < L; ++i) {
1523
- if (!(*this)[i]->head()) continue;
1524
- if ((*this)[i]->head()->is_empty_reference()) {
1525
- // simply move to the next tail if we have "no" combinator
1526
- if ((*this)[i]->combinator() == Complex_Selector::ANCESTOR_OF) {
1527
- if ((*this)[i]->tail()) {
1528
- if ((*this)[i]->has_line_feed()) {
1529
- (*this)[i]->tail()->has_line_feed(true);
1530
- }
1531
- (*this)[i] = (*this)[i]->tail();
1532
- }
1533
- }
1534
- // otherwise remove the first item from head
1535
- else {
1536
- (*this)[i]->head()->erase((*this)[i]->head()->begin());
1537
- }
1538
- }
1539
- }
93
+ if (elements_.count(k))
94
+ { return elements_.at(k); }
95
+ else { return {}; }
1540
96
  }
1541
97
 
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
- }
98
+ /////////////////////////////////////////////////////////////////////////
99
+ /////////////////////////////////////////////////////////////////////////
1564
100
 
101
+ Statement::Statement(ParserState pstate, Type st, size_t t)
102
+ : AST_Node(pstate), statement_type_(st), tabs_(t), group_end_(false)
103
+ { }
104
+ Statement::Statement(const Statement* ptr)
105
+ : AST_Node(ptr),
106
+ statement_type_(ptr->statement_type_),
107
+ tabs_(ptr->tabs_),
108
+ group_end_(ptr->group_end_)
109
+ { }
1565
110
 
1566
- bool Selector_List::has_parent_ref() const
111
+ bool Statement::bubbles()
1567
112
  {
1568
- for (Complex_Selector_Obj s : elements()) {
1569
- if (s && s->has_parent_ref()) return true;
1570
- }
1571
113
  return false;
1572
114
  }
1573
115
 
1574
- bool Selector_List::has_real_parent_ref() const
116
+ bool Statement::has_content()
1575
117
  {
1576
- for (Complex_Selector_Obj s : elements()) {
1577
- if (s && s->has_real_parent_ref()) return true;
1578
- }
1579
- return false;
118
+ return statement_type_ == CONTENT;
1580
119
  }
1581
120
 
1582
- bool Selector_Schema::has_parent_ref() const
121
+ bool Statement::is_invisible() const
1583
122
  {
1584
- if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
1585
- return schema->length() > 0 && Cast<Parent_Selector>(schema->at(0)) != NULL;
1586
- }
1587
123
  return false;
1588
124
  }
1589
125
 
1590
- bool Selector_Schema::has_real_parent_ref() const
126
+ /////////////////////////////////////////////////////////////////////////
127
+ /////////////////////////////////////////////////////////////////////////
128
+
129
+ Block::Block(ParserState pstate, size_t s, bool r)
130
+ : Statement(pstate),
131
+ Vectorized<Statement_Obj>(s),
132
+ is_root_(r)
133
+ { }
134
+ Block::Block(const Block* ptr)
135
+ : Statement(ptr),
136
+ Vectorized<Statement_Obj>(*ptr),
137
+ is_root_(ptr->is_root_)
138
+ { }
139
+
140
+ bool Block::has_content()
1591
141
  {
1592
- if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
1593
- Parent_Selector_Obj p = Cast<Parent_Selector>(schema->at(0));
1594
- return schema->length() > 0 && p && p->is_real_parent_ref();
142
+ for (size_t i = 0, L = elements().size(); i < L; ++i) {
143
+ if (elements()[i]->has_content()) return true;
1595
144
  }
1596
- return false;
145
+ return Statement::has_content();
1597
146
  }
1598
147
 
1599
- void Selector_List::adjust_after_pushing(Complex_Selector_Obj c)
148
+ /////////////////////////////////////////////////////////////////////////
149
+ /////////////////////////////////////////////////////////////////////////
150
+
151
+ Has_Block::Has_Block(ParserState pstate, Block_Obj b)
152
+ : Statement(pstate), block_(b)
153
+ { }
154
+ Has_Block::Has_Block(const Has_Block* ptr)
155
+ : Statement(ptr), block_(ptr->block_)
156
+ { }
157
+
158
+ bool Has_Block::has_content()
1600
159
  {
1601
- // if (c->has_reference()) has_reference(true);
160
+ return (block_ && block_->has_content()) || Statement::has_content();
1602
161
  }
1603
162
 
1604
- // it's a superselector if every selector of the right side
1605
- // list is a superselector of the given left side selector
1606
- bool Complex_Selector::is_superselector_of(Selector_List_Obj sub, std::string wrapping)
1607
- {
1608
- // Check every rhs selector against left hand list
1609
- for(size_t i = 0, L = sub->length(); i < L; ++i) {
1610
- if (!is_superselector_of((*sub)[i], wrapping)) return false;
163
+ /////////////////////////////////////////////////////////////////////////
164
+ /////////////////////////////////////////////////////////////////////////
165
+
166
+ Ruleset::Ruleset(ParserState pstate, Selector_List_Obj s, Block_Obj b)
167
+ : Has_Block(pstate, b), selector_(s), is_root_(false)
168
+ { statement_type(RULESET); }
169
+ Ruleset::Ruleset(const Ruleset* ptr)
170
+ : Has_Block(ptr),
171
+ selector_(ptr->selector_),
172
+ is_root_(ptr->is_root_)
173
+ { statement_type(RULESET); }
174
+
175
+ bool Ruleset::is_invisible() const {
176
+ if (Selector_List* sl = Cast<Selector_List>(selector())) {
177
+ for (size_t i = 0, L = sl->length(); i < L; ++i)
178
+ if (!(*sl)[i]->has_placeholder()) return false;
1611
179
  }
1612
180
  return true;
1613
181
  }
1614
182
 
1615
- // it's a superselector if every selector of the right side
1616
- // list is a superselector of the given left side selector
1617
- bool Selector_List::is_superselector_of(Selector_List_Obj sub, std::string wrapping)
183
+ /////////////////////////////////////////////////////////////////////////
184
+ /////////////////////////////////////////////////////////////////////////
185
+
186
+ Bubble::Bubble(ParserState pstate, Statement_Obj n, Statement_Obj g, size_t t)
187
+ : Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == 0)
188
+ { }
189
+ Bubble::Bubble(const Bubble* ptr)
190
+ : Statement(ptr),
191
+ node_(ptr->node_),
192
+ group_end_(ptr->group_end_)
193
+ { }
194
+
195
+ bool Bubble::bubbles()
1618
196
  {
1619
- // Check every rhs selector against left hand list
1620
- for(size_t i = 0, L = sub->length(); i < L; ++i) {
1621
- if (!is_superselector_of((*sub)[i], wrapping)) return false;
1622
- }
1623
197
  return true;
1624
198
  }
1625
199
 
1626
- // it's a superselector if every selector on the right side
1627
- // is a superselector of any one of the left side selectors
1628
- bool Selector_List::is_superselector_of(Compound_Selector_Obj sub, std::string wrapping)
1629
- {
1630
- // Check every lhs selector against right hand
1631
- for(size_t i = 0, L = length(); i < L; ++i) {
1632
- if ((*this)[i]->is_superselector_of(sub, wrapping)) return true;
200
+ /////////////////////////////////////////////////////////////////////////
201
+ /////////////////////////////////////////////////////////////////////////
202
+
203
+ Trace::Trace(ParserState pstate, std::string n, Block_Obj b, char type)
204
+ : Has_Block(pstate, b), type_(type), name_(n)
205
+ { }
206
+ Trace::Trace(const Trace* ptr)
207
+ : Has_Block(ptr),
208
+ type_(ptr->type_),
209
+ name_(ptr->name_)
210
+ { }
211
+
212
+ /////////////////////////////////////////////////////////////////////////
213
+ /////////////////////////////////////////////////////////////////////////
214
+
215
+ Media_Block::Media_Block(ParserState pstate, List_Obj mqs, Block_Obj b)
216
+ : Has_Block(pstate, b), media_queries_(mqs)
217
+ { statement_type(MEDIA); }
218
+ Media_Block::Media_Block(const Media_Block* ptr)
219
+ : Has_Block(ptr), media_queries_(ptr->media_queries_)
220
+ { statement_type(MEDIA); }
221
+
222
+ bool Media_Block::is_invisible() const {
223
+ for (size_t i = 0, L = block()->length(); i < L; ++i) {
224
+ Statement_Obj stm = block()->at(i);
225
+ if (!stm->is_invisible()) return false;
1633
226
  }
1634
- return false;
227
+ return true;
1635
228
  }
1636
229
 
1637
- // it's a superselector if every selector on the right side
1638
- // is a superselector of any one of the left side selectors
1639
- bool Selector_List::is_superselector_of(Complex_Selector_Obj sub, std::string wrapping)
230
+ bool Media_Block::bubbles()
1640
231
  {
1641
- // Check every lhs selector against right hand
1642
- for(size_t i = 0, L = length(); i < L; ++i) {
1643
- if ((*this)[i]->is_superselector_of(sub)) return true;
1644
- }
1645
- return false;
232
+ return true;
1646
233
  }
1647
234
 
1648
- Selector_List_Ptr Selector_List::unify_with(Selector_List_Ptr rhs) {
1649
- std::vector<Complex_Selector_Obj> unified_complex_selectors;
1650
- // Unify all of children with RHS's children, storing the results in `unified_complex_selectors`
1651
- for (size_t lhs_i = 0, lhs_L = length(); lhs_i < lhs_L; ++lhs_i) {
1652
- Complex_Selector_Obj seq1 = (*this)[lhs_i];
1653
- for(size_t rhs_i = 0, rhs_L = rhs->length(); rhs_i < rhs_L; ++rhs_i) {
1654
- Complex_Selector_Ptr seq2 = rhs->at(rhs_i);
1655
-
1656
- Selector_List_Obj result = seq1->unify_with(seq2);
1657
- if( result ) {
1658
- for(size_t i = 0, L = result->length(); i < L; ++i) {
1659
- unified_complex_selectors.push_back( (*result)[i] );
1660
- }
1661
- }
1662
- }
1663
- }
235
+ /////////////////////////////////////////////////////////////////////////
236
+ /////////////////////////////////////////////////////////////////////////
237
+
238
+ Directive::Directive(ParserState pstate, std::string kwd, Selector_List_Obj sel, Block_Obj b, Expression_Obj val)
239
+ : Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed
240
+ { statement_type(DIRECTIVE); }
241
+ Directive::Directive(const Directive* ptr)
242
+ : Has_Block(ptr),
243
+ keyword_(ptr->keyword_),
244
+ selector_(ptr->selector_),
245
+ value_(ptr->value_) // set value manually if needed
246
+ { statement_type(DIRECTIVE); }
247
+
248
+ bool Directive::bubbles() { return is_keyframes() || is_media(); }
249
+
250
+ bool Directive::is_media() {
251
+ return keyword_.compare("@-webkit-media") == 0 ||
252
+ keyword_.compare("@-moz-media") == 0 ||
253
+ keyword_.compare("@-o-media") == 0 ||
254
+ keyword_.compare("@media") == 0;
255
+ }
256
+ bool Directive::is_keyframes() {
257
+ return keyword_.compare("@-webkit-keyframes") == 0 ||
258
+ keyword_.compare("@-moz-keyframes") == 0 ||
259
+ keyword_.compare("@-o-keyframes") == 0 ||
260
+ keyword_.compare("@keyframes") == 0;
261
+ }
262
+
263
+ /////////////////////////////////////////////////////////////////////////
264
+ /////////////////////////////////////////////////////////////////////////
265
+
266
+ Keyframe_Rule::Keyframe_Rule(ParserState pstate, Block_Obj b)
267
+ : Has_Block(pstate, b), name_()
268
+ { statement_type(KEYFRAMERULE); }
269
+ Keyframe_Rule::Keyframe_Rule(const Keyframe_Rule* ptr)
270
+ : Has_Block(ptr), name_(ptr->name_)
271
+ { statement_type(KEYFRAMERULE); }
272
+
273
+ /////////////////////////////////////////////////////////////////////////
274
+ /////////////////////////////////////////////////////////////////////////
275
+
276
+ Declaration::Declaration(ParserState pstate, String_Obj prop, Expression_Obj val, bool i, bool c, Block_Obj b)
277
+ : Has_Block(pstate, b), property_(prop), value_(val), is_important_(i), is_custom_property_(c), is_indented_(false)
278
+ { statement_type(DECLARATION); }
279
+ Declaration::Declaration(const Declaration* ptr)
280
+ : Has_Block(ptr),
281
+ property_(ptr->property_),
282
+ value_(ptr->value_),
283
+ is_important_(ptr->is_important_),
284
+ is_custom_property_(ptr->is_custom_property_),
285
+ is_indented_(ptr->is_indented_)
286
+ { statement_type(DECLARATION); }
1664
287
 
1665
- // Creates the final Selector_List by combining all the complex selectors
1666
- Selector_List_Ptr final_result = SASS_MEMORY_NEW(Selector_List, pstate());
1667
- for (auto itr = unified_complex_selectors.begin(); itr != unified_complex_selectors.end(); ++itr) {
1668
- final_result->append(*itr);
288
+ bool Declaration::is_invisible() const
289
+ {
290
+ if (is_custom_property()) return false;
291
+ return !(value_ && !Cast<Null>(value_));
292
+ }
293
+
294
+ /////////////////////////////////////////////////////////////////////////
295
+ /////////////////////////////////////////////////////////////////////////
296
+
297
+ Assignment::Assignment(ParserState pstate, std::string var, Expression_Obj val, bool is_default, bool is_global)
298
+ : Statement(pstate), variable_(var), value_(val), is_default_(is_default), is_global_(is_global)
299
+ { statement_type(ASSIGNMENT); }
300
+ Assignment::Assignment(const Assignment* ptr)
301
+ : Statement(ptr),
302
+ variable_(ptr->variable_),
303
+ value_(ptr->value_),
304
+ is_default_(ptr->is_default_),
305
+ is_global_(ptr->is_global_)
306
+ { statement_type(ASSIGNMENT); }
307
+
308
+ /////////////////////////////////////////////////////////////////////////
309
+ /////////////////////////////////////////////////////////////////////////
310
+
311
+ Import::Import(ParserState pstate)
312
+ : Statement(pstate),
313
+ urls_(std::vector<Expression_Obj>()),
314
+ incs_(std::vector<Include>()),
315
+ import_queries_()
316
+ { statement_type(IMPORT); }
317
+ Import::Import(const Import* ptr)
318
+ : Statement(ptr),
319
+ urls_(ptr->urls_),
320
+ incs_(ptr->incs_),
321
+ import_queries_(ptr->import_queries_)
322
+ { statement_type(IMPORT); }
323
+
324
+ std::vector<Include>& Import::incs() { return incs_; }
325
+ std::vector<Expression_Obj>& Import::urls() { return urls_; }
326
+
327
+ /////////////////////////////////////////////////////////////////////////
328
+ /////////////////////////////////////////////////////////////////////////
329
+
330
+ Import_Stub::Import_Stub(ParserState pstate, Include res)
331
+ : Statement(pstate), resource_(res)
332
+ { statement_type(IMPORT_STUB); }
333
+ Import_Stub::Import_Stub(const Import_Stub* ptr)
334
+ : Statement(ptr), resource_(ptr->resource_)
335
+ { statement_type(IMPORT_STUB); }
336
+ Include Import_Stub::resource() { return resource_; };
337
+ std::string Import_Stub::imp_path() { return resource_.imp_path; };
338
+ std::string Import_Stub::abs_path() { return resource_.abs_path; };
339
+
340
+ /////////////////////////////////////////////////////////////////////////
341
+ /////////////////////////////////////////////////////////////////////////
342
+
343
+ Warning::Warning(ParserState pstate, Expression_Obj msg)
344
+ : Statement(pstate), message_(msg)
345
+ { statement_type(WARNING); }
346
+ Warning::Warning(const Warning* ptr)
347
+ : Statement(ptr), message_(ptr->message_)
348
+ { statement_type(WARNING); }
349
+
350
+ /////////////////////////////////////////////////////////////////////////
351
+ /////////////////////////////////////////////////////////////////////////
352
+
353
+ Error::Error(ParserState pstate, Expression_Obj msg)
354
+ : Statement(pstate), message_(msg)
355
+ { statement_type(ERROR); }
356
+ Error::Error(const Error* ptr)
357
+ : Statement(ptr), message_(ptr->message_)
358
+ { statement_type(ERROR); }
359
+
360
+ /////////////////////////////////////////////////////////////////////////
361
+ /////////////////////////////////////////////////////////////////////////
362
+
363
+ Debug::Debug(ParserState pstate, Expression_Obj val)
364
+ : Statement(pstate), value_(val)
365
+ { statement_type(DEBUGSTMT); }
366
+ Debug::Debug(const Debug* ptr)
367
+ : Statement(ptr), value_(ptr->value_)
368
+ { statement_type(DEBUGSTMT); }
369
+
370
+ /////////////////////////////////////////////////////////////////////////
371
+ /////////////////////////////////////////////////////////////////////////
372
+
373
+ Comment::Comment(ParserState pstate, String_Obj txt, bool is_important)
374
+ : Statement(pstate), text_(txt), is_important_(is_important)
375
+ { statement_type(COMMENT); }
376
+ Comment::Comment(const Comment* ptr)
377
+ : Statement(ptr),
378
+ text_(ptr->text_),
379
+ is_important_(ptr->is_important_)
380
+ { statement_type(COMMENT); }
381
+
382
+ bool Comment::is_invisible() const
383
+ {
384
+ return false;
385
+ }
386
+
387
+ /////////////////////////////////////////////////////////////////////////
388
+ /////////////////////////////////////////////////////////////////////////
389
+
390
+ If::If(ParserState pstate, Expression_Obj pred, Block_Obj con, Block_Obj alt)
391
+ : Has_Block(pstate, con), predicate_(pred), alternative_(alt)
392
+ { statement_type(IF); }
393
+ If::If(const If* ptr)
394
+ : Has_Block(ptr),
395
+ predicate_(ptr->predicate_),
396
+ alternative_(ptr->alternative_)
397
+ { statement_type(IF); }
398
+
399
+ bool If::has_content()
400
+ {
401
+ return Has_Block::has_content() || (alternative_ && alternative_->has_content());
402
+ }
403
+
404
+ /////////////////////////////////////////////////////////////////////////
405
+ /////////////////////////////////////////////////////////////////////////
406
+
407
+ For::For(ParserState pstate,
408
+ std::string var, Expression_Obj lo, Expression_Obj hi, Block_Obj b, bool inc)
409
+ : Has_Block(pstate, b),
410
+ variable_(var), lower_bound_(lo), upper_bound_(hi), is_inclusive_(inc)
411
+ { statement_type(FOR); }
412
+ For::For(const For* ptr)
413
+ : Has_Block(ptr),
414
+ variable_(ptr->variable_),
415
+ lower_bound_(ptr->lower_bound_),
416
+ upper_bound_(ptr->upper_bound_),
417
+ is_inclusive_(ptr->is_inclusive_)
418
+ { statement_type(FOR); }
419
+
420
+ /////////////////////////////////////////////////////////////////////////
421
+ /////////////////////////////////////////////////////////////////////////
422
+
423
+ Each::Each(ParserState pstate, std::vector<std::string> vars, Expression_Obj lst, Block_Obj b)
424
+ : Has_Block(pstate, b), variables_(vars), list_(lst)
425
+ { statement_type(EACH); }
426
+ Each::Each(const Each* ptr)
427
+ : Has_Block(ptr), variables_(ptr->variables_), list_(ptr->list_)
428
+ { statement_type(EACH); }
429
+
430
+ /////////////////////////////////////////////////////////////////////////
431
+ /////////////////////////////////////////////////////////////////////////
432
+
433
+ While::While(ParserState pstate, Expression_Obj pred, Block_Obj b)
434
+ : Has_Block(pstate, b), predicate_(pred)
435
+ { statement_type(WHILE); }
436
+ While::While(const While* ptr)
437
+ : Has_Block(ptr), predicate_(ptr->predicate_)
438
+ { statement_type(WHILE); }
439
+
440
+ /////////////////////////////////////////////////////////////////////////
441
+ /////////////////////////////////////////////////////////////////////////
442
+
443
+ Return::Return(ParserState pstate, Expression_Obj val)
444
+ : Statement(pstate), value_(val)
445
+ { statement_type(RETURN); }
446
+ Return::Return(const Return* ptr)
447
+ : Statement(ptr), value_(ptr->value_)
448
+ { statement_type(RETURN); }
449
+
450
+ /////////////////////////////////////////////////////////////////////////
451
+ /////////////////////////////////////////////////////////////////////////
452
+
453
+ Extension::Extension(ParserState pstate, Selector_List_Obj s)
454
+ : Statement(pstate), selector_(s)
455
+ { statement_type(EXTEND); }
456
+ Extension::Extension(const Extension* ptr)
457
+ : Statement(ptr), selector_(ptr->selector_)
458
+ { statement_type(EXTEND); }
459
+
460
+ /////////////////////////////////////////////////////////////////////////
461
+ /////////////////////////////////////////////////////////////////////////
462
+
463
+ Definition::Definition(const Definition* ptr)
464
+ : Has_Block(ptr),
465
+ name_(ptr->name_),
466
+ parameters_(ptr->parameters_),
467
+ environment_(ptr->environment_),
468
+ type_(ptr->type_),
469
+ native_function_(ptr->native_function_),
470
+ c_function_(ptr->c_function_),
471
+ cookie_(ptr->cookie_),
472
+ is_overload_stub_(ptr->is_overload_stub_),
473
+ signature_(ptr->signature_)
474
+ { }
475
+
476
+ Definition::Definition(ParserState pstate,
477
+ std::string n,
478
+ Parameters_Obj params,
479
+ Block_Obj b,
480
+ Type t)
481
+ : Has_Block(pstate, b),
482
+ name_(n),
483
+ parameters_(params),
484
+ environment_(0),
485
+ type_(t),
486
+ native_function_(0),
487
+ c_function_(0),
488
+ cookie_(0),
489
+ is_overload_stub_(false),
490
+ signature_(0)
491
+ { }
492
+
493
+ Definition::Definition(ParserState pstate,
494
+ Signature sig,
495
+ std::string n,
496
+ Parameters_Obj params,
497
+ Native_Function func_ptr,
498
+ bool overload_stub)
499
+ : Has_Block(pstate, {}),
500
+ name_(n),
501
+ parameters_(params),
502
+ environment_(0),
503
+ type_(FUNCTION),
504
+ native_function_(func_ptr),
505
+ c_function_(0),
506
+ cookie_(0),
507
+ is_overload_stub_(overload_stub),
508
+ signature_(sig)
509
+ { }
510
+
511
+ Definition::Definition(ParserState pstate,
512
+ Signature sig,
513
+ std::string n,
514
+ Parameters_Obj params,
515
+ Sass_Function_Entry c_func)
516
+ : Has_Block(pstate, {}),
517
+ name_(n),
518
+ parameters_(params),
519
+ environment_(0),
520
+ type_(FUNCTION),
521
+ native_function_(0),
522
+ c_function_(c_func),
523
+ cookie_(sass_function_get_cookie(c_func)),
524
+ is_overload_stub_(false),
525
+ signature_(sig)
526
+ { }
527
+
528
+ /////////////////////////////////////////////////////////////////////////
529
+ /////////////////////////////////////////////////////////////////////////
530
+
531
+ Mixin_Call::Mixin_Call(ParserState pstate, std::string n, Arguments_Obj args, Parameters_Obj b_params, Block_Obj b)
532
+ : Has_Block(pstate, b), name_(n), arguments_(args), block_parameters_(b_params)
533
+ { }
534
+ Mixin_Call::Mixin_Call(const Mixin_Call* ptr)
535
+ : Has_Block(ptr),
536
+ name_(ptr->name_),
537
+ arguments_(ptr->arguments_),
538
+ block_parameters_(ptr->block_parameters_)
539
+ { }
540
+
541
+ /////////////////////////////////////////////////////////////////////////
542
+ /////////////////////////////////////////////////////////////////////////
543
+
544
+ Content::Content(ParserState pstate, Arguments_Obj args)
545
+ : Statement(pstate),
546
+ arguments_(args)
547
+ { statement_type(CONTENT); }
548
+ Content::Content(const Content* ptr)
549
+ : Statement(ptr),
550
+ arguments_(ptr->arguments_)
551
+ { statement_type(CONTENT); }
552
+
553
+ /////////////////////////////////////////////////////////////////////////
554
+ /////////////////////////////////////////////////////////////////////////
555
+
556
+ Expression::Expression(ParserState pstate, bool d, bool e, bool i, Type ct)
557
+ : AST_Node(pstate),
558
+ is_delayed_(d),
559
+ is_expanded_(e),
560
+ is_interpolant_(i),
561
+ concrete_type_(ct)
562
+ { }
563
+
564
+ Expression::Expression(const Expression* ptr)
565
+ : AST_Node(ptr),
566
+ is_delayed_(ptr->is_delayed_),
567
+ is_expanded_(ptr->is_expanded_),
568
+ is_interpolant_(ptr->is_interpolant_),
569
+ concrete_type_(ptr->concrete_type_)
570
+ { }
571
+
572
+ /////////////////////////////////////////////////////////////////////////
573
+ /////////////////////////////////////////////////////////////////////////
574
+
575
+ Unary_Expression::Unary_Expression(ParserState pstate, Type t, Expression_Obj o)
576
+ : Expression(pstate), optype_(t), operand_(o), hash_(0)
577
+ { }
578
+ Unary_Expression::Unary_Expression(const Unary_Expression* ptr)
579
+ : Expression(ptr),
580
+ optype_(ptr->optype_),
581
+ operand_(ptr->operand_),
582
+ hash_(ptr->hash_)
583
+ { }
584
+ const std::string Unary_Expression::type_name() {
585
+ switch (optype_) {
586
+ case PLUS: return "plus";
587
+ case MINUS: return "minus";
588
+ case SLASH: return "slash";
589
+ case NOT: return "not";
590
+ default: return "invalid";
591
+ }
592
+ }
593
+ bool Unary_Expression::operator==(const Expression& rhs) const
594
+ {
595
+ try
596
+ {
597
+ const Unary_Expression* m = Cast<Unary_Expression>(&rhs);
598
+ if (m == 0) return false;
599
+ return type() == m->type() &&
600
+ *operand() == *m->operand();
601
+ }
602
+ catch (std::bad_cast&)
603
+ {
604
+ return false;
1669
605
  }
1670
- return final_result;
606
+ catch (...) { throw; }
1671
607
  }
1672
-
1673
- void Selector_List::populate_extends(Selector_List_Obj extendee, Subset_Map& extends)
608
+ size_t Unary_Expression::hash() const
1674
609
  {
610
+ if (hash_ == 0) {
611
+ hash_ = std::hash<size_t>()(optype_);
612
+ hash_combine(hash_, operand()->hash());
613
+ };
614
+ return hash_;
615
+ }
1675
616
 
1676
- Selector_List_Ptr extender = this;
1677
- for (auto complex_sel : extendee->elements()) {
1678
- Complex_Selector_Obj c = complex_sel;
1679
-
1680
-
1681
- // Ignore any parent selectors, until we find the first non Selectorerence head
1682
- Compound_Selector_Obj compound_sel = c->head();
1683
- Complex_Selector_Obj pIter = complex_sel;
1684
- while (pIter) {
1685
- Compound_Selector_Obj pHead = pIter->head();
1686
- if (pHead && Cast<Parent_Selector>(pHead->elements()[0]) == NULL) {
1687
- compound_sel = pHead;
1688
- break;
1689
- }
1690
-
1691
- pIter = pIter->tail();
1692
- }
1693
-
1694
- if (!pIter->head() || pIter->tail()) {
1695
- coreError("nested selectors may not be extended", c->pstate());
1696
- }
1697
-
1698
- compound_sel->is_optional(extendee->is_optional());
617
+ /////////////////////////////////////////////////////////////////////////
618
+ /////////////////////////////////////////////////////////////////////////
1699
619
 
1700
- for (size_t i = 0, L = extender->length(); i < L; ++i) {
1701
- extends.put(compound_sel, std::make_pair((*extender)[i], compound_sel));
1702
- }
620
+ Argument::Argument(ParserState pstate, Expression_Obj val, std::string n, bool rest, bool keyword)
621
+ : Expression(pstate), value_(val), name_(n), is_rest_argument_(rest), is_keyword_argument_(keyword), hash_(0)
622
+ {
623
+ if (!name_.empty() && is_rest_argument_) {
624
+ coreError("variable-length argument may not be passed by name", pstate_);
1703
625
  }
1704
- };
1705
-
1706
- void Compound_Selector::append(Simple_Selector_Ptr element)
626
+ }
627
+ Argument::Argument(const Argument* ptr)
628
+ : Expression(ptr),
629
+ value_(ptr->value_),
630
+ name_(ptr->name_),
631
+ is_rest_argument_(ptr->is_rest_argument_),
632
+ is_keyword_argument_(ptr->is_keyword_argument_),
633
+ hash_(ptr->hash_)
1707
634
  {
1708
- Vectorized<Simple_Selector_Obj>::append(element);
1709
- pstate_.offset += element->pstate().offset;
635
+ if (!name_.empty() && is_rest_argument_) {
636
+ coreError("variable-length argument may not be passed by name", pstate_);
637
+ }
1710
638
  }
1711
639
 
1712
- Compound_Selector_Ptr Compound_Selector::minus(Compound_Selector_Ptr rhs)
640
+ void Argument::set_delayed(bool delayed)
1713
641
  {
1714
- Compound_Selector_Ptr result = SASS_MEMORY_NEW(Compound_Selector, pstate());
1715
- // result->has_parent_reference(has_parent_reference());
642
+ if (value_) value_->set_delayed(delayed);
643
+ is_delayed(delayed);
644
+ }
1716
645
 
1717
- // not very efficient because it needs to preserve order
1718
- for (size_t i = 0, L = length(); i < L; ++i)
646
+ bool Argument::operator==(const Expression& rhs) const
647
+ {
648
+ try
1719
649
  {
1720
- bool found = false;
1721
- std::string thisSelector((*this)[i]->to_string());
1722
- for (size_t j = 0, M = rhs->length(); j < M; ++j)
1723
- {
1724
- if (thisSelector == (*rhs)[j]->to_string())
1725
- {
1726
- found = true;
1727
- break;
1728
- }
1729
- }
1730
- if (!found) result->append((*this)[i]);
650
+ const Argument* m = Cast<Argument>(&rhs);
651
+ if (!(m && name() == m->name())) return false;
652
+ return *value() == *m->value();
653
+ }
654
+ catch (std::bad_cast&)
655
+ {
656
+ return false;
1731
657
  }
658
+ catch (...) { throw; }
659
+ }
1732
660
 
1733
- return result;
661
+ size_t Argument::hash() const
662
+ {
663
+ if (hash_ == 0) {
664
+ hash_ = std::hash<std::string>()(name());
665
+ hash_combine(hash_, value()->hash());
666
+ }
667
+ return hash_;
1734
668
  }
1735
669
 
1736
- void Compound_Selector::mergeSources(ComplexSelectorSet& sources)
670
+ /////////////////////////////////////////////////////////////////////////
671
+ /////////////////////////////////////////////////////////////////////////
672
+
673
+ Arguments::Arguments(ParserState pstate)
674
+ : Expression(pstate),
675
+ Vectorized<Argument_Obj>(),
676
+ has_named_arguments_(false),
677
+ has_rest_argument_(false),
678
+ has_keyword_argument_(false)
679
+ { }
680
+ Arguments::Arguments(const Arguments* ptr)
681
+ : Expression(ptr),
682
+ Vectorized<Argument_Obj>(*ptr),
683
+ has_named_arguments_(ptr->has_named_arguments_),
684
+ has_rest_argument_(ptr->has_rest_argument_),
685
+ has_keyword_argument_(ptr->has_keyword_argument_)
686
+ { }
687
+
688
+ void Arguments::set_delayed(bool delayed)
1737
689
  {
1738
- for (ComplexSelectorSet::iterator iterator = sources.begin(), endIterator = sources.end(); iterator != endIterator; ++iterator) {
1739
- this->sources_.insert(SASS_MEMORY_CLONE(*iterator));
690
+ for (Argument_Obj arg : elements()) {
691
+ if (arg) arg->set_delayed(delayed);
1740
692
  }
693
+ is_delayed(delayed);
1741
694
  }
1742
695
 
1743
696
  Argument_Obj Arguments::get_rest_argument()
@@ -1749,7 +702,7 @@ namespace Sass {
1749
702
  }
1750
703
  }
1751
704
  }
1752
- return NULL;
705
+ return {};
1753
706
  }
1754
707
 
1755
708
  Argument_Obj Arguments::get_keyword_argument()
@@ -1761,7 +714,7 @@ namespace Sass {
1761
714
  }
1762
715
  }
1763
716
  }
1764
- return NULL;
717
+ return {};
1765
718
  }
1766
719
 
1767
720
  void Arguments::adjust_after_pushing(Argument_Obj a)
@@ -1797,397 +750,185 @@ namespace Sass {
1797
750
  }
1798
751
  }
1799
752
 
1800
- bool Ruleset::is_invisible() const {
1801
- if (Selector_List_Ptr sl = Cast<Selector_List>(selector())) {
1802
- for (size_t i = 0, L = sl->length(); i < L; ++i)
1803
- if (!(*sl)[i]->has_placeholder()) return false;
1804
- }
1805
- return true;
1806
- }
1807
-
1808
- bool Media_Block::is_invisible() const {
1809
- for (size_t i = 0, L = block()->length(); i < L; ++i) {
1810
- Statement_Obj stm = block()->at(i);
1811
- if (!stm->is_invisible()) return false;
1812
- }
1813
- return true;
1814
- }
753
+ /////////////////////////////////////////////////////////////////////////
754
+ /////////////////////////////////////////////////////////////////////////
755
+
756
+ Media_Query::Media_Query(ParserState pstate, String_Obj t, size_t s, bool n, bool r)
757
+ : Expression(pstate), Vectorized<Media_Query_Expression_Obj>(s),
758
+ media_type_(t), is_negated_(n), is_restricted_(r)
759
+ { }
760
+ Media_Query::Media_Query(const Media_Query* ptr)
761
+ : Expression(ptr),
762
+ Vectorized<Media_Query_Expression_Obj>(*ptr),
763
+ media_type_(ptr->media_type_),
764
+ is_negated_(ptr->is_negated_),
765
+ is_restricted_(ptr->is_restricted_)
766
+ { }
767
+
768
+ /////////////////////////////////////////////////////////////////////////
769
+ /////////////////////////////////////////////////////////////////////////
770
+
771
+ Media_Query_Expression::Media_Query_Expression(ParserState pstate,
772
+ Expression_Obj f, Expression_Obj v, bool i)
773
+ : Expression(pstate), feature_(f), value_(v), is_interpolated_(i)
774
+ { }
775
+ Media_Query_Expression::Media_Query_Expression(const Media_Query_Expression* ptr)
776
+ : Expression(ptr),
777
+ feature_(ptr->feature_),
778
+ value_(ptr->value_),
779
+ is_interpolated_(ptr->is_interpolated_)
780
+ { }
781
+
782
+ /////////////////////////////////////////////////////////////////////////
783
+ /////////////////////////////////////////////////////////////////////////
784
+
785
+ At_Root_Query::At_Root_Query(ParserState pstate, Expression_Obj f, Expression_Obj v, bool i)
786
+ : Expression(pstate), feature_(f), value_(v)
787
+ { }
788
+ At_Root_Query::At_Root_Query(const At_Root_Query* ptr)
789
+ : Expression(ptr),
790
+ feature_(ptr->feature_),
791
+ value_(ptr->value_)
792
+ { }
1815
793
 
1816
- Number::Number(ParserState pstate, double val, std::string u, bool zero)
1817
- : Value(pstate),
1818
- Units(),
1819
- value_(val),
1820
- zero_(zero),
1821
- hash_(0)
794
+ bool At_Root_Query::exclude(std::string str)
1822
795
  {
1823
- size_t l = 0;
1824
- size_t r;
1825
- if (!u.empty()) {
1826
- bool nominator = true;
1827
- while (true) {
1828
- r = u.find_first_of("*/", l);
1829
- std::string unit(u.substr(l, r == std::string::npos ? r : r - l));
1830
- if (!unit.empty()) {
1831
- if (nominator) numerators.push_back(unit);
1832
- else denominators.push_back(unit);
1833
- }
1834
- if (r == std::string::npos) break;
1835
- // ToDo: should error for multiple slashes
1836
- // if (!nominator && u[r] == '/') error(...)
1837
- if (u[r] == '/')
1838
- nominator = false;
1839
- // strange math parsing?
1840
- // else if (u[r] == '*')
1841
- // nominator = true;
1842
- l = r + 1;
796
+ bool with = feature() && unquote(feature()->to_string()).compare("with") == 0;
797
+ List* l = static_cast<List*>(value().ptr());
798
+ std::string v;
799
+
800
+ if (with)
801
+ {
802
+ if (!l || l->length() == 0) return str.compare("rule") != 0;
803
+ for (size_t i = 0, L = l->length(); i < L; ++i)
804
+ {
805
+ v = unquote((*l)[i]->to_string());
806
+ if (v.compare("all") == 0 || v == str) return false;
1843
807
  }
808
+ return true;
809
+ }
810
+ else
811
+ {
812
+ if (!l || !l->length()) return str.compare("rule") == 0;
813
+ for (size_t i = 0, L = l->length(); i < L; ++i)
814
+ {
815
+ v = unquote((*l)[i]->to_string());
816
+ if (v.compare("all") == 0 || v == str) return true;
817
+ }
818
+ return false;
1844
819
  }
1845
- concrete_type(NUMBER);
1846
- }
1847
-
1848
- // cancel out unnecessary units
1849
- void Number::reduce()
1850
- {
1851
- // apply conversion factor
1852
- value_ *= this->Units::reduce();
1853
820
  }
1854
821
 
1855
- void Number::normalize()
1856
- {
1857
- // apply conversion factor
1858
- value_ *= this->Units::normalize();
1859
- }
822
+ /////////////////////////////////////////////////////////////////////////
823
+ /////////////////////////////////////////////////////////////////////////
1860
824
 
1861
- bool Custom_Warning::operator== (const Expression& rhs) const
1862
- {
1863
- if (Custom_Warning_Ptr_Const r = Cast<Custom_Warning>(&rhs)) {
1864
- return message() == r->message();
1865
- }
1866
- return false;
1867
- }
825
+ At_Root_Block::At_Root_Block(ParserState pstate, Block_Obj b, At_Root_Query_Obj e)
826
+ : Has_Block(pstate, b), expression_(e)
827
+ { statement_type(ATROOT); }
828
+ At_Root_Block::At_Root_Block(const At_Root_Block* ptr)
829
+ : Has_Block(ptr), expression_(ptr->expression_)
830
+ { statement_type(ATROOT); }
1868
831
 
1869
- bool Custom_Error::operator== (const Expression& rhs) const
1870
- {
1871
- if (Custom_Error_Ptr_Const r = Cast<Custom_Error>(&rhs)) {
1872
- return message() == r->message();
1873
- }
1874
- return false;
832
+ bool At_Root_Block::bubbles() {
833
+ return true;
1875
834
  }
1876
835
 
1877
- bool Number::operator== (const Expression& rhs) const
1878
- {
1879
- if (auto rhsnr = Cast<Number>(&rhs)) {
1880
- return *this == *rhsnr;
836
+ bool At_Root_Block::exclude_node(Statement_Obj s) {
837
+ if (expression() == 0)
838
+ {
839
+ return s->statement_type() == Statement::RULESET;
1881
840
  }
1882
- return false;
1883
- }
1884
841
 
1885
- bool Number::operator== (const Number& rhs) const
1886
- {
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());
842
+ if (s->statement_type() == Statement::DIRECTIVE)
843
+ {
844
+ if (Directive_Obj dir = Cast<Directive>(s))
845
+ {
846
+ std::string keyword(dir->keyword());
847
+ if (keyword.length() > 0) keyword.erase(0, 1);
848
+ return expression()->exclude(keyword);
849
+ }
1893
850
  }
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());
1898
- }
1899
-
1900
- bool Number::operator< (const Number& rhs) const
1901
- {
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();
1905
- // unitless and only having one unit seems equivalent (will change in future)
1906
- if (!lhs_units || !rhs_units) {
1907
- return l.value() < r.value();
851
+ if (s->statement_type() == Statement::MEDIA)
852
+ {
853
+ return expression()->exclude("media");
1908
854
  }
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);
855
+ if (s->statement_type() == Statement::RULESET)
856
+ {
857
+ return expression()->exclude("rule");
1914
858
  }
1915
- return lhs_unit < rhs_unit ||
1916
- l.value() < r.value();
1917
- }
1918
-
1919
- bool String_Quoted::operator== (const Expression& rhs) const
1920
- {
1921
- if (String_Quoted_Ptr_Const qstr = Cast<String_Quoted>(&rhs)) {
1922
- return (value() == qstr->value());
1923
- } else if (String_Constant_Ptr_Const cstr = Cast<String_Constant>(&rhs)) {
1924
- return (value() == cstr->value());
859
+ if (s->statement_type() == Statement::SUPPORTS)
860
+ {
861
+ return expression()->exclude("supports");
1925
862
  }
1926
- return false;
1927
- }
1928
-
1929
- bool String_Constant::is_invisible() const {
1930
- return value_.empty() && quote_mark_ == 0;
1931
- }
1932
-
1933
- bool String_Constant::operator== (const Expression& rhs) const
1934
- {
1935
- if (String_Quoted_Ptr_Const qstr = Cast<String_Quoted>(&rhs)) {
1936
- return (value() == qstr->value());
1937
- } else if (String_Constant_Ptr_Const cstr = Cast<String_Constant>(&rhs)) {
1938
- return (value() == cstr->value());
863
+ if (Directive_Obj dir = Cast<Directive>(s))
864
+ {
865
+ if (dir->is_keyframes()) return expression()->exclude("keyframes");
1939
866
  }
1940
867
  return false;
1941
868
  }
1942
869
 
1943
- bool String_Schema::is_left_interpolant(void) const
1944
- {
1945
- return length() && first()->is_left_interpolant();
1946
- }
1947
- bool String_Schema::is_right_interpolant(void) const
1948
- {
1949
- return length() && last()->is_right_interpolant();
1950
- }
870
+ /////////////////////////////////////////////////////////////////////////
871
+ /////////////////////////////////////////////////////////////////////////
1951
872
 
1952
- bool String_Schema::operator== (const Expression& rhs) const
1953
- {
1954
- if (String_Schema_Ptr_Const r = Cast<String_Schema>(&rhs)) {
1955
- if (length() != r->length()) return false;
1956
- for (size_t i = 0, L = length(); i < L; ++i) {
1957
- Expression_Obj rv = (*r)[i];
1958
- Expression_Obj lv = (*this)[i];
1959
- if (!lv || !rv) return false;
1960
- if (!(*lv == *rv)) return false;
1961
- }
1962
- return true;
1963
- }
1964
- return false;
1965
- }
873
+ Parameter::Parameter(ParserState pstate, std::string n, Expression_Obj def, bool rest)
874
+ : AST_Node(pstate), name_(n), default_value_(def), is_rest_parameter_(rest)
875
+ { }
876
+ Parameter::Parameter(const Parameter* ptr)
877
+ : AST_Node(ptr),
878
+ name_(ptr->name_),
879
+ default_value_(ptr->default_value_),
880
+ is_rest_parameter_(ptr->is_rest_parameter_)
881
+ { }
1966
882
 
1967
- bool Boolean::operator== (const Expression& rhs) const
1968
- {
1969
- if (Boolean_Ptr_Const r = Cast<Boolean>(&rhs)) {
1970
- return (value() == r->value());
1971
- }
1972
- return false;
1973
- }
883
+ /////////////////////////////////////////////////////////////////////////
884
+ /////////////////////////////////////////////////////////////////////////
1974
885
 
1975
- bool Color::operator== (const Expression& rhs) const
1976
- {
1977
- if (Color_Ptr_Const r = Cast<Color>(&rhs)) {
1978
- return r_ == r->r() &&
1979
- g_ == r->g() &&
1980
- b_ == r->b() &&
1981
- a_ == r->a();
1982
- }
1983
- return false;
1984
- }
886
+ Parameters::Parameters(ParserState pstate)
887
+ : AST_Node(pstate),
888
+ Vectorized<Parameter_Obj>(),
889
+ has_optional_parameters_(false),
890
+ has_rest_parameter_(false)
891
+ { }
892
+ Parameters::Parameters(const Parameters* ptr)
893
+ : AST_Node(ptr),
894
+ Vectorized<Parameter_Obj>(*ptr),
895
+ has_optional_parameters_(ptr->has_optional_parameters_),
896
+ has_rest_parameter_(ptr->has_rest_parameter_)
897
+ { }
1985
898
 
1986
- bool List::operator== (const Expression& rhs) const
899
+ void Parameters::adjust_after_pushing(Parameter_Obj p)
1987
900
  {
1988
- if (List_Ptr_Const r = Cast<List>(&rhs)) {
1989
- if (length() != r->length()) return false;
1990
- if (separator() != r->separator()) return false;
1991
- if (is_bracketed() != r->is_bracketed()) return false;
1992
- for (size_t i = 0, L = length(); i < L; ++i) {
1993
- Expression_Obj rv = r->at(i);
1994
- Expression_Obj lv = this->at(i);
1995
- if (!lv || !rv) return false;
1996
- if (!(*lv == *rv)) return false;
901
+ if (p->default_value()) {
902
+ if (has_rest_parameter()) {
903
+ coreError("optional parameters may not be combined with variable-length parameters", p->pstate());
1997
904
  }
1998
- return true;
905
+ has_optional_parameters(true);
1999
906
  }
2000
- return false;
2001
- }
2002
-
2003
- bool Map::operator== (const Expression& rhs) const
2004
- {
2005
- if (Map_Ptr_Const r = Cast<Map>(&rhs)) {
2006
- if (length() != r->length()) return false;
2007
- for (auto key : keys()) {
2008
- Expression_Obj lv = at(key);
2009
- Expression_Obj rv = r->at(key);
2010
- if (!rv || !lv) return false;
2011
- if (!(*lv == *rv)) return false;
907
+ else if (p->is_rest_parameter()) {
908
+ if (has_rest_parameter()) {
909
+ coreError("functions and mixins cannot have more than one variable-length parameter", p->pstate());
2012
910
  }
2013
- return true;
2014
- }
2015
- return false;
2016
- }
2017
-
2018
- bool Null::operator== (const Expression& rhs) const
2019
- {
2020
- return rhs.concrete_type() == NULL_VAL;
2021
- }
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();
911
+ has_rest_parameter(true);
2029
912
  }
2030
- return false;
2031
- }
2032
-
2033
- size_t List::size() const {
2034
- if (!is_arglist_) return length();
2035
- // arglist expects a list of arguments
2036
- // so we need to break before keywords
2037
- for (size_t i = 0, L = length(); i < L; ++i) {
2038
- Expression_Obj obj = this->at(i);
2039
- if (Argument_Ptr arg = Cast<Argument>(obj)) {
2040
- if (!arg->name().empty()) return i;
913
+ else {
914
+ if (has_rest_parameter()) {
915
+ coreError("required parameters must precede variable-length parameters", p->pstate());
2041
916
  }
2042
- }
2043
- return length();
2044
- }
2045
-
2046
- Expression_Obj Hashed::at(Expression_Obj k) const
2047
- {
2048
- if (elements_.count(k))
2049
- { return elements_.at(k); }
2050
- else { return NULL; }
2051
- }
2052
-
2053
- bool Binary_Expression::is_left_interpolant(void) const
2054
- {
2055
- return is_interpolant() || (left() && left()->is_left_interpolant());
2056
- }
2057
- bool Binary_Expression::is_right_interpolant(void) const
2058
- {
2059
- return is_interpolant() || (right() && right()->is_right_interpolant());
2060
- }
2061
-
2062
- const std::string AST_Node::to_string(Sass_Inspect_Options opt) const
2063
- {
2064
- Sass_Output_Options out(opt);
2065
- Emitter emitter(out);
2066
- Inspect i(emitter);
2067
- i.in_declaration = true;
2068
- // ToDo: inspect should be const
2069
- const_cast<AST_Node_Ptr>(this)->perform(&i);
2070
- return i.get_buffer();
2071
- }
2072
-
2073
- const std::string AST_Node::to_string() const
2074
- {
2075
- return to_string({ NESTED, 5 });
2076
- }
2077
-
2078
- std::string String_Quoted::inspect() const
2079
- {
2080
- return quote(value_, '*');
2081
- }
2082
-
2083
- std::string String_Constant::inspect() const
2084
- {
2085
- return quote(value_, '*');
2086
- }
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
-
2095
- //////////////////////////////////////////////////////////////////////////////////////////
2096
- // Additional method on Lists to retrieve values directly or from an encompassed Argument.
2097
- //////////////////////////////////////////////////////////////////////////////////////////
2098
- Expression_Obj List::value_at_index(size_t i) {
2099
- Expression_Obj obj = this->at(i);
2100
- if (is_arglist_) {
2101
- if (Argument_Ptr arg = Cast<Argument>(obj)) {
2102
- return arg->value();
2103
- } else {
2104
- return obj;
917
+ if (has_optional_parameters()) {
918
+ coreError("required parameters must precede optional parameters", p->pstate());
2105
919
  }
2106
- } else {
2107
- return obj;
2108
920
  }
2109
921
  }
2110
922
 
2111
- //////////////////////////////////////////////////////////////////////////////////////////
2112
- // Convert map to (key, value) list.
2113
- //////////////////////////////////////////////////////////////////////////////////////////
2114
- List_Obj Map::to_list(ParserState& pstate) {
2115
- List_Obj ret = SASS_MEMORY_NEW(List, pstate, length(), SASS_COMMA);
2116
-
2117
- for (auto key : keys()) {
2118
- List_Obj l = SASS_MEMORY_NEW(List, pstate, 2);
2119
- l->append(key);
2120
- l->append(at(key));
2121
- ret->append(l);
2122
- }
2123
-
2124
- return ret;
2125
- }
923
+ /////////////////////////////////////////////////////////////////////////
924
+ /////////////////////////////////////////////////////////////////////////
2126
925
 
2127
- //////////////////////////////////////////////////////////////////////////////////////////
2128
- // Copy implementations
2129
- //////////////////////////////////////////////////////////////////////////////////////////
2130
-
2131
- #ifdef DEBUG_SHARED_PTR
2132
-
2133
- #define IMPLEMENT_AST_OPERATORS(klass) \
2134
- klass##_Ptr klass::copy(std::string file, size_t line) const { \
2135
- klass##_Ptr cpy = new klass(this); \
2136
- cpy->trace(file, line); \
2137
- return cpy; \
2138
- } \
2139
- klass##_Ptr klass::clone(std::string file, size_t line) const { \
2140
- klass##_Ptr cpy = copy(file, line); \
2141
- cpy->cloneChildren(); \
2142
- return cpy; \
2143
- } \
2144
-
2145
- #else
2146
-
2147
- #define IMPLEMENT_AST_OPERATORS(klass) \
2148
- klass##_Ptr klass::copy() const { \
2149
- return new klass(this); \
2150
- } \
2151
- klass##_Ptr klass::clone() const { \
2152
- klass##_Ptr cpy = copy(); \
2153
- cpy->cloneChildren(); \
2154
- return cpy; \
2155
- } \
2156
-
2157
- #endif
2158
-
2159
- IMPLEMENT_AST_OPERATORS(Supports_Operator);
2160
- IMPLEMENT_AST_OPERATORS(Supports_Negation);
2161
- IMPLEMENT_AST_OPERATORS(Compound_Selector);
2162
- IMPLEMENT_AST_OPERATORS(Complex_Selector);
2163
- IMPLEMENT_AST_OPERATORS(Element_Selector);
2164
- IMPLEMENT_AST_OPERATORS(Class_Selector);
2165
- IMPLEMENT_AST_OPERATORS(Id_Selector);
2166
- IMPLEMENT_AST_OPERATORS(Pseudo_Selector);
2167
- IMPLEMENT_AST_OPERATORS(Wrapped_Selector);
2168
- IMPLEMENT_AST_OPERATORS(Selector_List);
2169
926
  IMPLEMENT_AST_OPERATORS(Ruleset);
2170
927
  IMPLEMENT_AST_OPERATORS(Media_Block);
2171
- IMPLEMENT_AST_OPERATORS(Custom_Warning);
2172
- IMPLEMENT_AST_OPERATORS(Custom_Error);
2173
- IMPLEMENT_AST_OPERATORS(List);
2174
- IMPLEMENT_AST_OPERATORS(Map);
2175
- IMPLEMENT_AST_OPERATORS(Function);
2176
- IMPLEMENT_AST_OPERATORS(Number);
2177
- IMPLEMENT_AST_OPERATORS(Binary_Expression);
2178
- IMPLEMENT_AST_OPERATORS(String_Schema);
2179
- IMPLEMENT_AST_OPERATORS(String_Constant);
2180
- IMPLEMENT_AST_OPERATORS(String_Quoted);
2181
- IMPLEMENT_AST_OPERATORS(Boolean);
2182
- IMPLEMENT_AST_OPERATORS(Color);
2183
- IMPLEMENT_AST_OPERATORS(Null);
2184
- IMPLEMENT_AST_OPERATORS(Parent_Selector);
2185
928
  IMPLEMENT_AST_OPERATORS(Import);
2186
929
  IMPLEMENT_AST_OPERATORS(Import_Stub);
2187
- IMPLEMENT_AST_OPERATORS(Function_Call);
2188
930
  IMPLEMENT_AST_OPERATORS(Directive);
2189
931
  IMPLEMENT_AST_OPERATORS(At_Root_Block);
2190
- IMPLEMENT_AST_OPERATORS(Supports_Block);
2191
932
  IMPLEMENT_AST_OPERATORS(While);
2192
933
  IMPLEMENT_AST_OPERATORS(Each);
2193
934
  IMPLEMENT_AST_OPERATORS(For);
@@ -2202,25 +943,21 @@ namespace Sass {
2202
943
  IMPLEMENT_AST_OPERATORS(Assignment);
2203
944
  IMPLEMENT_AST_OPERATORS(Return);
2204
945
  IMPLEMENT_AST_OPERATORS(At_Root_Query);
2205
- IMPLEMENT_AST_OPERATORS(Variable);
2206
946
  IMPLEMENT_AST_OPERATORS(Comment);
2207
- IMPLEMENT_AST_OPERATORS(Attribute_Selector);
2208
- IMPLEMENT_AST_OPERATORS(Supports_Interpolation);
2209
- IMPLEMENT_AST_OPERATORS(Supports_Declaration);
2210
- IMPLEMENT_AST_OPERATORS(Supports_Condition);
2211
947
  IMPLEMENT_AST_OPERATORS(Parameters);
2212
948
  IMPLEMENT_AST_OPERATORS(Parameter);
2213
949
  IMPLEMENT_AST_OPERATORS(Arguments);
2214
950
  IMPLEMENT_AST_OPERATORS(Argument);
2215
951
  IMPLEMENT_AST_OPERATORS(Unary_Expression);
2216
- IMPLEMENT_AST_OPERATORS(Function_Call_Schema);
2217
952
  IMPLEMENT_AST_OPERATORS(Block);
2218
953
  IMPLEMENT_AST_OPERATORS(Content);
2219
954
  IMPLEMENT_AST_OPERATORS(Trace);
2220
955
  IMPLEMENT_AST_OPERATORS(Keyframe_Rule);
2221
956
  IMPLEMENT_AST_OPERATORS(Bubble);
2222
- IMPLEMENT_AST_OPERATORS(Selector_Schema);
2223
- IMPLEMENT_AST_OPERATORS(Placeholder_Selector);
2224
957
  IMPLEMENT_AST_OPERATORS(Definition);
2225
958
  IMPLEMENT_AST_OPERATORS(Declaration);
959
+
960
+ /////////////////////////////////////////////////////////////////////////
961
+ /////////////////////////////////////////////////////////////////////////
962
+
2226
963
  }