sassc 2.1.0.pre3 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/CHANGELOG.md +24 -0
  4. data/Rakefile +2 -4
  5. data/ext/extconf.rb +13 -5
  6. data/ext/libsass/VERSION +1 -1
  7. data/ext/libsass/include/sass/base.h +2 -1
  8. data/ext/libsass/include/sass/context.h +4 -0
  9. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  10. data/ext/libsass/src/ast.cpp +158 -168
  11. data/ext/libsass/src/ast.hpp +389 -230
  12. data/ext/libsass/src/ast_def_macros.hpp +18 -10
  13. data/ext/libsass/src/ast_fwd_decl.cpp +4 -3
  14. data/ext/libsass/src/ast_fwd_decl.hpp +98 -165
  15. data/ext/libsass/src/ast_helpers.hpp +292 -0
  16. data/ext/libsass/src/ast_sel_cmp.cpp +219 -732
  17. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  18. data/ext/libsass/src/ast_sel_unify.cpp +207 -212
  19. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  20. data/ext/libsass/src/ast_selectors.cpp +594 -1026
  21. data/ext/libsass/src/ast_selectors.hpp +339 -385
  22. data/ext/libsass/src/ast_supports.cpp +36 -52
  23. data/ext/libsass/src/ast_supports.hpp +29 -29
  24. data/ext/libsass/src/ast_values.cpp +271 -84
  25. data/ext/libsass/src/ast_values.hpp +116 -107
  26. data/ext/libsass/src/backtrace.cpp +9 -9
  27. data/ext/libsass/src/backtrace.hpp +5 -5
  28. data/ext/libsass/src/base64vlq.cpp +2 -2
  29. data/ext/libsass/src/base64vlq.hpp +1 -1
  30. data/ext/libsass/src/bind.cpp +18 -18
  31. data/ext/libsass/src/bind.hpp +1 -1
  32. data/ext/libsass/src/c2ast.cpp +3 -3
  33. data/ext/libsass/src/c2ast.hpp +1 -1
  34. data/ext/libsass/src/cencode.c +4 -6
  35. data/ext/libsass/src/check_nesting.cpp +40 -41
  36. data/ext/libsass/src/check_nesting.hpp +6 -2
  37. data/ext/libsass/src/color_maps.cpp +14 -13
  38. data/ext/libsass/src/color_maps.hpp +1 -9
  39. data/ext/libsass/src/constants.cpp +5 -0
  40. data/ext/libsass/src/constants.hpp +6 -0
  41. data/ext/libsass/src/context.cpp +92 -119
  42. data/ext/libsass/src/context.hpp +41 -53
  43. data/ext/libsass/src/cssize.cpp +66 -149
  44. data/ext/libsass/src/cssize.hpp +17 -23
  45. data/ext/libsass/src/dart_helpers.hpp +199 -0
  46. data/ext/libsass/src/debugger.hpp +451 -295
  47. data/ext/libsass/src/emitter.cpp +15 -16
  48. data/ext/libsass/src/emitter.hpp +10 -12
  49. data/ext/libsass/src/environment.cpp +27 -27
  50. data/ext/libsass/src/environment.hpp +29 -24
  51. data/ext/libsass/src/error_handling.cpp +62 -41
  52. data/ext/libsass/src/error_handling.hpp +61 -51
  53. data/ext/libsass/src/eval.cpp +167 -281
  54. data/ext/libsass/src/eval.hpp +27 -29
  55. data/ext/libsass/src/eval_selectors.cpp +75 -0
  56. data/ext/libsass/src/expand.cpp +275 -222
  57. data/ext/libsass/src/expand.hpp +36 -16
  58. data/ext/libsass/src/extender.cpp +1188 -0
  59. data/ext/libsass/src/extender.hpp +399 -0
  60. data/ext/libsass/src/extension.cpp +43 -0
  61. data/ext/libsass/src/extension.hpp +89 -0
  62. data/ext/libsass/src/file.cpp +81 -72
  63. data/ext/libsass/src/file.hpp +28 -37
  64. data/ext/libsass/src/fn_colors.cpp +20 -18
  65. data/ext/libsass/src/fn_lists.cpp +30 -29
  66. data/ext/libsass/src/fn_maps.cpp +3 -3
  67. data/ext/libsass/src/fn_miscs.cpp +34 -46
  68. data/ext/libsass/src/fn_numbers.cpp +20 -13
  69. data/ext/libsass/src/fn_selectors.cpp +98 -128
  70. data/ext/libsass/src/fn_strings.cpp +47 -33
  71. data/ext/libsass/src/fn_utils.cpp +31 -29
  72. data/ext/libsass/src/fn_utils.hpp +17 -11
  73. data/ext/libsass/src/inspect.cpp +186 -148
  74. data/ext/libsass/src/inspect.hpp +31 -29
  75. data/ext/libsass/src/lexer.cpp +20 -82
  76. data/ext/libsass/src/lexer.hpp +5 -16
  77. data/ext/libsass/src/listize.cpp +23 -37
  78. data/ext/libsass/src/listize.hpp +8 -9
  79. data/ext/libsass/src/mapping.hpp +1 -0
  80. data/ext/libsass/src/memory.hpp +12 -0
  81. data/ext/libsass/src/memory/allocator.cpp +48 -0
  82. data/ext/libsass/src/memory/allocator.hpp +138 -0
  83. data/ext/libsass/src/memory/config.hpp +20 -0
  84. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  85. data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
  86. data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +55 -9
  87. data/ext/libsass/src/operation.hpp +71 -61
  88. data/ext/libsass/src/operators.cpp +19 -18
  89. data/ext/libsass/src/operators.hpp +11 -11
  90. data/ext/libsass/src/ordered_map.hpp +112 -0
  91. data/ext/libsass/src/output.cpp +45 -64
  92. data/ext/libsass/src/output.hpp +6 -6
  93. data/ext/libsass/src/parser.cpp +512 -700
  94. data/ext/libsass/src/parser.hpp +89 -97
  95. data/ext/libsass/src/parser_selectors.cpp +189 -0
  96. data/ext/libsass/src/permutate.hpp +164 -0
  97. data/ext/libsass/src/plugins.cpp +7 -7
  98. data/ext/libsass/src/plugins.hpp +8 -8
  99. data/ext/libsass/src/position.cpp +7 -26
  100. data/ext/libsass/src/position.hpp +44 -21
  101. data/ext/libsass/src/prelexer.cpp +6 -6
  102. data/ext/libsass/src/remove_placeholders.cpp +55 -56
  103. data/ext/libsass/src/remove_placeholders.hpp +21 -18
  104. data/ext/libsass/src/sass.cpp +16 -15
  105. data/ext/libsass/src/sass.hpp +10 -5
  106. data/ext/libsass/src/sass2scss.cpp +4 -4
  107. data/ext/libsass/src/sass_context.cpp +91 -122
  108. data/ext/libsass/src/sass_context.hpp +2 -2
  109. data/ext/libsass/src/sass_functions.cpp +1 -1
  110. data/ext/libsass/src/sass_values.cpp +8 -11
  111. data/ext/libsass/src/settings.hpp +19 -0
  112. data/ext/libsass/src/source.cpp +69 -0
  113. data/ext/libsass/src/source.hpp +95 -0
  114. data/ext/libsass/src/source_data.hpp +32 -0
  115. data/ext/libsass/src/source_map.cpp +22 -18
  116. data/ext/libsass/src/source_map.hpp +12 -9
  117. data/ext/libsass/src/stylesheet.cpp +22 -0
  118. data/ext/libsass/src/stylesheet.hpp +57 -0
  119. data/ext/libsass/src/to_value.cpp +2 -2
  120. data/ext/libsass/src/to_value.hpp +1 -1
  121. data/ext/libsass/src/units.cpp +24 -22
  122. data/ext/libsass/src/units.hpp +8 -8
  123. data/ext/libsass/src/utf8_string.cpp +9 -10
  124. data/ext/libsass/src/utf8_string.hpp +7 -6
  125. data/ext/libsass/src/util.cpp +48 -50
  126. data/ext/libsass/src/util.hpp +20 -21
  127. data/ext/libsass/src/util_string.cpp +111 -61
  128. data/ext/libsass/src/util_string.hpp +62 -8
  129. data/ext/libsass/src/values.cpp +12 -12
  130. data/lib/sassc/engine.rb +5 -3
  131. data/lib/sassc/functions_handler.rb +11 -13
  132. data/lib/sassc/native.rb +9 -7
  133. data/lib/sassc/script.rb +4 -6
  134. data/lib/sassc/version.rb +1 -1
  135. data/test/functions_test.rb +38 -1
  136. data/test/native_test.rb +4 -4
  137. metadata +31 -18
  138. data/ext/libsass/src/extend.cpp +0 -2132
  139. data/ext/libsass/src/extend.hpp +0 -86
  140. data/ext/libsass/src/node.cpp +0 -322
  141. data/ext/libsass/src/node.hpp +0 -118
  142. data/ext/libsass/src/paths.hpp +0 -71
  143. data/ext/libsass/src/sass_util.cpp +0 -152
  144. data/ext/libsass/src/sass_util.hpp +0 -256
  145. data/ext/libsass/src/subset_map.cpp +0 -58
  146. data/ext/libsass/src/subset_map.hpp +0 -76
  147. data/lib/sassc/native/lib_c.rb +0 -21
@@ -5,7 +5,6 @@
5
5
  #include <cstdint>
6
6
  #include <cstdlib>
7
7
  #include <cmath>
8
- #include <cctype>
9
8
  #include <random>
10
9
  #include <sstream>
11
10
  #include <iomanip>
@@ -61,7 +60,7 @@ namespace Sass {
61
60
  BUILT_IN(percentage)
62
61
  {
63
62
  Number_Obj n = ARGN("$number");
64
- if (!n->is_unitless()) error("argument $number of `" + std::string(sig) + "` must be unitless", pstate, traces);
63
+ if (!n->is_unitless()) error("argument $number of `" + sass::string(sig) + "` must be unitless", pstate, traces);
65
64
  return SASS_MEMORY_NEW(Number, pstate, n->value() * 100, "%");
66
65
  }
67
66
 
@@ -106,8 +105,12 @@ namespace Sass {
106
105
  {
107
106
  List* arglist = ARG("$numbers", List);
108
107
  Number_Obj least;
109
- for (size_t i = 0, L = arglist->length(); i < L; ++i) {
110
- Expression_Obj val = arglist->value_at_index(i);
108
+ size_t L = arglist->length();
109
+ if (L == 0) {
110
+ error("At least one argument must be passed.", pstate, traces);
111
+ }
112
+ for (size_t i = 0; i < L; ++i) {
113
+ ExpressionObj val = arglist->value_at_index(i);
111
114
  Number_Obj xi = Cast<Number>(val);
112
115
  if (!xi) {
113
116
  error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `min'", pstate, traces);
@@ -124,8 +127,12 @@ namespace Sass {
124
127
  {
125
128
  List* arglist = ARG("$numbers", List);
126
129
  Number_Obj greatest;
127
- for (size_t i = 0, L = arglist->length(); i < L; ++i) {
128
- Expression_Obj val = arglist->value_at_index(i);
130
+ size_t L = arglist->length();
131
+ if (L == 0) {
132
+ error("At least one argument must be passed.", pstate, traces);
133
+ }
134
+ for (size_t i = 0; i < L; ++i) {
135
+ ExpressionObj val = arglist->value_at_index(i);
129
136
  Number_Obj xi = Cast<Number>(val);
130
137
  if (!xi) {
131
138
  error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `max'", pstate, traces);
@@ -147,13 +154,13 @@ namespace Sass {
147
154
  if (l) {
148
155
  double lv = l->value();
149
156
  if (lv < 1) {
150
- std::stringstream err;
157
+ sass::ostream err;
151
158
  err << "$limit " << lv << " must be greater than or equal to 1 for `random'";
152
159
  error(err.str(), pstate, traces);
153
160
  }
154
161
  bool eq_int = std::fabs(trunc(lv) - lv) < NUMBER_EPSILON;
155
162
  if (!eq_int) {
156
- std::stringstream err;
163
+ sass::ostream err;
157
164
  err << "Expected $limit to be an integer but got " << lv << " for `random'";
158
165
  error(err.str(), pstate, traces);
159
166
  }
@@ -177,7 +184,7 @@ namespace Sass {
177
184
  Signature unique_id_sig = "unique-id()";
178
185
  BUILT_IN(unique_id)
179
186
  {
180
- std::stringstream ss;
187
+ sass::ostream ss;
181
188
  std::uniform_real_distribution<> distributor(0, 4294967296); // 16^8
182
189
  uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
183
190
  ss << "u" << std::setfill('0') << std::setw(8) << std::hex << distributed;
@@ -188,7 +195,7 @@ namespace Sass {
188
195
  BUILT_IN(unit)
189
196
  {
190
197
  Number_Obj arg = ARGN("$number");
191
- std::string str(quote(arg->unit(), '"'));
198
+ sass::string str(quote(arg->unit(), '"'));
192
199
  return SASS_MEMORY_NEW(String_Quoted, pstate, str);
193
200
  }
194
201
 
@@ -200,11 +207,11 @@ namespace Sass {
200
207
  return SASS_MEMORY_NEW(Boolean, pstate, unitless);
201
208
  }
202
209
 
203
- Signature comparable_sig = "comparable($number-1, $number-2)";
210
+ Signature comparable_sig = "comparable($number1, $number2)";
204
211
  BUILT_IN(comparable)
205
212
  {
206
- Number_Obj n1 = ARGN("$number-1");
207
- Number_Obj n2 = ARGN("$number-2");
213
+ Number_Obj n1 = ARGN("$number1");
214
+ Number_Obj n2 = ARGN("$number2");
208
215
  if (n1->is_unitless() || n2->is_unitless()) {
209
216
  return SASS_MEMORY_NEW(Boolean, pstate, true);
210
217
  }
@@ -1,5 +1,8 @@
1
+ #include <numeric>
2
+
1
3
  #include "parser.hpp"
2
- #include "extend.hpp"
4
+ #include "extender.hpp"
5
+ #include "listize.hpp"
3
6
  #include "fn_utils.hpp"
4
7
  #include "fn_selectors.hpp"
5
8
 
@@ -13,24 +16,28 @@ namespace Sass {
13
16
  List* arglist = ARG("$selectors", List);
14
17
 
15
18
  // Not enough parameters
16
- if( arglist->length() == 0 )
17
- error("$selectors: At least one selector must be passed for `selector-nest'", pstate, traces);
19
+ if (arglist->length() == 0) {
20
+ error(
21
+ "$selectors: At least one selector must be passed for `selector-nest'",
22
+ pstate, traces);
23
+ }
18
24
 
19
25
  // Parse args into vector of selectors
20
26
  SelectorStack parsedSelectors;
21
27
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
22
- Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
28
+ ExpressionObj exp = Cast<Expression>(arglist->value_at_index(i));
23
29
  if (exp->concrete_type() == Expression::NULL_VAL) {
24
- std::stringstream msg;
25
- msg << "$selectors: null is not a valid selector: it must be a string,\n";
26
- msg << "a list of strings, or a list of lists of strings for 'selector-nest'";
27
- error(msg.str(), pstate, traces);
30
+ error(
31
+ "$selectors: null is not a valid selector: it must be a string,\n"
32
+ "a list of strings, or a list of lists of strings for 'selector-nest'",
33
+ pstate, traces);
28
34
  }
29
35
  if (String_Constant_Obj str = Cast<String_Constant>(exp)) {
30
36
  str->quote_mark(0);
31
37
  }
32
- std::string exp_src = exp->to_string(ctx.c_options);
33
- Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
38
+ sass::string exp_src = exp->to_string(ctx.c_options);
39
+ ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate());
40
+ SelectorListObj sel = Parser::parse_selector(source, ctx, traces);
34
41
  parsedSelectors.push_back(sel);
35
42
  }
36
43
 
@@ -39,25 +46,21 @@ namespace Sass {
39
46
  return SASS_MEMORY_NEW(Null, pstate);
40
47
  }
41
48
 
42
- // Set the first element as the `result`, keep appending to as we go down the parsedSelector vector.
49
+ // Set the first element as the `result`, keep
50
+ // appending to as we go down the parsedSelector vector.
43
51
  SelectorStack::iterator itr = parsedSelectors.begin();
44
- Selector_List_Obj result = *itr;
52
+ SelectorListObj& result = *itr;
45
53
  ++itr;
46
54
 
47
55
  for(;itr != parsedSelectors.end(); ++itr) {
48
- Selector_List_Obj child = *itr;
49
- std::vector<Complex_Selector_Obj> exploded;
50
- selector_stack.push_back(result);
51
- Selector_List_Obj rv = child->resolve_parent_refs(selector_stack, traces);
52
- selector_stack.pop_back();
53
- for (size_t m = 0, mLen = rv->length(); m < mLen; ++m) {
54
- exploded.push_back((*rv)[m]);
55
- }
56
- result->elements(exploded);
56
+ SelectorListObj& child = *itr;
57
+ original_stack.push_back(result);
58
+ SelectorListObj rv = child->resolve_parent_refs(original_stack, traces);
59
+ result->elements(rv->elements());
60
+ original_stack.pop_back();
57
61
  }
58
62
 
59
- Listize listize;
60
- return Cast<Value>(result->perform(&listize));
63
+ return Cast<Value>(Listize::perform(result));
61
64
  }
62
65
 
63
66
  Signature selector_append_sig = "selector-append($selectors...)";
@@ -66,113 +69,95 @@ namespace Sass {
66
69
  List* arglist = ARG("$selectors", List);
67
70
 
68
71
  // Not enough parameters
69
- if( arglist->length() == 0 )
70
- error("$selectors: At least one selector must be passed for `selector-append'", pstate, traces);
72
+ if (arglist->empty()) {
73
+ error(
74
+ "$selectors: At least one selector must be "
75
+ "passed for `selector-append'",
76
+ pstate, traces);
77
+ }
71
78
 
72
79
  // Parse args into vector of selectors
73
80
  SelectorStack parsedSelectors;
81
+ parsedSelectors.push_back({});
74
82
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
75
- Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
83
+ Expression* exp = Cast<Expression>(arglist->value_at_index(i));
76
84
  if (exp->concrete_type() == Expression::NULL_VAL) {
77
- std::stringstream msg;
78
- msg << "$selectors: null is not a valid selector: it must be a string,\n";
79
- msg << "a list of strings, or a list of lists of strings for 'selector-append'";
80
- error(msg.str(), pstate, traces);
85
+ error(
86
+ "$selectors: null is not a valid selector: it must be a string,\n"
87
+ "a list of strings, or a list of lists of strings for 'selector-append'",
88
+ pstate, traces);
81
89
  }
82
90
  if (String_Constant* str = Cast<String_Constant>(exp)) {
83
91
  str->quote_mark(0);
84
92
  }
85
- std::string exp_src = exp->to_string();
86
- Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces,
87
- exp->pstate(), pstate.src,
88
- /*allow_parent=*/false);
89
-
90
- parsedSelectors.push_back(sel);
91
- }
93
+ sass::string exp_src = exp->to_string();
94
+ ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate());
95
+ SelectorListObj sel = Parser::parse_selector(source, ctx, traces, true);
92
96
 
93
- // Nothing to do
94
- if( parsedSelectors.empty() ) {
95
- return SASS_MEMORY_NEW(Null, pstate);
96
- }
97
-
98
- // Set the first element as the `result`, keep appending to as we go down the parsedSelector vector.
99
- SelectorStack::iterator itr = parsedSelectors.begin();
100
- Selector_List_Obj result = *itr;
101
- ++itr;
102
-
103
- for(;itr != parsedSelectors.end(); ++itr) {
104
- Selector_List_Obj child = *itr;
105
- std::vector<Complex_Selector_Obj> newElements;
106
-
107
- // For every COMPLEX_SELECTOR in `result`
108
- // For every COMPLEX_SELECTOR in `child`
109
- // let parentSeqClone equal a copy of result->elements[i]
110
- // let childSeq equal child->elements[j]
111
- // Append all of childSeq head elements into parentSeqClone
112
- // Set the innermost tail of parentSeqClone, to childSeq's tail
113
- // Replace result->elements with newElements
114
- for (size_t i = 0, resultLen = result->length(); i < resultLen; ++i) {
115
- for (size_t j = 0, childLen = child->length(); j < childLen; ++j) {
116
- Complex_Selector_Obj parentSeqClone = SASS_MEMORY_CLONE((*result)[i]);
117
- Complex_Selector_Obj childSeq = (*child)[j];
118
- Complex_Selector_Obj base = childSeq->tail();
119
-
120
- // Must be a simple sequence
121
- if( childSeq->combinator() != Complex_Selector::Combinator::ANCESTOR_OF ) {
122
- error("Can't append \"" + childSeq->to_string() + "\" to \"" +
123
- parentSeqClone->to_string() + "\" for `selector-append'", pstate, traces);
124
- }
125
-
126
- // Cannot be a Universal selector
127
- Type_Selector_Obj pType = Cast<Type_Selector>(childSeq->head()->first());
128
- if(pType && pType->name() == "*") {
129
- error("Can't append \"" + childSeq->to_string() + "\" to \"" +
130
- parentSeqClone->to_string() + "\" for `selector-append'", pstate, traces);
131
- }
97
+ for (auto& complex : sel->elements()) {
98
+ if (complex->empty()) {
99
+ complex->append(SASS_MEMORY_NEW(CompoundSelector, "[phony]"));
100
+ }
101
+ if (CompoundSelector* comp = Cast<CompoundSelector>(complex->first())) {
102
+ comp->hasRealParent(true);
103
+ complex->chroots(true);
104
+ }
105
+ }
132
106
 
133
- // TODO: Add check for namespace stuff
107
+ if (parsedSelectors.size() > 1) {
134
108
 
135
- Complex_Selector* lastComponent = parentSeqClone->mutable_last();
136
- if (lastComponent->head() == nullptr) {
137
- std::string msg = "Parent \"" + parentSeqClone->to_string() + "\" is incompatible with \"" + base->to_string() + "\"";
138
- error(msg, pstate, traces);
109
+ if (!sel->has_real_parent_ref()) {
110
+ auto parent = parsedSelectors.back();
111
+ for (auto& complex : parent->elements()) {
112
+ if (CompoundSelector* comp = Cast<CompoundSelector>(complex->first())) {
113
+ comp->hasRealParent(false);
114
+ }
139
115
  }
140
- lastComponent->head()->concat(base->head());
141
- lastComponent->tail(base->tail());
142
-
143
- newElements.push_back(parentSeqClone);
116
+ error("Can't append \"" + sel->to_string() + "\" to \"" +
117
+ parent->to_string() + "\" for `selector-append'",
118
+ pstate, traces);
144
119
  }
120
+
121
+ // Build the resolved stack from the left. It's cheaper to directly
122
+ // calculate and update each resolved selcted from the left, than to
123
+ // recursively calculate them from the right side, as we would need
124
+ // to go through the whole stack depth to build the final results.
125
+ // E.g. 'a', 'b', 'x, y' => 'a' => 'a b' => 'a b x, a b y'
126
+ // vs 'a', 'b', 'x, y' => 'x' => 'b x' => 'a b x', 'y' ...
127
+ parsedSelectors.push_back(sel->resolve_parent_refs(parsedSelectors, traces, true));
145
128
  }
129
+ else {
130
+ parsedSelectors.push_back(sel);
131
+ }
132
+ }
146
133
 
147
- result->elements(newElements);
134
+ // Nothing to do
135
+ if( parsedSelectors.empty() ) {
136
+ return SASS_MEMORY_NEW(Null, pstate);
148
137
  }
149
138
 
150
- Listize listize;
151
- return Cast<Value>(result->perform(&listize));
139
+ return Cast<Value>(Listize::perform(parsedSelectors.back()));
152
140
  }
153
141
 
154
142
  Signature selector_unify_sig = "selector-unify($selector1, $selector2)";
155
143
  BUILT_IN(selector_unify)
156
144
  {
157
- Selector_List_Obj selector1 = ARGSELS("$selector1");
158
- Selector_List_Obj selector2 = ARGSELS("$selector2");
159
-
160
- Selector_List_Obj result = selector1->unify_with(selector2);
161
- Listize listize;
162
- return Cast<Value>(result->perform(&listize));
145
+ SelectorListObj selector1 = ARGSELS("$selector1");
146
+ SelectorListObj selector2 = ARGSELS("$selector2");
147
+ SelectorListObj result = selector1->unifyWith(selector2);
148
+ return Cast<Value>(Listize::perform(result));
163
149
  }
164
150
 
165
151
  Signature simple_selectors_sig = "simple-selectors($selector)";
166
152
  BUILT_IN(simple_selectors)
167
153
  {
168
- Compound_Selector_Obj sel = ARGSEL("$selector");
154
+ CompoundSelectorObj sel = ARGSEL("$selector");
169
155
 
170
156
  List* l = SASS_MEMORY_NEW(List, sel->pstate(), sel->length(), SASS_COMMA);
171
157
 
172
158
  for (size_t i = 0, L = sel->length(); i < L; ++i) {
173
- Simple_Selector_Obj ss = (*sel)[i];
174
- std::string ss_string = ss->to_string() ;
175
-
159
+ const SimpleSelectorObj& ss = sel->get(i);
160
+ sass::string ss_string = ss->to_string() ;
176
161
  l->append(SASS_MEMORY_NEW(String_Quoted, ss->pstate(), ss_string));
177
162
  }
178
163
 
@@ -182,51 +167,36 @@ namespace Sass {
182
167
  Signature selector_extend_sig = "selector-extend($selector, $extendee, $extender)";
183
168
  BUILT_IN(selector_extend)
184
169
  {
185
- Selector_List_Obj selector = ARGSELS("$selector");
186
- Selector_List_Obj extendee = ARGSELS("$extendee");
187
- Selector_List_Obj extender = ARGSELS("$extender");
188
-
189
- Subset_Map subset_map;
190
- extender->populate_extends(extendee, subset_map);
191
- Extend extend(subset_map);
192
-
193
- Selector_List_Obj result = extend.extendSelectorList(selector, false);
194
-
195
- Listize listize;
196
- return Cast<Value>(result->perform(&listize));
170
+ SelectorListObj selector = ARGSELS("$selector");
171
+ SelectorListObj target = ARGSELS("$extendee");
172
+ SelectorListObj source = ARGSELS("$extender");
173
+ SelectorListObj result = Extender::extend(selector, source, target, traces);
174
+ return Cast<Value>(Listize::perform(result));
197
175
  }
198
176
 
199
177
  Signature selector_replace_sig = "selector-replace($selector, $original, $replacement)";
200
178
  BUILT_IN(selector_replace)
201
179
  {
202
- Selector_List_Obj selector = ARGSELS("$selector");
203
- Selector_List_Obj original = ARGSELS("$original");
204
- Selector_List_Obj replacement = ARGSELS("$replacement");
205
- Subset_Map subset_map;
206
- replacement->populate_extends(original, subset_map);
207
- Extend extend(subset_map);
208
-
209
- Selector_List_Obj result = extend.extendSelectorList(selector, true);
210
-
211
- Listize listize;
212
- return Cast<Value>(result->perform(&listize));
180
+ SelectorListObj selector = ARGSELS("$selector");
181
+ SelectorListObj target = ARGSELS("$original");
182
+ SelectorListObj source = ARGSELS("$replacement");
183
+ SelectorListObj result = Extender::replace(selector, source, target, traces);
184
+ return Cast<Value>(Listize::perform(result));
213
185
  }
214
186
 
215
187
  Signature selector_parse_sig = "selector-parse($selector)";
216
188
  BUILT_IN(selector_parse)
217
189
  {
218
- Selector_List_Obj sel = ARGSELS("$selector");
219
-
220
- Listize listize;
221
- return Cast<Value>(sel->perform(&listize));
190
+ SelectorListObj selector = ARGSELS("$selector");
191
+ return Cast<Value>(Listize::perform(selector));
222
192
  }
223
193
 
224
194
  Signature is_superselector_sig = "is-superselector($super, $sub)";
225
195
  BUILT_IN(is_superselector)
226
196
  {
227
- Selector_List_Obj sel_sup = ARGSELS("$super");
228
- Selector_List_Obj sel_sub = ARGSELS("$sub");
229
- bool result = sel_sup->is_superselector_of(sel_sub);
197
+ SelectorListObj sel_sup = ARGSELS("$super");
198
+ SelectorListObj sel_sub = ARGSELS("$sub");
199
+ bool result = sel_sup->isSuperselectorOf(sel_sub);
230
200
  return SASS_MEMORY_NEW(Boolean, pstate, result);
231
201
  }
232
202
 
@@ -2,31 +2,31 @@
2
2
  // __EXTENSIONS__ fix on Solaris.
3
3
  #include "sass.hpp"
4
4
 
5
- #include <cctype>
6
5
  #include "utf8.h"
7
6
  #include "ast.hpp"
8
7
  #include "fn_utils.hpp"
9
8
  #include "fn_strings.hpp"
9
+ #include "util_string.hpp"
10
10
 
11
11
  namespace Sass {
12
12
 
13
13
  namespace Functions {
14
14
 
15
- void handle_utf8_error (const ParserState& pstate, Backtraces traces)
15
+ void handle_utf8_error (const SourceSpan& pstate, Backtraces traces)
16
16
  {
17
17
  try {
18
18
  throw;
19
19
  }
20
20
  catch (utf8::invalid_code_point&) {
21
- std::string msg("utf8::invalid_code_point");
21
+ sass::string msg("utf8::invalid_code_point");
22
22
  error(msg, pstate, traces);
23
23
  }
24
24
  catch (utf8::not_enough_room&) {
25
- std::string msg("utf8::not_enough_room");
25
+ sass::string msg("utf8::not_enough_room");
26
26
  error(msg, pstate, traces);
27
27
  }
28
28
  catch (utf8::invalid_utf8&) {
29
- std::string msg("utf8::invalid_utf8");
29
+ sass::string msg("utf8::invalid_utf8");
30
30
  error(msg, pstate, traces);
31
31
  }
32
32
  catch (...) { throw; }
@@ -52,7 +52,7 @@ namespace Sass {
52
52
  else if (Value* ex = Cast<Value>(arg)) {
53
53
  Sass_Output_Style oldstyle = ctx.c_options.output_style;
54
54
  ctx.c_options.output_style = SASS_STYLE_NESTED;
55
- std::string val(arg->to_string(ctx.c_options));
55
+ sass::string val(arg->to_string(ctx.c_options));
56
56
  val = Cast<Null>(arg) ? "null" : val;
57
57
  ctx.c_options.output_style = oldstyle;
58
58
 
@@ -76,7 +76,7 @@ namespace Sass {
76
76
  Signature str_length_sig = "str-length($string)";
77
77
  BUILT_IN(str_length)
78
78
  {
79
- size_t len = std::string::npos;
79
+ size_t len = sass::string::npos;
80
80
  try {
81
81
  String_Constant* s = ARG("$string", String_Constant);
82
82
  len = UTF_8::code_point_count(s->value(), 0, s->value().size());
@@ -92,13 +92,20 @@ namespace Sass {
92
92
  Signature str_insert_sig = "str-insert($string, $insert, $index)";
93
93
  BUILT_IN(str_insert)
94
94
  {
95
- std::string str;
95
+ sass::string str;
96
96
  try {
97
97
  String_Constant* s = ARG("$string", String_Constant);
98
98
  str = s->value();
99
99
  String_Constant* i = ARG("$insert", String_Constant);
100
- std::string ins = i->value();
100
+ sass::string ins = i->value();
101
101
  double index = ARGVAL("$index");
102
+ if (index != (int)index) {
103
+ sass::ostream strm;
104
+ strm << "$index: ";
105
+ strm << std::to_string(index);
106
+ strm << " is not an int";
107
+ error(strm.str(), pstate, traces);
108
+ }
102
109
  size_t len = UTF_8::code_point_count(str, 0, str.size());
103
110
 
104
111
  if (index > 0 && index <= len) {
@@ -135,15 +142,15 @@ namespace Sass {
135
142
  Signature str_index_sig = "str-index($string, $substring)";
136
143
  BUILT_IN(str_index)
137
144
  {
138
- size_t index = std::string::npos;
145
+ size_t index = sass::string::npos;
139
146
  try {
140
147
  String_Constant* s = ARG("$string", String_Constant);
141
148
  String_Constant* t = ARG("$substring", String_Constant);
142
- std::string str = s->value();
143
- std::string substr = t->value();
149
+ sass::string str = s->value();
150
+ sass::string substr = t->value();
144
151
 
145
152
  size_t c_index = str.find(substr);
146
- if(c_index == std::string::npos) {
153
+ if(c_index == sass::string::npos) {
147
154
  return SASS_MEMORY_NEW(Null, pstate);
148
155
  }
149
156
  index = UTF_8::code_point_count(str, 0, c_index) + 1;
@@ -158,14 +165,23 @@ namespace Sass {
158
165
  Signature str_slice_sig = "str-slice($string, $start-at, $end-at:-1)";
159
166
  BUILT_IN(str_slice)
160
167
  {
161
- std::string newstr;
168
+ sass::string newstr;
162
169
  try {
163
170
  String_Constant* s = ARG("$string", String_Constant);
164
171
  double start_at = ARGVAL("$start-at");
165
172
  double end_at = ARGVAL("$end-at");
173
+
174
+ if (start_at != (int)start_at) {
175
+ sass::ostream strm;
176
+ strm << "$start-at: ";
177
+ strm << std::to_string(start_at);
178
+ strm << " is not an int";
179
+ error(strm.str(), pstate, traces);
180
+ }
181
+
166
182
  String_Quoted* ss = Cast<String_Quoted>(s);
167
183
 
168
- std::string str(s->value());
184
+ sass::string str(s->value());
169
185
 
170
186
  size_t size = utf8::distance(str.begin(), str.end());
171
187
 
@@ -173,6 +189,14 @@ namespace Sass {
173
189
  end_at = -1;
174
190
  }
175
191
 
192
+ if (end_at != (int)end_at) {
193
+ sass::ostream strm;
194
+ strm << "$end-at: ";
195
+ strm << std::to_string(end_at);
196
+ strm << " is not an int";
197
+ error(strm.str(), pstate, traces);
198
+ }
199
+
176
200
  if (end_at == 0 || (end_at + size) < 0) {
177
201
  if (ss && ss->quote_mark()) newstr = quote("");
178
202
  return SASS_MEMORY_NEW(String_Quoted, pstate, newstr);
@@ -185,17 +209,17 @@ namespace Sass {
185
209
  if (end_at > size) { end_at = (double)size; }
186
210
  if (start_at < 0) {
187
211
  start_at += size + 1;
188
- if (start_at < 0) start_at = 0;
212
+ if (start_at <= 0) start_at = 1;
189
213
  }
190
214
  else if (start_at == 0) { ++ start_at; }
191
215
 
192
216
  if (start_at <= end_at)
193
217
  {
194
- std::string::iterator start = str.begin();
218
+ sass::string::iterator start = str.begin();
195
219
  utf8::advance(start, start_at - 1, str.end());
196
- std::string::iterator end = start;
220
+ sass::string::iterator end = start;
197
221
  utf8::advance(end, end_at - start_at + 1, str.end());
198
- newstr = std::string(start, end);
222
+ newstr = sass::string(start, end);
199
223
  }
200
224
  if (ss) {
201
225
  if(ss->quote_mark()) newstr = quote(newstr);
@@ -211,13 +235,8 @@ namespace Sass {
211
235
  BUILT_IN(to_upper_case)
212
236
  {
213
237
  String_Constant* s = ARG("$string", String_Constant);
214
- std::string str = s->value();
215
-
216
- for (size_t i = 0, L = str.length(); i < L; ++i) {
217
- if (Sass::Util::isAscii(str[i])) {
218
- str[i] = std::toupper(str[i]);
219
- }
220
- }
238
+ sass::string str = s->value();
239
+ Util::ascii_str_toupper(&str);
221
240
 
222
241
  if (String_Quoted* ss = Cast<String_Quoted>(s)) {
223
242
  String_Quoted* cpy = SASS_MEMORY_COPY(ss);
@@ -232,13 +251,8 @@ namespace Sass {
232
251
  BUILT_IN(to_lower_case)
233
252
  {
234
253
  String_Constant* s = ARG("$string", String_Constant);
235
- std::string str = s->value();
236
-
237
- for (size_t i = 0, L = str.length(); i < L; ++i) {
238
- if (Sass::Util::isAscii(str[i])) {
239
- str[i] = std::tolower(str[i]);
240
- }
241
- }
254
+ sass::string str = s->value();
255
+ Util::ascii_str_tolower(&str);
242
256
 
243
257
  if (String_Quoted* ss = Cast<String_Quoted>(s)) {
244
258
  String_Quoted* cpy = SASS_MEMORY_COPY(ss);