1 // sass.hpp must go before all system headers to get the
2 // __EXTENSIONS__ fix on Solaris.
3 #include "sass.hpp"
4 #include "ast.hpp"
5 
6 namespace Sass {
7 
str_rtrim(sass::string & str,const sass::string & delimiters=" \\f\\n\\r\\t\\v")8   void str_rtrim(sass::string& str, const sass::string& delimiters = " \f\n\r\t\v")
9   {
10     str.erase( str.find_last_not_of( delimiters ) + 1 );
11   }
12 
13   /////////////////////////////////////////////////////////////////////////
14   /////////////////////////////////////////////////////////////////////////
15 
PreValue(SourceSpan pstate,bool d,bool e,bool i,Type ct)16   PreValue::PreValue(SourceSpan pstate, bool d, bool e, bool i, Type ct)
17   : Expression(pstate, d, e, i, ct)
18   { }
PreValue(const PreValue * ptr)19   PreValue::PreValue(const PreValue* ptr)
20   : Expression(ptr)
21   { }
22 
23   /////////////////////////////////////////////////////////////////////////
24   /////////////////////////////////////////////////////////////////////////
25 
Value(SourceSpan pstate,bool d,bool e,bool i,Type ct)26   Value::Value(SourceSpan pstate, bool d, bool e, bool i, Type ct)
27   : PreValue(pstate, d, e, i, ct)
28   { }
Value(const Value * ptr)29   Value::Value(const Value* ptr)
30   : PreValue(ptr)
31   { }
32 
33   /////////////////////////////////////////////////////////////////////////
34   /////////////////////////////////////////////////////////////////////////
35 
List(SourceSpan pstate,size_t size,enum Sass_Separator sep,bool argl,bool bracket)36   List::List(SourceSpan pstate, size_t size, enum Sass_Separator sep, bool argl, bool bracket)
37   : Value(pstate),
38     Vectorized<ExpressionObj>(size),
39     separator_(sep),
40     is_arglist_(argl),
41     is_bracketed_(bracket),
42     from_selector_(false)
43   { concrete_type(LIST); }
44 
List(const List * ptr)45   List::List(const List* ptr)
46   : Value(ptr),
47     Vectorized<ExpressionObj>(*ptr),
48     separator_(ptr->separator_),
49     is_arglist_(ptr->is_arglist_),
50     is_bracketed_(ptr->is_bracketed_),
51     from_selector_(ptr->from_selector_)
52   { concrete_type(LIST); }
53 
hash() const54   size_t List::hash() const
55   {
56     if (hash_ == 0) {
57       hash_ = std::hash<sass::string>()(sep_string());
58       hash_combine(hash_, std::hash<bool>()(is_bracketed()));
59       for (size_t i = 0, L = length(); i < L; ++i)
60         hash_combine(hash_, (elements()[i])->hash());
61     }
62     return hash_;
63   }
64 
set_delayed(bool delayed)65   void List::set_delayed(bool delayed)
66   {
67     is_delayed(delayed);
68     // don't set children
69   }
70 
operator <(const Expression & rhs) const71   bool List::operator< (const Expression& rhs) const
72   {
73     if (auto r = Cast<List>(&rhs)) {
74       if (length() < r->length()) return true;
75       if (length() > r->length()) return false;
76       const auto& left = elements();
77       const auto& right = r->elements();
78       for (size_t i = 0; i < left.size(); i += 1) {
79         if (*left[i] < *right[i]) return true;
80         if (*left[i] == *right[i]) continue;
81         return false;
82       }
83       return false;
84     }
85     // compare/sort by type
86     return type() < rhs.type();
87   }
88 
operator ==(const Expression & rhs) const89   bool List::operator== (const Expression& rhs) const
90   {
91     if (auto r = Cast<List>(&rhs)) {
92       if (length() != r->length()) return false;
93       if (separator() != r->separator()) return false;
94       if (is_bracketed() != r->is_bracketed()) return false;
95       for (size_t i = 0, L = length(); i < L; ++i) {
96         auto rv = r->at(i);
97         auto lv = this->at(i);
98         if (!lv && rv) return false;
99         else if (!rv && lv) return false;
100         else if (*lv != *rv) return false;
101       }
102       return true;
103     }
104     return false;
105   }
106 
size() const107   size_t List::size() const {
108     if (!is_arglist_) return length();
109     // arglist expects a list of arguments
110     // so we need to break before keywords
111     for (size_t i = 0, L = length(); i < L; ++i) {
112       ExpressionObj obj = this->at(i);
113       if (Argument* arg = Cast<Argument>(obj)) {
114         if (!arg->name().empty()) return i;
115       }
116     }
117     return length();
118   }
119 
120 
value_at_index(size_t i)121   ExpressionObj List::value_at_index(size_t i) {
122     ExpressionObj obj = this->at(i);
123     if (is_arglist_) {
124       if (Argument* arg = Cast<Argument>(obj)) {
125         return arg->value();
126       } else {
127         return obj;
128       }
129     } else {
130       return obj;
131     }
132   }
133 
134   /////////////////////////////////////////////////////////////////////////
135   /////////////////////////////////////////////////////////////////////////
136 
Map(SourceSpan pstate,size_t size)137   Map::Map(SourceSpan pstate, size_t size)
138   : Value(pstate),
139     Hashed(size)
140   { concrete_type(MAP); }
141 
Map(const Map * ptr)142   Map::Map(const Map* ptr)
143   : Value(ptr),
144     Hashed(*ptr)
145   { concrete_type(MAP); }
146 
operator <(const Expression & rhs) const147   bool Map::operator< (const Expression& rhs) const
148   {
149     if (auto r = Cast<Map>(&rhs)) {
150       if (length() < r->length()) return true;
151       if (length() > r->length()) return false;
152       const auto& lkeys = keys();
153       const auto& rkeys = r->keys();
154       for (size_t i = 0; i < lkeys.size(); i += 1) {
155         if (*lkeys[i] < *rkeys[i]) return true;
156         if (*lkeys[i] == *rkeys[i]) continue;
157         return false;
158       }
159       const auto& lvals = values();
160       const auto& rvals = r->values();
161       for (size_t i = 0; i < lvals.size(); i += 1) {
162         if (*lvals[i] < *rvals[i]) return true;
163         if (*lvals[i] == *rvals[i]) continue;
164         return false;
165       }
166       return false;
167     }
168     // compare/sort by type
169     return type() < rhs.type();
170   }
171 
operator ==(const Expression & rhs) const172   bool Map::operator== (const Expression& rhs) const
173   {
174     if (auto r = Cast<Map>(&rhs)) {
175       if (length() != r->length()) return false;
176       for (auto key : keys()) {
177         auto rv = r->at(key);
178         auto lv = this->at(key);
179         if (!lv && rv) return false;
180         else if (!rv && lv) return false;
181         else if (*lv != *rv) return false;
182       }
183       return true;
184     }
185     return false;
186   }
187 
to_list(SourceSpan & pstate)188   List_Obj Map::to_list(SourceSpan& pstate) {
189     List_Obj ret = SASS_MEMORY_NEW(List, pstate, length(), SASS_COMMA);
190 
191     for (auto key : keys()) {
192       List_Obj l = SASS_MEMORY_NEW(List, pstate, 2);
193       l->append(key);
194       l->append(at(key));
195       ret->append(l);
196     }
197 
198     return ret;
199   }
200 
hash() const201   size_t Map::hash() const
202   {
203     if (hash_ == 0) {
204       for (auto key : keys()) {
205         hash_combine(hash_, key->hash());
206         hash_combine(hash_, at(key)->hash());
207       }
208     }
209 
210     return hash_;
211   }
212 
213   /////////////////////////////////////////////////////////////////////////
214   /////////////////////////////////////////////////////////////////////////
215 
Binary_Expression(SourceSpan pstate,Operand op,ExpressionObj lhs,ExpressionObj rhs)216   Binary_Expression::Binary_Expression(SourceSpan pstate,
217                     Operand op, ExpressionObj lhs, ExpressionObj rhs)
218   : PreValue(pstate), op_(op), left_(lhs), right_(rhs), hash_(0)
219   { }
220 
Binary_Expression(const Binary_Expression * ptr)221   Binary_Expression::Binary_Expression(const Binary_Expression* ptr)
222   : PreValue(ptr),
223     op_(ptr->op_),
224     left_(ptr->left_),
225     right_(ptr->right_),
226     hash_(ptr->hash_)
227   { }
228 
is_left_interpolant(void) const229   bool Binary_Expression::is_left_interpolant(void) const
230   {
231     return is_interpolant() || (left() && left()->is_left_interpolant());
232   }
is_right_interpolant(void) const233   bool Binary_Expression::is_right_interpolant(void) const
234   {
235     return is_interpolant() || (right() && right()->is_right_interpolant());
236   }
237 
type_name()238   const sass::string Binary_Expression::type_name()
239   {
240     return sass_op_to_name(optype());
241   }
242 
separator()243   const sass::string Binary_Expression::separator()
244   {
245     return sass_op_separator(optype());
246   }
247 
has_interpolant() const248   bool Binary_Expression::has_interpolant() const
249   {
250     return is_left_interpolant() ||
251             is_right_interpolant();
252   }
253 
set_delayed(bool delayed)254   void Binary_Expression::set_delayed(bool delayed)
255   {
256     right()->set_delayed(delayed);
257     left()->set_delayed(delayed);
258     is_delayed(delayed);
259   }
260 
operator <(const Expression & rhs) const261   bool Binary_Expression::operator<(const Expression& rhs) const
262   {
263     if (auto m = Cast<Binary_Expression>(&rhs)) {
264       return type() < m->type() ||
265         *left() < *m->left() ||
266         *right() < *m->right();
267     }
268     // compare/sort by type
269     return type() < rhs.type();
270   }
271 
operator ==(const Expression & rhs) const272   bool Binary_Expression::operator==(const Expression& rhs) const
273   {
274     if (auto m = Cast<Binary_Expression>(&rhs)) {
275       return type() == m->type() &&
276              *left() == *m->left() &&
277              *right() == *m->right();
278     }
279     return false;
280   }
281 
hash() const282   size_t Binary_Expression::hash() const
283   {
284     if (hash_ == 0) {
285       hash_ = std::hash<size_t>()(optype());
286       hash_combine(hash_, left()->hash());
287       hash_combine(hash_, right()->hash());
288     }
289     return hash_;
290   }
291 
292   /////////////////////////////////////////////////////////////////////////
293   /////////////////////////////////////////////////////////////////////////
294 
Function(SourceSpan pstate,Definition_Obj def,bool css)295   Function::Function(SourceSpan pstate, Definition_Obj def, bool css)
296   : Value(pstate), definition_(def), is_css_(css)
297   { concrete_type(FUNCTION_VAL); }
298 
Function(const Function * ptr)299   Function::Function(const Function* ptr)
300   : Value(ptr), definition_(ptr->definition_), is_css_(ptr->is_css_)
301   { concrete_type(FUNCTION_VAL); }
302 
operator <(const Expression & rhs) const303   bool Function::operator< (const Expression& rhs) const
304   {
305     if (auto r = Cast<Function>(&rhs)) {
306       auto d1 = Cast<Definition>(definition());
307       auto d2 = Cast<Definition>(r->definition());
308       if (d1 == nullptr) return d2 != nullptr;
309       else if (d2 == nullptr) return false;
310       if (is_css() == r->is_css()) {
311         return d1 < d2;
312       }
313       return r->is_css();
314     }
315     // compare/sort by type
316     return type() < rhs.type();
317   }
318 
operator ==(const Expression & rhs) const319   bool Function::operator== (const Expression& rhs) const
320   {
321     if (auto r = Cast<Function>(&rhs)) {
322       auto d1 = Cast<Definition>(definition());
323       auto d2 = Cast<Definition>(r->definition());
324       return d1 && d2 && d1 == d2 && is_css() == r->is_css();
325     }
326     return false;
327   }
328 
name()329   sass::string Function::name() {
330     if (definition_) {
331       return definition_->name();
332     }
333     return "";
334   }
335 
336   /////////////////////////////////////////////////////////////////////////
337   /////////////////////////////////////////////////////////////////////////
338 
Function_Call(SourceSpan pstate,String_Obj n,Arguments_Obj args,void * cookie)339   Function_Call::Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args, void* cookie)
340   : PreValue(pstate), sname_(n), arguments_(args), func_(), via_call_(false), cookie_(cookie), hash_(0)
341   { concrete_type(FUNCTION); }
Function_Call(SourceSpan pstate,String_Obj n,Arguments_Obj args,Function_Obj func)342   Function_Call::Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args, Function_Obj func)
343   : PreValue(pstate), sname_(n), arguments_(args), func_(func), via_call_(false), cookie_(0), hash_(0)
344   { concrete_type(FUNCTION); }
Function_Call(SourceSpan pstate,String_Obj n,Arguments_Obj args)345   Function_Call::Function_Call(SourceSpan pstate, String_Obj n, Arguments_Obj args)
346   : PreValue(pstate), sname_(n), arguments_(args), via_call_(false), cookie_(0), hash_(0)
347   { concrete_type(FUNCTION); }
348 
Function_Call(SourceSpan pstate,sass::string n,Arguments_Obj args,void * cookie)349   Function_Call::Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, void* cookie)
350   : PreValue(pstate), sname_(SASS_MEMORY_NEW(String_Constant, pstate, n)), arguments_(args), func_(), via_call_(false), cookie_(cookie), hash_(0)
351   { concrete_type(FUNCTION); }
Function_Call(SourceSpan pstate,sass::string n,Arguments_Obj args,Function_Obj func)352   Function_Call::Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, Function_Obj func)
353   : PreValue(pstate), sname_(SASS_MEMORY_NEW(String_Constant, pstate, n)), arguments_(args), func_(func), via_call_(false), cookie_(0), hash_(0)
354   { concrete_type(FUNCTION); }
Function_Call(SourceSpan pstate,sass::string n,Arguments_Obj args)355   Function_Call::Function_Call(SourceSpan pstate, sass::string n, Arguments_Obj args)
356   : PreValue(pstate), sname_(SASS_MEMORY_NEW(String_Constant, pstate, n)), arguments_(args), via_call_(false), cookie_(0), hash_(0)
357   { concrete_type(FUNCTION); }
358 
Function_Call(const Function_Call * ptr)359   Function_Call::Function_Call(const Function_Call* ptr)
360   : PreValue(ptr),
361     sname_(ptr->sname_),
362     arguments_(ptr->arguments_),
363     func_(ptr->func_),
364     via_call_(ptr->via_call_),
365     cookie_(ptr->cookie_),
366     hash_(ptr->hash_)
367   { concrete_type(FUNCTION); }
368 
operator ==(const Expression & rhs) const369   bool Function_Call::operator==(const Expression& rhs) const
370   {
371     if (auto m = Cast<Function_Call>(&rhs)) {
372       if (*sname() != *m->sname()) return false;
373       if (arguments()->length() != m->arguments()->length()) return false;
374       for (size_t i = 0, L = arguments()->length(); i < L; ++i)
375         if (*arguments()->get(i) != *m->arguments()->get(i)) return false;
376       return true;
377     }
378     return false;
379   }
380 
hash() const381   size_t Function_Call::hash() const
382   {
383     if (hash_ == 0) {
384       hash_ = std::hash<sass::string>()(name());
385       for (auto argument : arguments()->elements())
386         hash_combine(hash_, argument->hash());
387     }
388     return hash_;
389   }
390 
name() const391   sass::string Function_Call::name() const
392   {
393     return sname();
394   }
395 
is_css()396   bool Function_Call::is_css() {
397     if (func_) return func_->is_css();
398     return false;
399   }
400 
401   /////////////////////////////////////////////////////////////////////////
402   /////////////////////////////////////////////////////////////////////////
403 
Variable(SourceSpan pstate,sass::string n)404   Variable::Variable(SourceSpan pstate, sass::string n)
405   : PreValue(pstate), name_(n)
406   { concrete_type(VARIABLE); }
407 
Variable(const Variable * ptr)408   Variable::Variable(const Variable* ptr)
409   : PreValue(ptr), name_(ptr->name_)
410   { concrete_type(VARIABLE); }
411 
operator ==(const Expression & rhs) const412   bool Variable::operator==(const Expression& rhs) const
413   {
414     if (auto e = Cast<Variable>(&rhs)) {
415       return name() == e->name();
416     }
417     return false;
418   }
419 
hash() const420   size_t Variable::hash() const
421   {
422     return std::hash<sass::string>()(name());
423   }
424 
425   /////////////////////////////////////////////////////////////////////////
426   /////////////////////////////////////////////////////////////////////////
427 
Number(SourceSpan pstate,double val,sass::string u,bool zero)428   Number::Number(SourceSpan pstate, double val, sass::string u, bool zero)
429   : Value(pstate),
430     Units(),
431     value_(val),
432     zero_(zero),
433     hash_(0)
434   {
435     size_t l = 0;
436     size_t r;
437     if (!u.empty()) {
438       bool nominator = true;
439       while (true) {
440         r = u.find_first_of("*/", l);
441         sass::string unit(u.substr(l, r == sass::string::npos ? r : r - l));
442         if (!unit.empty()) {
443           if (nominator) numerators.push_back(unit);
444           else denominators.push_back(unit);
445         }
446         if (r == sass::string::npos) break;
447         // ToDo: should error for multiple slashes
448         // if (!nominator && u[r] == '/') error(...)
449         if (u[r] == '/')
450           nominator = false;
451         // strange math parsing?
452         // else if (u[r] == '*')
453         //  nominator = true;
454         l = r + 1;
455       }
456     }
457     concrete_type(NUMBER);
458   }
459 
Number(const Number * ptr)460   Number::Number(const Number* ptr)
461   : Value(ptr),
462     Units(ptr),
463     value_(ptr->value_), zero_(ptr->zero_),
464     hash_(ptr->hash_)
465   { concrete_type(NUMBER); }
466 
467   // cancel out unnecessary units
reduce()468   void Number::reduce()
469   {
470     // apply conversion factor
471     value_ *= this->Units::reduce();
472   }
473 
normalize()474   void Number::normalize()
475   {
476     // apply conversion factor
477     value_ *= this->Units::normalize();
478   }
479 
hash() const480   size_t Number::hash() const
481   {
482     if (hash_ == 0) {
483       hash_ = std::hash<double>()(value_);
484       for (const auto& numerator : numerators)
485         hash_combine(hash_, std::hash<sass::string>()(numerator));
486       for (const auto& denominator : denominators)
487         hash_combine(hash_, std::hash<sass::string>()(denominator));
488     }
489     return hash_;
490   }
491 
operator <(const Expression & rhs) const492   bool Number::operator< (const Expression& rhs) const
493   {
494     if (auto n = Cast<Number>(&rhs)) {
495       return *this < *n;
496     }
497     return false;
498   }
499 
operator ==(const Expression & rhs) const500   bool Number::operator== (const Expression& rhs) const
501   {
502     if (auto n = Cast<Number>(&rhs)) {
503       return *this == *n;
504     }
505     return false;
506   }
507 
operator ==(const Number & rhs) const508   bool Number::operator== (const Number& rhs) const
509   {
510     // unitless or only having one unit are equivalent (3.4)
511     // therefore we need to reduce the units beforehand
512     Number l(*this), r(rhs); l.reduce(); r.reduce();
513     size_t lhs_units = l.numerators.size() + l.denominators.size();
514     size_t rhs_units = r.numerators.size() + r.denominators.size();
515     if (!lhs_units || !rhs_units) {
516       return NEAR_EQUAL(l.value(), r.value());
517     }
518     // ensure both have same units
519     l.normalize(); r.normalize();
520     Units &lhs_unit = l, &rhs_unit = r;
521     return lhs_unit == rhs_unit &&
522       NEAR_EQUAL(l.value(), r.value());
523   }
524 
operator <(const Number & rhs) const525   bool Number::operator< (const Number& rhs) const
526   {
527     // unitless or only having one unit are equivalent (3.4)
528     // therefore we need to reduce the units beforehand
529     Number l(*this), r(rhs); l.reduce(); r.reduce();
530     size_t lhs_units = l.numerators.size() + l.denominators.size();
531     size_t rhs_units = r.numerators.size() + r.denominators.size();
532     if (!lhs_units || !rhs_units) {
533       return l.value() < r.value();
534     }
535     // ensure both have same units
536     l.normalize(); r.normalize();
537     Units &lhs_unit = l, &rhs_unit = r;
538     if (!(lhs_unit == rhs_unit)) {
539       /* ToDo: do we always get useful backtraces? */
540       throw Exception::IncompatibleUnits(rhs, *this);
541     }
542     if (lhs_unit == rhs_unit) {
543       return l.value() < r.value();
544     } else {
545       return lhs_unit < rhs_unit;
546     }
547   }
548 
549   /////////////////////////////////////////////////////////////////////////
550   /////////////////////////////////////////////////////////////////////////
551 
Color(SourceSpan pstate,double a,const sass::string disp)552   Color::Color(SourceSpan pstate, double a, const sass::string disp)
553   : Value(pstate),
554     disp_(disp), a_(a),
555     hash_(0)
556   { concrete_type(COLOR); }
557 
Color(const Color * ptr)558   Color::Color(const Color* ptr)
559   : Value(ptr->pstate()),
560     // reset on copy
561     disp_(""),
562     a_(ptr->a_),
563     hash_(ptr->hash_)
564   { concrete_type(COLOR); }
565 
operator <(const Expression & rhs) const566   bool Color::operator< (const Expression& rhs) const
567   {
568     if (auto r = Cast<Color_RGBA>(&rhs)) {
569       return *this < *r;
570     }
571     else if (auto r = Cast<Color_HSLA>(&rhs)) {
572       return *this < *r;
573     }
574     else if (auto r = Cast<Color>(&rhs)) {
575       return a_ < r->a();
576     }
577     // compare/sort by type
578     return type() < rhs.type();
579   }
580 
operator ==(const Expression & rhs) const581   bool Color::operator== (const Expression& rhs) const
582   {
583     if (auto r = Cast<Color_RGBA>(&rhs)) {
584       return *this == *r;
585     }
586     else if (auto r = Cast<Color_HSLA>(&rhs)) {
587       return *this == *r;
588     }
589     else if (auto r = Cast<Color>(&rhs)) {
590       return a_ == r->a();
591     }
592     return false;
593   }
594 
595   /////////////////////////////////////////////////////////////////////////
596   /////////////////////////////////////////////////////////////////////////
597 
Color_RGBA(SourceSpan pstate,double r,double g,double b,double a,const sass::string disp)598   Color_RGBA::Color_RGBA(SourceSpan pstate, double r, double g, double b, double a, const sass::string disp)
599   : Color(pstate, a, disp),
600     r_(r), g_(g), b_(b)
601   { concrete_type(COLOR); }
602 
Color_RGBA(const Color_RGBA * ptr)603   Color_RGBA::Color_RGBA(const Color_RGBA* ptr)
604   : Color(ptr),
605     r_(ptr->r_),
606     g_(ptr->g_),
607     b_(ptr->b_)
608   { concrete_type(COLOR); }
609 
operator <(const Expression & rhs) const610   bool Color_RGBA::operator< (const Expression& rhs) const
611   {
612     if (auto r = Cast<Color_RGBA>(&rhs)) {
613       if (r_ < r->r()) return true;
614       if (r_ > r->r()) return false;
615       if (g_ < r->g()) return true;
616       if (g_ > r->g()) return false;
617       if (b_ < r->b()) return true;
618       if (b_ > r->b()) return false;
619       if (a_ < r->a()) return true;
620       if (a_ > r->a()) return false;
621       return false; // is equal
622     }
623     // compare/sort by type
624     return type() < rhs.type();
625   }
626 
operator ==(const Expression & rhs) const627   bool Color_RGBA::operator== (const Expression& rhs) const
628   {
629     if (auto r = Cast<Color_RGBA>(&rhs)) {
630       return r_ == r->r() &&
631              g_ == r->g() &&
632              b_ == r->b() &&
633              a_ == r->a();
634     }
635     return false;
636   }
637 
hash() const638   size_t Color_RGBA::hash() const
639   {
640     if (hash_ == 0) {
641       hash_ = std::hash<sass::string>()("RGBA");
642       hash_combine(hash_, std::hash<double>()(a_));
643       hash_combine(hash_, std::hash<double>()(r_));
644       hash_combine(hash_, std::hash<double>()(g_));
645       hash_combine(hash_, std::hash<double>()(b_));
646     }
647     return hash_;
648   }
649 
copyAsHSLA() const650   Color_HSLA* Color_RGBA::copyAsHSLA() const
651   {
652 
653     // Algorithm from http://en.wikipedia.org/wiki/wHSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
654     double r = r_ / 255.0;
655     double g = g_ / 255.0;
656     double b = b_ / 255.0;
657 
658     double max = std::max(r, std::max(g, b));
659     double min = std::min(r, std::min(g, b));
660     double delta = max - min;
661 
662     double h = 0;
663     double s;
664     double l = (max + min) / 2.0;
665 
666     if (NEAR_EQUAL(max, min)) {
667       h = s = 0; // achromatic
668     }
669     else {
670       if (l < 0.5) s = delta / (max + min);
671       else         s = delta / (2.0 - max - min);
672 
673       if      (r == max) h = (g - b) / delta + (g < b ? 6 : 0);
674       else if (g == max) h = (b - r) / delta + 2;
675       else if (b == max) h = (r - g) / delta + 4;
676     }
677 
678     // HSL hsl_struct;
679     h = h * 60;
680     s = s * 100;
681     l = l * 100;
682 
683     return SASS_MEMORY_NEW(Color_HSLA,
684       pstate(), h, s, l, a(), ""
685     );
686   }
687 
copyAsRGBA() const688   Color_RGBA* Color_RGBA::copyAsRGBA() const
689   {
690     return SASS_MEMORY_COPY(this);
691   }
692 
693   /////////////////////////////////////////////////////////////////////////
694   /////////////////////////////////////////////////////////////////////////
695 
Color_HSLA(SourceSpan pstate,double h,double s,double l,double a,const sass::string disp)696   Color_HSLA::Color_HSLA(SourceSpan pstate, double h, double s, double l, double a, const sass::string disp)
697   : Color(pstate, a, disp),
698     h_(absmod(h, 360.0)),
699     s_(clip(s, 0.0, 100.0)),
700     l_(clip(l, 0.0, 100.0))
701     // hash_(0)
702   { concrete_type(COLOR); }
703 
Color_HSLA(const Color_HSLA * ptr)704   Color_HSLA::Color_HSLA(const Color_HSLA* ptr)
705   : Color(ptr),
706     h_(ptr->h_),
707     s_(ptr->s_),
708     l_(ptr->l_)
709     // hash_(ptr->hash_)
710   { concrete_type(COLOR); }
711 
operator <(const Expression & rhs) const712   bool Color_HSLA::operator< (const Expression& rhs) const
713   {
714     if (auto r = Cast<Color_HSLA>(&rhs)) {
715       if (h_ < r->h()) return true;
716       if (h_ > r->h()) return false;
717       if (s_ < r->s()) return true;
718       if (s_ > r->s()) return false;
719       if (l_ < r->l()) return true;
720       if (l_ > r->l()) return false;
721       if (a_ < r->a()) return true;
722       if (a_ > r->a()) return false;
723       return false; // is equal
724     }
725     // compare/sort by type
726     return type() < rhs.type();
727   }
728 
operator ==(const Expression & rhs) const729   bool Color_HSLA::operator== (const Expression& rhs) const
730   {
731     if (auto r = Cast<Color_HSLA>(&rhs)) {
732       return h_ == r->h() &&
733              s_ == r->s() &&
734              l_ == r->l() &&
735              a_ == r->a();
736     }
737     return false;
738   }
739 
hash() const740   size_t Color_HSLA::hash() const
741   {
742     if (hash_ == 0) {
743       hash_ = std::hash<sass::string>()("HSLA");
744       hash_combine(hash_, std::hash<double>()(a_));
745       hash_combine(hash_, std::hash<double>()(h_));
746       hash_combine(hash_, std::hash<double>()(s_));
747       hash_combine(hash_, std::hash<double>()(l_));
748     }
749     return hash_;
750   }
751 
752   // hue to RGB helper function
h_to_rgb(double m1,double m2,double h)753   double h_to_rgb(double m1, double m2, double h)
754   {
755     h = absmod(h, 1.0);
756     if (h*6.0 < 1) return m1 + (m2 - m1)*h*6;
757     if (h*2.0 < 1) return m2;
758     if (h*3.0 < 2) return m1 + (m2 - m1) * (2.0/3.0 - h)*6;
759     return m1;
760   }
761 
copyAsRGBA() const762   Color_RGBA* Color_HSLA::copyAsRGBA() const
763   {
764 
765     double h = absmod(h_ / 360.0, 1.0);
766     double s = clip(s_ / 100.0, 0.0, 1.0);
767     double l = clip(l_ / 100.0, 0.0, 1.0);
768 
769     // Algorithm from the CSS3 spec: http://www.w3.org/TR/css3-color/#hsl-color.
770     double m2;
771     if (l <= 0.5) m2 = l*(s+1.0);
772     else m2 = (l+s)-(l*s);
773     double m1 = (l*2.0)-m2;
774     // round the results -- consider moving this into the Color constructor
775     double r = (h_to_rgb(m1, m2, h + 1.0/3.0) * 255.0);
776     double g = (h_to_rgb(m1, m2, h) * 255.0);
777     double b = (h_to_rgb(m1, m2, h - 1.0/3.0) * 255.0);
778 
779     return SASS_MEMORY_NEW(Color_RGBA,
780       pstate(), r, g, b, a(), ""
781     );
782   }
783 
copyAsHSLA() const784   Color_HSLA* Color_HSLA::copyAsHSLA() const
785   {
786     return SASS_MEMORY_COPY(this);
787   }
788 
789   /////////////////////////////////////////////////////////////////////////
790   /////////////////////////////////////////////////////////////////////////
791 
Custom_Error(SourceSpan pstate,sass::string msg)792   Custom_Error::Custom_Error(SourceSpan pstate, sass::string msg)
793   : Value(pstate), message_(msg)
794   { concrete_type(C_ERROR); }
795 
Custom_Error(const Custom_Error * ptr)796   Custom_Error::Custom_Error(const Custom_Error* ptr)
797   : Value(ptr), message_(ptr->message_)
798   { concrete_type(C_ERROR); }
799 
operator <(const Expression & rhs) const800   bool Custom_Error::operator< (const Expression& rhs) const
801   {
802     if (auto r = Cast<Custom_Error>(&rhs)) {
803       return message() < r->message();
804     }
805     // compare/sort by type
806     return type() < rhs.type();
807   }
808 
operator ==(const Expression & rhs) const809   bool Custom_Error::operator== (const Expression& rhs) const
810   {
811     if (auto r = Cast<Custom_Error>(&rhs)) {
812       return message() == r->message();
813     }
814     return false;
815   }
816 
817   /////////////////////////////////////////////////////////////////////////
818   /////////////////////////////////////////////////////////////////////////
819 
Custom_Warning(SourceSpan pstate,sass::string msg)820   Custom_Warning::Custom_Warning(SourceSpan pstate, sass::string msg)
821   : Value(pstate), message_(msg)
822   { concrete_type(C_WARNING); }
823 
Custom_Warning(const Custom_Warning * ptr)824   Custom_Warning::Custom_Warning(const Custom_Warning* ptr)
825   : Value(ptr), message_(ptr->message_)
826   { concrete_type(C_WARNING); }
827 
operator <(const Expression & rhs) const828   bool Custom_Warning::operator< (const Expression& rhs) const
829   {
830     if (auto r = Cast<Custom_Warning>(&rhs)) {
831       return message() < r->message();
832     }
833     // compare/sort by type
834     return type() < rhs.type();
835   }
836 
operator ==(const Expression & rhs) const837   bool Custom_Warning::operator== (const Expression& rhs) const
838   {
839     if (auto r = Cast<Custom_Warning>(&rhs)) {
840       return message() == r->message();
841     }
842     return false;
843   }
844 
845   /////////////////////////////////////////////////////////////////////////
846   /////////////////////////////////////////////////////////////////////////
847 
Boolean(SourceSpan pstate,bool val)848   Boolean::Boolean(SourceSpan pstate, bool val)
849   : Value(pstate), value_(val),
850     hash_(0)
851   { concrete_type(BOOLEAN); }
852 
Boolean(const Boolean * ptr)853   Boolean::Boolean(const Boolean* ptr)
854   : Value(ptr),
855     value_(ptr->value_),
856     hash_(ptr->hash_)
857   { concrete_type(BOOLEAN); }
858 
operator <(const Expression & rhs) const859  bool Boolean::operator< (const Expression& rhs) const
860   {
861     if (auto r = Cast<Boolean>(&rhs)) {
862       return (value() < r->value());
863     }
864     return false;
865   }
866 
operator ==(const Expression & rhs) const867  bool Boolean::operator== (const Expression& rhs) const
868  {
869    if (auto r = Cast<Boolean>(&rhs)) {
870      return (value() == r->value());
871    }
872    return false;
873  }
874 
hash() const875  size_t Boolean::hash() const
876   {
877     if (hash_ == 0) {
878       hash_ = std::hash<bool>()(value_);
879     }
880     return hash_;
881   }
882 
883   /////////////////////////////////////////////////////////////////////////
884   /////////////////////////////////////////////////////////////////////////
885 
String(SourceSpan pstate,bool delayed)886   String::String(SourceSpan pstate, bool delayed)
887   : Value(pstate, delayed)
888   { concrete_type(STRING); }
String(const String * ptr)889   String::String(const String* ptr)
890   : Value(ptr)
891   { concrete_type(STRING); }
892 
893   /////////////////////////////////////////////////////////////////////////
894   /////////////////////////////////////////////////////////////////////////
895 
String_Schema(SourceSpan pstate,size_t size,bool css)896   String_Schema::String_Schema(SourceSpan pstate, size_t size, bool css)
897   : String(pstate), Vectorized<PreValueObj>(size), css_(css), hash_(0)
898   { concrete_type(STRING); }
899 
String_Schema(const String_Schema * ptr)900   String_Schema::String_Schema(const String_Schema* ptr)
901   : String(ptr),
902     Vectorized<PreValueObj>(*ptr),
903     css_(ptr->css_),
904     hash_(ptr->hash_)
905   { concrete_type(STRING); }
906 
rtrim()907   void String_Schema::rtrim()
908   {
909     if (!empty()) {
910       if (String* str = Cast<String>(last())) str->rtrim();
911     }
912   }
913 
is_left_interpolant(void) const914   bool String_Schema::is_left_interpolant(void) const
915   {
916     return length() && first()->is_left_interpolant();
917   }
is_right_interpolant(void) const918   bool String_Schema::is_right_interpolant(void) const
919   {
920     return length() && last()->is_right_interpolant();
921   }
922 
operator <(const Expression & rhs) const923   bool String_Schema::operator< (const Expression& rhs) const
924   {
925     if (auto r = Cast<String_Schema>(&rhs)) {
926       if (length() < r->length()) return true;
927       if (length() > r->length()) return false;
928       for (size_t i = 0, L = length(); i < L; ++i) {
929         if (*get(i) < *r->get(i)) return true;
930         if (*get(i) == *r->get(i)) continue;
931         return false;
932       }
933       // Is equal
934       return false;
935     }
936     // compare/sort by type
937     return type() < rhs.type();
938   }
939 
operator ==(const Expression & rhs) const940   bool String_Schema::operator== (const Expression& rhs) const
941   {
942     if (auto r = Cast<String_Schema>(&rhs)) {
943       if (length() != r->length()) return false;
944       for (size_t i = 0, L = length(); i < L; ++i) {
945         auto rv = (*r)[i];
946         auto lv = (*this)[i];
947         if (*lv != *rv) return false;
948       }
949       return true;
950     }
951     return false;
952   }
953 
has_interpolants()954   bool String_Schema::has_interpolants()
955   {
956     for (auto el : elements()) {
957       if (el->is_interpolant()) return true;
958     }
959     return false;
960   }
961 
hash() const962   size_t String_Schema::hash() const
963   {
964     if (hash_ == 0) {
965       for (auto string : elements())
966         hash_combine(hash_, string->hash());
967     }
968     return hash_;
969   }
970 
set_delayed(bool delayed)971   void String_Schema::set_delayed(bool delayed)
972   {
973     is_delayed(delayed);
974   }
975 
976   /////////////////////////////////////////////////////////////////////////
977   /////////////////////////////////////////////////////////////////////////
978 
String_Constant(SourceSpan pstate,sass::string val,bool css)979   String_Constant::String_Constant(SourceSpan pstate, sass::string val, bool css)
980   : String(pstate), quote_mark_(0), value_(read_css_string(val, css)), hash_(0)
981   { }
String_Constant(SourceSpan pstate,const char * beg,bool css)982   String_Constant::String_Constant(SourceSpan pstate, const char* beg, bool css)
983   : String(pstate), quote_mark_(0), value_(read_css_string(sass::string(beg), css)), hash_(0)
984   { }
String_Constant(SourceSpan pstate,const char * beg,const char * end,bool css)985   String_Constant::String_Constant(SourceSpan pstate, const char* beg, const char* end, bool css)
986   : String(pstate), quote_mark_(0), value_(read_css_string(sass::string(beg, end-beg), css)), hash_(0)
987   { }
String_Constant(SourceSpan pstate,const Token & tok,bool css)988   String_Constant::String_Constant(SourceSpan pstate, const Token& tok, bool css)
989   : String(pstate), quote_mark_(0), value_(read_css_string(sass::string(tok.begin, tok.end), css)), hash_(0)
990   { }
991 
String_Constant(const String_Constant * ptr)992   String_Constant::String_Constant(const String_Constant* ptr)
993   : String(ptr),
994     quote_mark_(ptr->quote_mark_),
995     value_(ptr->value_),
996     hash_(ptr->hash_)
997   { }
998 
is_invisible() const999   bool String_Constant::is_invisible() const {
1000     return value_.empty() && quote_mark_ == 0;
1001   }
1002 
operator <(const Expression & rhs) const1003   bool String_Constant::operator< (const Expression& rhs) const
1004   {
1005     if (auto qstr = Cast<String_Quoted>(&rhs)) {
1006       return value() < qstr->value();
1007     }
1008     else if (auto cstr = Cast<String_Constant>(&rhs)) {
1009       return value() < cstr->value();
1010     }
1011     // compare/sort by type
1012     return type() < rhs.type();
1013   }
1014 
operator ==(const Expression & rhs) const1015   bool String_Constant::operator== (const Expression& rhs) const
1016   {
1017     if (auto qstr = Cast<String_Quoted>(&rhs)) {
1018       return value() == qstr->value();
1019     }
1020     else if (auto cstr = Cast<String_Constant>(&rhs)) {
1021       return value() == cstr->value();
1022     }
1023     return false;
1024   }
1025 
inspect() const1026   sass::string String_Constant::inspect() const
1027   {
1028     return quote(value_, '*');
1029   }
1030 
rtrim()1031   void String_Constant::rtrim()
1032   {
1033     str_rtrim(value_);
1034   }
1035 
hash() const1036   size_t String_Constant::hash() const
1037   {
1038     if (hash_ == 0) {
1039       hash_ = std::hash<sass::string>()(value_);
1040     }
1041     return hash_;
1042   }
1043 
1044   /////////////////////////////////////////////////////////////////////////
1045   /////////////////////////////////////////////////////////////////////////
1046 
String_Quoted(SourceSpan pstate,sass::string val,char q,bool keep_utf8_escapes,bool skip_unquoting,bool strict_unquoting,bool css)1047   String_Quoted::String_Quoted(SourceSpan pstate, sass::string val, char q,
1048     bool keep_utf8_escapes, bool skip_unquoting,
1049     bool strict_unquoting, bool css)
1050   : String_Constant(pstate, val, css)
1051   {
1052     if (skip_unquoting == false) {
1053       value_ = unquote(value_, &quote_mark_, keep_utf8_escapes, strict_unquoting);
1054     }
1055     if (q && quote_mark_) quote_mark_ = q;
1056   }
1057 
String_Quoted(const String_Quoted * ptr)1058   String_Quoted::String_Quoted(const String_Quoted* ptr)
1059   : String_Constant(ptr)
1060   { }
1061 
operator <(const Expression & rhs) const1062   bool String_Quoted::operator< (const Expression& rhs) const
1063   {
1064     if (auto qstr = Cast<String_Quoted>(&rhs)) {
1065       return value() < qstr->value();
1066     }
1067     else if (auto cstr = Cast<String_Constant>(&rhs)) {
1068       return value() < cstr->value();
1069     }
1070     // compare/sort by type
1071     return type() < rhs.type();
1072   }
1073 
operator ==(const Expression & rhs) const1074   bool String_Quoted::operator== (const Expression& rhs) const
1075   {
1076     if (auto qstr = Cast<String_Quoted>(&rhs)) {
1077       return value() == qstr->value();
1078     }
1079     else if (auto cstr = Cast<String_Constant>(&rhs)) {
1080       return value() == cstr->value();
1081     }
1082     return false;
1083   }
1084 
inspect() const1085   sass::string String_Quoted::inspect() const
1086   {
1087     return quote(value_, '*');
1088   }
1089 
1090   /////////////////////////////////////////////////////////////////////////
1091   /////////////////////////////////////////////////////////////////////////
1092 
Null(SourceSpan pstate)1093   Null::Null(SourceSpan pstate)
1094   : Value(pstate)
1095   { concrete_type(NULL_VAL); }
1096 
Null(const Null * ptr)1097   Null::Null(const Null* ptr) : Value(ptr)
1098   { concrete_type(NULL_VAL); }
1099 
operator <(const Expression & rhs) const1100   bool Null::operator< (const Expression& rhs) const
1101   {
1102     if (Cast<Null>(&rhs)) {
1103       return false;
1104     }
1105     // compare/sort by type
1106     return type() < rhs.type();
1107   }
1108 
operator ==(const Expression & rhs) const1109   bool Null::operator== (const Expression& rhs) const
1110   {
1111     return Cast<Null>(&rhs) != nullptr;
1112   }
1113 
hash() const1114   size_t Null::hash() const
1115   {
1116     return -1;
1117   }
1118 
1119   /////////////////////////////////////////////////////////////////////////
1120   /////////////////////////////////////////////////////////////////////////
1121 
Parent_Reference(SourceSpan pstate)1122   Parent_Reference::Parent_Reference(SourceSpan pstate)
1123   : Value(pstate)
1124   { concrete_type(PARENT); }
1125 
Parent_Reference(const Parent_Reference * ptr)1126   Parent_Reference::Parent_Reference(const Parent_Reference* ptr)
1127   : Value(ptr)
1128   { concrete_type(PARENT); }
1129 
1130   /////////////////////////////////////////////////////////////////////////
1131   /////////////////////////////////////////////////////////////////////////
1132 
1133   IMPLEMENT_AST_OPERATORS(List);
1134   IMPLEMENT_AST_OPERATORS(Map);
1135   IMPLEMENT_AST_OPERATORS(Binary_Expression);
1136   IMPLEMENT_AST_OPERATORS(Function);
1137   IMPLEMENT_AST_OPERATORS(Function_Call);
1138   IMPLEMENT_AST_OPERATORS(Variable);
1139   IMPLEMENT_AST_OPERATORS(Number);
1140   IMPLEMENT_AST_OPERATORS(Color_RGBA);
1141   IMPLEMENT_AST_OPERATORS(Color_HSLA);
1142   IMPLEMENT_AST_OPERATORS(Custom_Error);
1143   IMPLEMENT_AST_OPERATORS(Custom_Warning);
1144   IMPLEMENT_AST_OPERATORS(Boolean);
1145   IMPLEMENT_AST_OPERATORS(String_Schema);
1146   IMPLEMENT_AST_OPERATORS(String_Constant);
1147   IMPLEMENT_AST_OPERATORS(String_Quoted);
1148   IMPLEMENT_AST_OPERATORS(Null);
1149   IMPLEMENT_AST_OPERATORS(Parent_Reference);
1150 
1151   /////////////////////////////////////////////////////////////////////////
1152   /////////////////////////////////////////////////////////////////////////
1153 
1154 }
1155