Initial commit
[yaffs-website] / node_modules / node-sass / src / libsass / src / eval.cpp
1 #include "sass.hpp"
2 #include <cstdlib>
3 #include <cmath>
4 #include <iostream>
5 #include <sstream>
6 #include <iomanip>
7 #include <typeinfo>
8
9 #include "file.hpp"
10 #include "eval.hpp"
11 #include "ast.hpp"
12 #include "bind.hpp"
13 #include "util.hpp"
14 #include "inspect.hpp"
15 #include "environment.hpp"
16 #include "position.hpp"
17 #include "sass/values.h"
18 #include "to_value.hpp"
19 #include "to_c.hpp"
20 #include "context.hpp"
21 #include "backtrace.hpp"
22 #include "lexer.hpp"
23 #include "prelexer.hpp"
24 #include "parser.hpp"
25 #include "expand.hpp"
26 #include "color_maps.hpp"
27 #include "sass_functions.hpp"
28
29 namespace Sass {
30
31   inline double add(double x, double y) { return x + y; }
32   inline double sub(double x, double y) { return x - y; }
33   inline double mul(double x, double y) { return x * y; }
34   inline double div(double x, double y) { return x / y; } // x/0 checked by caller
35   inline double mod(double x, double y) { // x/0 checked by caller
36     if ((x > 0 && y < 0) || (x < 0 && y > 0)) {
37       double ret = std::fmod(x, y);
38       return ret ? ret + y : ret;
39     } else {
40       return std::fmod(x, y);
41     }
42   }
43   typedef double (*bop)(double, double);
44   bop ops[Sass_OP::NUM_OPS] = {
45     0, 0, // and, or
46     0, 0, 0, 0, 0, 0, // eq, neq, gt, gte, lt, lte
47     add, sub, mul, div, mod
48   };
49
50   Eval::Eval(Expand& exp)
51   : exp(exp),
52     ctx(exp.ctx),
53     force(false),
54     is_in_comment(false)
55   { }
56   Eval::~Eval() { }
57
58   Env* Eval::environment()
59   {
60     return exp.environment();
61   }
62
63   Selector_List_Obj Eval::selector()
64   {
65     return exp.selector();
66   }
67
68   Backtrace* Eval::backtrace()
69   {
70     return exp.backtrace();
71   }
72
73   Expression_Ptr Eval::operator()(Block_Ptr b)
74   {
75     Expression_Ptr val = 0;
76     for (size_t i = 0, L = b->length(); i < L; ++i) {
77       val = b->at(i)->perform(this);
78       if (val) return val;
79     }
80     return val;
81   }
82
83   Expression_Ptr Eval::operator()(Assignment_Ptr a)
84   {
85     Env* env = exp.environment();
86     std::string var(a->variable());
87     if (a->is_global()) {
88       if (a->is_default()) {
89         if (env->has_global(var)) {
90           Expression_Ptr e = Cast<Expression>(env->get_global(var));
91           if (!e || e->concrete_type() == Expression::NULL_VAL) {
92             env->set_global(var, a->value()->perform(this));
93           }
94         }
95         else {
96           env->set_global(var, a->value()->perform(this));
97         }
98       }
99       else {
100         env->set_global(var, a->value()->perform(this));
101       }
102     }
103     else if (a->is_default()) {
104       if (env->has_lexical(var)) {
105         auto cur = env;
106         while (cur && cur->is_lexical()) {
107           if (cur->has_local(var)) {
108             if (AST_Node_Obj node = cur->get_local(var)) {
109               Expression_Ptr e = Cast<Expression>(node);
110               if (!e || e->concrete_type() == Expression::NULL_VAL) {
111                 cur->set_local(var, a->value()->perform(this));
112               }
113             }
114             else {
115               throw std::runtime_error("Env not in sync");
116             }
117             return 0;
118           }
119           cur = cur->parent();
120         }
121         throw std::runtime_error("Env not in sync");
122       }
123       else if (env->has_global(var)) {
124         if (AST_Node_Obj node = env->get_global(var)) {
125           Expression_Ptr e = Cast<Expression>(node);
126           if (!e || e->concrete_type() == Expression::NULL_VAL) {
127             env->set_global(var, a->value()->perform(this));
128           }
129         }
130       }
131       else if (env->is_lexical()) {
132         env->set_local(var, a->value()->perform(this));
133       }
134       else {
135         env->set_local(var, a->value()->perform(this));
136       }
137     }
138     else {
139       env->set_lexical(var, a->value()->perform(this));
140     }
141     return 0;
142   }
143
144   Expression_Ptr Eval::operator()(If_Ptr i)
145   {
146     Expression_Obj rv = 0;
147     Env env(exp.environment());
148     exp.env_stack.push_back(&env);
149     Expression_Obj cond = i->predicate()->perform(this);
150     if (!cond->is_false()) {
151       rv = i->block()->perform(this);
152     }
153     else {
154       Block_Obj alt = i->alternative();
155       if (alt) rv = alt->perform(this);
156     }
157     exp.env_stack.pop_back();
158     return rv.detach();
159   }
160
161   // For does not create a new env scope
162   // But iteration vars are reset afterwards
163   Expression_Ptr Eval::operator()(For_Ptr f)
164   {
165     std::string variable(f->variable());
166     Expression_Obj low = f->lower_bound()->perform(this);
167     if (low->concrete_type() != Expression::NUMBER) {
168       throw Exception::TypeMismatch(*low, "integer");
169     }
170     Expression_Obj high = f->upper_bound()->perform(this);
171     if (high->concrete_type() != Expression::NUMBER) {
172       throw Exception::TypeMismatch(*high, "integer");
173     }
174     Number_Obj sass_start = Cast<Number>(low);
175     Number_Obj sass_end = Cast<Number>(high);
176     // check if units are valid for sequence
177     if (sass_start->unit() != sass_end->unit()) {
178       std::stringstream msg; msg << "Incompatible units: '"
179         << sass_end->unit() << "' and '"
180         << sass_start->unit() << "'.";
181       error(msg.str(), low->pstate(), backtrace());
182     }
183     double start = sass_start->value();
184     double end = sass_end->value();
185     // only create iterator once in this environment
186     Env env(environment(), true);
187     exp.env_stack.push_back(&env);
188     Number_Ptr it = SASS_MEMORY_NEW(Number, low->pstate(), start, sass_end->unit());
189     env.set_local(variable, it);
190     Block_Obj body = f->block();
191     Expression_Ptr val = 0;
192     if (start < end) {
193       if (f->is_inclusive()) ++end;
194       for (double i = start;
195            i < end;
196            ++i) {
197         it->value(i);
198         env.set_local(variable, it);
199         val = body->perform(this);
200         if (val) break;
201       }
202     } else {
203       if (f->is_inclusive()) --end;
204       for (double i = start;
205            i > end;
206            --i) {
207         it->value(i);
208         env.set_local(variable, it);
209         val = body->perform(this);
210         if (val) break;
211       }
212     }
213     exp.env_stack.pop_back();
214     return val;
215   }
216
217   // Eval does not create a new env scope
218   // But iteration vars are reset afterwards
219   Expression_Ptr Eval::operator()(Each_Ptr e)
220   {
221     std::vector<std::string> variables(e->variables());
222     Expression_Obj expr = e->list()->perform(this);
223     Env env(environment(), true);
224     exp.env_stack.push_back(&env);
225     List_Obj list = 0;
226     Map_Ptr map = 0;
227     if (expr->concrete_type() == Expression::MAP) {
228       map = Cast<Map>(expr);
229     }
230     else if (Selector_List_Ptr ls = Cast<Selector_List>(expr)) {
231       Listize listize;
232       Expression_Obj rv = ls->perform(&listize);
233       list = Cast<List>(rv);
234     }
235     else if (expr->concrete_type() != Expression::LIST) {
236       list = SASS_MEMORY_NEW(List, expr->pstate(), 1, SASS_COMMA);
237       list->append(expr);
238     }
239     else {
240       list = Cast<List>(expr);
241     }
242
243     Block_Obj body = e->block();
244     Expression_Obj val = 0;
245
246     if (map) {
247       for (Expression_Obj key : map->keys()) {
248         Expression_Obj value = map->at(key);
249
250         if (variables.size() == 1) {
251           List_Ptr variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE);
252           variable->append(key);
253           variable->append(value);
254           env.set_local(variables[0], variable);
255         } else {
256           env.set_local(variables[0], key);
257           env.set_local(variables[1], value);
258         }
259
260         val = body->perform(this);
261         if (val) break;
262       }
263     }
264     else {
265       if (list->length() == 1 && Cast<Selector_List>(list)) {
266         list = Cast<List>(list);
267       }
268       for (size_t i = 0, L = list->length(); i < L; ++i) {
269         Expression_Ptr e = list->at(i);
270         // unwrap value if the expression is an argument
271         if (Argument_Ptr arg = Cast<Argument>(e)) e = arg->value();
272         // check if we got passed a list of args (investigate)
273         if (List_Ptr scalars = Cast<List>(e)) {
274           if (variables.size() == 1) {
275             Expression_Ptr var = scalars;
276             env.set_local(variables[0], var);
277           } else {
278             // XXX: this is never hit via spec tests
279             for (size_t j = 0, K = variables.size(); j < K; ++j) {
280               Expression_Ptr res = j >= scalars->length()
281                 ? SASS_MEMORY_NEW(Null, expr->pstate())
282                 : scalars->at(j);
283               env.set_local(variables[j], res);
284             }
285           }
286         } else {
287           if (variables.size() > 0) {
288             env.set_local(variables.at(0), e);
289             for (size_t j = 1, K = variables.size(); j < K; ++j) {
290               // XXX: this is never hit via spec tests
291               Expression_Ptr res = SASS_MEMORY_NEW(Null, expr->pstate());
292               env.set_local(variables[j], res);
293             }
294           }
295         }
296         val = body->perform(this);
297         if (val) break;
298       }
299     }
300     exp.env_stack.pop_back();
301     return val.detach();
302   }
303
304   Expression_Ptr Eval::operator()(While_Ptr w)
305   {
306     Expression_Obj pred = w->predicate();
307     Block_Obj body = w->block();
308     Env env(environment(), true);
309     exp.env_stack.push_back(&env);
310     Expression_Obj cond = pred->perform(this);
311     while (!cond->is_false()) {
312       Expression_Obj val = body->perform(this);
313       if (val) {
314         exp.env_stack.pop_back();
315         return val.detach();
316       }
317       cond = pred->perform(this);
318     }
319     exp.env_stack.pop_back();
320     return 0;
321   }
322
323   Expression_Ptr Eval::operator()(Return_Ptr r)
324   {
325     return r->value()->perform(this);
326   }
327
328   Expression_Ptr Eval::operator()(Warning_Ptr w)
329   {
330     Sass_Output_Style outstyle = ctx.c_options.output_style;
331     ctx.c_options.output_style = NESTED;
332     Expression_Obj message = w->message()->perform(this);
333     Env* env = exp.environment();
334
335     // try to use generic function
336     if (env->has("@warn[f]")) {
337
338       // add call stack entry
339       ctx.callee_stack.push_back({
340         "@warn",
341         w->pstate().path,
342         w->pstate().line + 1,
343         w->pstate().column + 1,
344         SASS_CALLEE_FUNCTION,
345         { env }
346       });
347
348       Definition_Ptr def = Cast<Definition>((*env)["@warn[f]"]);
349       // Block_Obj          body   = def->block();
350       // Native_Function func   = def->native_function();
351       Sass_Function_Entry c_function = def->c_function();
352       Sass_Function_Fn c_func = sass_function_get_function(c_function);
353
354       To_C to_c;
355       union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
356       sass_list_set_value(c_args, 0, message->perform(&to_c));
357       union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
358       ctx.c_options.output_style = outstyle;
359       ctx.callee_stack.pop_back();
360       sass_delete_value(c_args);
361       sass_delete_value(c_val);
362       return 0;
363
364     }
365
366     std::string result(unquote(message->to_sass()));
367     Backtrace top(backtrace(), w->pstate(), "");
368     std::cerr << "WARNING: " << result;
369     std::cerr << top.to_string();
370     std::cerr << std::endl << std::endl;
371     ctx.c_options.output_style = outstyle;
372     return 0;
373   }
374
375   Expression_Ptr Eval::operator()(Error_Ptr e)
376   {
377     Sass_Output_Style outstyle = ctx.c_options.output_style;
378     ctx.c_options.output_style = NESTED;
379     Expression_Obj message = e->message()->perform(this);
380     Env* env = exp.environment();
381
382     // try to use generic function
383     if (env->has("@error[f]")) {
384
385       // add call stack entry
386       ctx.callee_stack.push_back({
387         "@error",
388         e->pstate().path,
389         e->pstate().line + 1,
390         e->pstate().column + 1,
391         SASS_CALLEE_FUNCTION,
392         { env }
393       });
394
395       Definition_Ptr def = Cast<Definition>((*env)["@error[f]"]);
396       // Block_Obj          body   = def->block();
397       // Native_Function func   = def->native_function();
398       Sass_Function_Entry c_function = def->c_function();
399       Sass_Function_Fn c_func = sass_function_get_function(c_function);
400
401       To_C to_c;
402       union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
403       sass_list_set_value(c_args, 0, message->perform(&to_c));
404       union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
405       ctx.c_options.output_style = outstyle;
406       ctx.callee_stack.pop_back();
407       sass_delete_value(c_args);
408       sass_delete_value(c_val);
409       return 0;
410
411     }
412
413     std::string result(unquote(message->to_sass()));
414     ctx.c_options.output_style = outstyle;
415     error(result, e->pstate());
416     return 0;
417   }
418
419   Expression_Ptr Eval::operator()(Debug_Ptr d)
420   {
421     Sass_Output_Style outstyle = ctx.c_options.output_style;
422     ctx.c_options.output_style = NESTED;
423     Expression_Obj message = d->value()->perform(this);
424     Env* env = exp.environment();
425
426     // try to use generic function
427     if (env->has("@debug[f]")) {
428
429       // add call stack entry
430       ctx.callee_stack.push_back({
431         "@debug",
432         d->pstate().path,
433         d->pstate().line + 1,
434         d->pstate().column + 1,
435         SASS_CALLEE_FUNCTION,
436         { env }
437       });
438
439       Definition_Ptr def = Cast<Definition>((*env)["@debug[f]"]);
440       // Block_Obj          body   = def->block();
441       // Native_Function func   = def->native_function();
442       Sass_Function_Entry c_function = def->c_function();
443       Sass_Function_Fn c_func = sass_function_get_function(c_function);
444
445       To_C to_c;
446       union Sass_Value* c_args = sass_make_list(1, SASS_COMMA, false);
447       sass_list_set_value(c_args, 0, message->perform(&to_c));
448       union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
449       ctx.c_options.output_style = outstyle;
450       ctx.callee_stack.pop_back();
451       sass_delete_value(c_args);
452       sass_delete_value(c_val);
453       return 0;
454
455     }
456
457     std::string cwd(ctx.cwd());
458     std::string result(unquote(message->to_sass()));
459     std::string abs_path(Sass::File::rel2abs(d->pstate().path, cwd, cwd));
460     std::string rel_path(Sass::File::abs2rel(d->pstate().path, cwd, cwd));
461     std::string output_path(Sass::File::path_for_console(rel_path, abs_path, d->pstate().path));
462     ctx.c_options.output_style = outstyle;
463
464     std::cerr << output_path << ":" << d->pstate().line+1 << " DEBUG: " << result;
465     std::cerr << std::endl;
466     return 0;
467   }
468
469   Expression_Ptr Eval::operator()(List_Ptr l)
470   {
471     // special case for unevaluated map
472     if (l->separator() == SASS_HASH) {
473       Map_Obj lm = SASS_MEMORY_NEW(Map,
474                                 l->pstate(),
475                                 l->length() / 2);
476       for (size_t i = 0, L = l->length(); i < L; i += 2)
477       {
478         Expression_Obj key = (*l)[i+0]->perform(this);
479         Expression_Obj val = (*l)[i+1]->perform(this);
480         // make sure the color key never displays its real name
481         key->is_delayed(true); // verified
482         *lm << std::make_pair(key, val);
483       }
484       if (lm->has_duplicate_key()) {
485         throw Exception::DuplicateKeyError(*lm, *l);
486       }
487
488       lm->is_interpolant(l->is_interpolant());
489       return lm->perform(this);
490     }
491     // check if we should expand it
492     if (l->is_expanded()) return l;
493     // regular case for unevaluated lists
494     List_Obj ll = SASS_MEMORY_NEW(List,
495                                l->pstate(),
496                                l->length(),
497                                l->separator(),
498                                l->is_arglist(),
499                                l->is_bracketed());
500     for (size_t i = 0, L = l->length(); i < L; ++i) {
501       ll->append((*l)[i]->perform(this));
502     }
503     ll->is_interpolant(l->is_interpolant());
504     ll->from_selector(l->from_selector());
505     ll->is_expanded(true);
506     return ll.detach();
507   }
508
509   Expression_Ptr Eval::operator()(Map_Ptr m)
510   {
511     if (m->is_expanded()) return m;
512
513     // make sure we're not starting with duplicate keys.
514     // the duplicate key state will have been set in the parser phase.
515     if (m->has_duplicate_key()) {
516       throw Exception::DuplicateKeyError(*m, *m);
517     }
518
519     Map_Obj mm = SASS_MEMORY_NEW(Map,
520                                 m->pstate(),
521                                 m->length());
522     for (auto key : m->keys()) {
523       Expression_Ptr ex_key = key->perform(this);
524       Expression_Ptr ex_val = m->at(key)->perform(this);
525       *mm << std::make_pair(ex_key, ex_val);
526     }
527
528     // check the evaluated keys aren't duplicates.
529     if (mm->has_duplicate_key()) {
530       throw Exception::DuplicateKeyError(*mm, *m);
531     }
532
533     mm->is_expanded(true);
534     return mm.detach();
535   }
536
537   Expression_Ptr Eval::operator()(Binary_Expression_Ptr b_in)
538   {
539
540     String_Schema_Obj ret_schema;
541     Binary_Expression_Obj b = b_in;
542     enum Sass_OP op_type = b->optype();
543
544     // only the last item will be used to eval the binary expression
545     if (String_Schema_Ptr s_l = Cast<String_Schema>(b->left())) {
546       if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) {
547         ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
548         Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
549                                                     b->op(), s_l->last(), b->right());
550         bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // unverified
551         for (size_t i = 0; i < s_l->length() - 1; ++i) {
552           ret_schema->append(s_l->at(i)->perform(this));
553         }
554         ret_schema->append(bin_ex->perform(this));
555         return ret_schema->perform(this);
556       }
557     }
558     if (String_Schema_Ptr s_r = Cast<String_Schema>(b->right())) {
559
560       if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) {
561         ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
562         Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
563                                                     b->op(), b->left(), s_r->first());
564         bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // verified
565         ret_schema->append(bin_ex->perform(this));
566         for (size_t i = 1; i < s_r->length(); ++i) {
567           ret_schema->append(s_r->at(i)->perform(this));
568         }
569         return ret_schema->perform(this);
570       }
571     }
572
573     // don't eval delayed expressions (the '/' when used as a separator)
574     if (!force && op_type == Sass_OP::DIV && b->is_delayed()) {
575       b->right(b->right()->perform(this));
576       b->left(b->left()->perform(this));
577       return b.detach();
578     }
579
580     Expression_Obj lhs = b->left();
581     Expression_Obj rhs = b->right();
582
583     // fully evaluate their values
584     if (op_type == Sass_OP::EQ ||
585         op_type == Sass_OP::NEQ ||
586         op_type == Sass_OP::GT ||
587         op_type == Sass_OP::GTE ||
588         op_type == Sass_OP::LT ||
589         op_type == Sass_OP::LTE)
590     {
591       LOCAL_FLAG(force, true);
592       lhs->is_expanded(false);
593       lhs->set_delayed(false);
594       lhs = lhs->perform(this);
595       rhs->is_expanded(false);
596       rhs->set_delayed(false);
597       rhs = rhs->perform(this);
598     }
599     else {
600       lhs = lhs->perform(this);
601     }
602
603     Binary_Expression_Obj u3 = b;
604     switch (op_type) {
605       case Sass_OP::AND: {
606         return *lhs ? b->right()->perform(this) : lhs.detach();
607       } break;
608
609       case Sass_OP::OR: {
610         return *lhs ? lhs.detach() : b->right()->perform(this);
611       } break;
612
613       default:
614         break;
615     }
616     // not a logical connective, so go ahead and eval the rhs
617     rhs = rhs->perform(this);
618     AST_Node_Obj lu = lhs;
619     AST_Node_Obj ru = rhs;
620
621     Expression::Concrete_Type l_type = lhs->concrete_type();
622     Expression::Concrete_Type r_type = rhs->concrete_type();
623
624     // Is one of the operands an interpolant?
625     String_Schema_Obj s1 = Cast<String_Schema>(b->left());
626     String_Schema_Obj s2 = Cast<String_Schema>(b->right());
627     Binary_Expression_Obj b1 = Cast<Binary_Expression>(b->left());
628     Binary_Expression_Obj b2 = Cast<Binary_Expression>(b->right());
629
630     bool schema_op = false;
631
632     bool force_delay = (s2 && s2->is_left_interpolant()) ||
633                        (s1 && s1->is_right_interpolant()) ||
634                        (b1 && b1->is_right_interpolant()) ||
635                        (b2 && b2->is_left_interpolant());
636
637     if ((s1 && s1->has_interpolants()) || (s2 && s2->has_interpolants()) || force_delay)
638     {
639       if (op_type == Sass_OP::DIV || op_type == Sass_OP::MUL || op_type == Sass_OP::MOD || op_type == Sass_OP::ADD || op_type == Sass_OP::SUB ||
640           op_type == Sass_OP::EQ) {
641         // If possible upgrade LHS to a number (for number to string compare)
642         if (String_Constant_Ptr str = Cast<String_Constant>(lhs)) {
643           std::string value(str->value());
644           const char* start = value.c_str();
645           if (Prelexer::sequence < Prelexer::dimension, Prelexer::end_of_file >(start) != 0) {
646             Textual_Obj l = SASS_MEMORY_NEW(Textual, b->pstate(), Textual::DIMENSION, str->value());
647             lhs = l->perform(this);
648           }
649         }
650         // If possible upgrade RHS to a number (for string to number compare)
651         if (String_Constant_Ptr str = Cast<String_Constant>(rhs)) {
652           std::string value(str->value());
653           const char* start = value.c_str();
654           if (Prelexer::sequence < Prelexer::dimension, Prelexer::number >(start) != 0) {
655             Textual_Obj r = SASS_MEMORY_NEW(Textual, b->pstate(), Textual::DIMENSION, str->value());
656             rhs = r->perform(this);
657           }
658         }
659       }
660
661       To_Value to_value(ctx);
662       Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
663       Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
664       l_type = lhs->concrete_type();
665       r_type = rhs->concrete_type();
666
667       if (s2 && s2->has_interpolants() && s2->length()) {
668         Textual_Obj front = Cast<Textual>(s2->elements().front());
669         if (front && !front->is_interpolant())
670         {
671           // XXX: this is never hit via spec tests
672           schema_op = true;
673           rhs = front->perform(this);
674         }
675       }
676
677       if (force_delay) {
678         std::string str("");
679         str += v_l->to_string(ctx.c_options);
680         if (b->op().ws_before) str += " ";
681         str += b->separator();
682         if (b->op().ws_after) str += " ";
683         str += v_r->to_string(ctx.c_options);
684         String_Constant_Ptr val = SASS_MEMORY_NEW(String_Constant, b->pstate(), str);
685         val->is_interpolant(b->left()->has_interpolant());
686         return val;
687       }
688     }
689
690     // see if it's a relational expression
691     try {
692       switch(op_type) {
693         case Sass_OP::EQ:  return SASS_MEMORY_NEW(Boolean, b->pstate(), eq(lhs, rhs));
694         case Sass_OP::NEQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), !eq(lhs, rhs));
695         case Sass_OP::GT:  return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gt") && !eq(lhs, rhs));
696         case Sass_OP::GTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gte"));
697         case Sass_OP::LT:  return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lt"));
698         case Sass_OP::LTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lte") || eq(lhs, rhs));
699         default:                     break;
700       }
701     }
702     catch (Exception::OperationError& err)
703     {
704       // throw Exception::Base(b->pstate(), err.what());
705       throw Exception::SassValueError(b->pstate(), err);
706     }
707
708     l_type = lhs->concrete_type();
709     r_type = rhs->concrete_type();
710
711     // ToDo: throw error in op functions
712     // ToDo: then catch and re-throw them
713     Expression_Obj rv = 0;
714     try {
715       ParserState pstate(b->pstate());
716       if (l_type == Expression::NUMBER && r_type == Expression::NUMBER) {
717         Number_Ptr l_n = Cast<Number>(lhs);
718         Number_Ptr r_n = Cast<Number>(rhs);
719         rv = op_numbers(op_type, *l_n, *r_n, ctx.c_options, &pstate);
720       }
721       else if (l_type == Expression::NUMBER && r_type == Expression::COLOR) {
722         Number_Ptr l_n = Cast<Number>(lhs);
723         Color_Ptr r_c = Cast<Color>(rhs);
724         rv = op_number_color(op_type, *l_n, *r_c, ctx.c_options, &pstate);
725       }
726       else if (l_type == Expression::COLOR && r_type == Expression::NUMBER) {
727         Color_Ptr l_c = Cast<Color>(lhs);
728         Number_Ptr r_n = Cast<Number>(rhs);
729         rv = op_color_number(op_type, *l_c, *r_n, ctx.c_options, &pstate);
730       }
731       else if (l_type == Expression::COLOR && r_type == Expression::COLOR) {
732         Color_Ptr l_c = Cast<Color>(lhs);
733         Color_Ptr r_c = Cast<Color>(rhs);
734         rv = op_colors(op_type, *l_c, *r_c, ctx.c_options, &pstate);
735       }
736       else {
737         To_Value to_value(ctx);
738         // this will leak if perform does not return a value!
739         Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
740         Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
741         bool interpolant = b->is_right_interpolant() ||
742                            b->is_left_interpolant() ||
743                            b->is_interpolant();
744         if (op_type == Sass_OP::SUB) interpolant = false;
745         // if (op_type == Sass_OP::DIV) interpolant = true;
746         // check for type violations
747         if (l_type == Expression::MAP) {
748           throw Exception::InvalidValue(*v_l);
749         }
750         if (r_type == Expression::MAP) {
751           throw Exception::InvalidValue(*v_r);
752         }
753         Value_Ptr ex = op_strings(b->op(), *v_l, *v_r, ctx.c_options, &pstate, !interpolant); // pass true to compress
754         if (String_Constant_Ptr str = Cast<String_Constant>(ex))
755         {
756           if (str->concrete_type() == Expression::STRING)
757           {
758             String_Constant_Ptr lstr = Cast<String_Constant>(lhs);
759             String_Constant_Ptr rstr = Cast<String_Constant>(rhs);
760             if (op_type != Sass_OP::SUB) {
761               if (String_Constant_Ptr org = lstr ? lstr : rstr)
762               { str->quote_mark(org->quote_mark()); }
763             }
764           }
765         }
766         ex->is_interpolant(b->is_interpolant());
767         rv = ex;
768       }
769     }
770     catch (Exception::OperationError& err)
771     {
772       // throw Exception::Base(b->pstate(), err.what());
773       throw Exception::SassValueError(b->pstate(), err);
774     }
775
776     if (rv) {
777       if (schema_op) {
778         // XXX: this is never hit via spec tests
779         (*s2)[0] = rv;
780         rv = s2->perform(this);
781       }
782     }
783
784     return rv.detach();
785
786   }
787
788   Expression_Ptr Eval::operator()(Unary_Expression_Ptr u)
789   {
790     Expression_Obj operand = u->operand()->perform(this);
791     if (u->optype() == Unary_Expression::NOT) {
792       Boolean_Ptr result = SASS_MEMORY_NEW(Boolean, u->pstate(), (bool)*operand);
793       result->value(!result->value());
794       return result;
795     }
796     else if (Number_Obj nr = Cast<Number>(operand)) {
797       // negate value for minus unary expression
798       if (u->optype() == Unary_Expression::MINUS) {
799         Number_Obj cpy = SASS_MEMORY_COPY(nr);
800         cpy->value( - cpy->value() ); // negate value
801         return cpy.detach(); // return the copy
802       }
803       // nothing for positive
804       return nr.detach();
805     }
806     else {
807       // Special cases: +/- variables which evaluate to null ouput just +/-,
808       // but +/- null itself outputs the string
809       if (operand->concrete_type() == Expression::NULL_VAL && Cast<Variable>(u->operand())) {
810         u->operand(SASS_MEMORY_NEW(String_Quoted, u->pstate(), ""));
811       }
812       // Never apply unary opertions on colors @see #2140
813       else if (Color_Ptr color = Cast<Color>(operand)) {
814         // Use the color name if this was eval with one
815         if (color->disp().length() > 0) {
816           operand = SASS_MEMORY_NEW(String_Constant, operand->pstate(), color->disp());
817           u->operand(operand);
818         }
819       }
820       else {
821         u->operand(operand);
822       }
823
824       return SASS_MEMORY_NEW(String_Quoted,
825                              u->pstate(),
826                              u->inspect());
827     }
828     // unreachable
829     return u;
830   }
831
832   Expression_Ptr Eval::operator()(Function_Call_Ptr c)
833   {
834     if (backtrace()->parent != NULL && backtrace()->depth() > Constants::MaxCallStack) {
835         // XXX: this is never hit via spec tests
836         std::ostringstream stm;
837         stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
838         error(stm.str(), c->pstate(), backtrace());
839     }
840     std::string name(Util::normalize_underscores(c->name()));
841     std::string full_name(name + "[f]");
842     // we make a clone here, need to implement that further
843     Arguments_Obj args = c->arguments();
844
845     Env* env = environment();
846     if (!env->has(full_name) || (!c->via_call() && Prelexer::re_special_fun(name.c_str()))) {
847       if (!env->has("*[f]")) {
848         for (Argument_Obj arg : args->elements()) {
849           if (List_Obj ls = Cast<List>(arg->value())) {
850             if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate());
851           }
852         }
853         args = Cast<Arguments>(args->perform(this));
854         Function_Call_Obj lit = SASS_MEMORY_NEW(Function_Call,
855                                              c->pstate(),
856                                              c->name(),
857                                              args);
858         if (args->has_named_arguments()) {
859           error("Function " + c->name() + " doesn't support keyword arguments", c->pstate());
860         }
861         String_Quoted_Ptr str = SASS_MEMORY_NEW(String_Quoted,
862                                              c->pstate(),
863                                              lit->to_string(ctx.c_options));
864         str->is_interpolant(c->is_interpolant());
865         return str;
866       } else {
867         // call generic function
868         full_name = "*[f]";
869       }
870     }
871
872     // further delay for calls
873     if (full_name != "call[f]") {
874       args->set_delayed(false); // verified
875     }
876     if (full_name != "if[f]") {
877       args = Cast<Arguments>(args->perform(this));
878     }
879     Definition_Ptr def = Cast<Definition>((*env)[full_name]);
880
881     if (def->is_overload_stub()) {
882       std::stringstream ss;
883       size_t L = args->length();
884       // account for rest arguments
885       if (args->has_rest_argument() && args->length() > 0) {
886         // get the rest arguments list
887         List_Ptr rest = Cast<List>(args->last()->value());
888         // arguments before rest argument plus rest
889         if (rest) L += rest->length() - 1;
890       }
891       ss << full_name << L;
892       full_name = ss.str();
893       std::string resolved_name(full_name);
894       if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate());
895       def = Cast<Definition>((*env)[resolved_name]);
896     }
897
898     Expression_Obj     result = c;
899     Block_Obj          body   = def->block();
900     Native_Function func   = def->native_function();
901     Sass_Function_Entry c_function = def->c_function();
902
903     Parameters_Obj params = def->parameters();
904     Env fn_env(def->environment());
905     exp.env_stack.push_back(&fn_env);
906
907     if (func || body) {
908       bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this);
909       Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`");
910       exp.backtrace_stack.push_back(&here);
911       ctx.callee_stack.push_back({
912         c->name().c_str(),
913         c->pstate().path,
914         c->pstate().line + 1,
915         c->pstate().column + 1,
916         SASS_CALLEE_FUNCTION,
917         { env }
918       });
919
920       // eval the body if user-defined or special, invoke underlying CPP function if native
921       if (body /* && !Prelexer::re_special_fun(name.c_str()) */) {
922         result = body->perform(this);
923       }
924       else if (func) {
925         result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace(), exp.selector_stack);
926       }
927       if (!result) {
928         error(std::string("Function ") + c->name() + " did not return a value", c->pstate());
929       }
930       exp.backtrace_stack.pop_back();
931       ctx.callee_stack.pop_back();
932     }
933
934     // else if it's a user-defined c function
935     // convert call into C-API compatible form
936     else if (c_function) {
937       Sass_Function_Fn c_func = sass_function_get_function(c_function);
938       if (full_name == "*[f]") {
939         String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, c->pstate(), c->name());
940         Arguments_Obj new_args = SASS_MEMORY_NEW(Arguments, c->pstate());
941         new_args->append(SASS_MEMORY_NEW(Argument, c->pstate(), str));
942         new_args->concat(args);
943         args = new_args;
944       }
945
946       // populates env with default values for params
947       std::string ff(c->name());
948       bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this);
949
950       Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`");
951       exp.backtrace_stack.push_back(&here);
952       ctx.callee_stack.push_back({
953         c->name().c_str(),
954         c->pstate().path,
955         c->pstate().line + 1,
956         c->pstate().column + 1,
957         SASS_CALLEE_C_FUNCTION,
958         { env }
959       });
960
961       To_C to_c;
962       union Sass_Value* c_args = sass_make_list(params->length(), SASS_COMMA, false);
963       for(size_t i = 0; i < params->length(); i++) {
964         Parameter_Obj param = params->at(i);
965         std::string key = param->name();
966         AST_Node_Obj node = fn_env.get_local(key);
967         Expression_Obj arg = Cast<Expression>(node);
968         sass_list_set_value(c_args, i, arg->perform(&to_c));
969       }
970       union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
971       if (sass_value_get_tag(c_val) == SASS_ERROR) {
972         error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), backtrace());
973       } else if (sass_value_get_tag(c_val) == SASS_WARNING) {
974         error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->pstate(), backtrace());
975       }
976       result = cval_to_astnode(c_val, backtrace(), c->pstate());
977
978       exp.backtrace_stack.pop_back();
979       ctx.callee_stack.pop_back();
980       sass_delete_value(c_args);
981       if (c_val != c_args)
982         sass_delete_value(c_val);
983     }
984
985     // link back to function definition
986     // only do this for custom functions
987     if (result->pstate().file == std::string::npos)
988       result->pstate(c->pstate());
989
990     result = result->perform(this);
991     result->is_interpolant(c->is_interpolant());
992     exp.env_stack.pop_back();
993     return result.detach();
994   }
995
996   Expression_Ptr Eval::operator()(Function_Call_Schema_Ptr s)
997   {
998     Expression_Ptr evaluated_name = s->name()->perform(this);
999     Expression_Ptr evaluated_args = s->arguments()->perform(this);
1000     String_Schema_Obj ss = SASS_MEMORY_NEW(String_Schema, s->pstate(), 2);
1001     ss->append(evaluated_name);
1002     ss->append(evaluated_args);
1003     return ss->perform(this);
1004   }
1005
1006   Expression_Ptr Eval::operator()(Variable_Ptr v)
1007   {
1008     std::string name(v->name());
1009     Expression_Obj value = 0;
1010     Env* env = environment();
1011     if (env->has(name)) {
1012       value = Cast<Expression>((*env)[name]);
1013     }
1014     else error("Undefined variable: \"" + v->name() + "\".", v->pstate());
1015     if (Argument* arg = Cast<Argument>(value)) {
1016       value = arg->value();
1017     }
1018
1019     // behave according to as ruby sass (add leading zero)
1020     if (Number_Ptr nr = Cast<Number>(value)) {
1021       nr->zero(true);
1022     }
1023
1024     value->is_interpolant(v->is_interpolant());
1025     if (force) value->is_expanded(false);
1026     value->set_delayed(false); // verified
1027     value = value->perform(this);
1028     if(!force) (*env)[name] = value;
1029     return value.detach();
1030   }
1031
1032   Expression_Ptr Eval::operator()(Textual_Ptr t)
1033   {
1034     using Prelexer::number;
1035     Expression_Obj result = 0;
1036     size_t L = t->value().length();
1037     bool zero = !( (L > 0 && t->value().substr(0, 1) == ".") ||
1038                    (L > 1 && t->value().substr(0, 2) == "0.") ||
1039                    (L > 1 && t->value().substr(0, 2) == "-.")  ||
1040                    (L > 2 && t->value().substr(0, 3) == "-0.")
1041                  );
1042
1043     const std::string& text = t->value();
1044     size_t num_pos = text.find_first_not_of(" \n\r\t");
1045     if (num_pos == std::string::npos) num_pos = text.length();
1046     size_t unit_pos = text.find_first_not_of("-+0123456789.", num_pos);
1047     if (unit_pos == std::string::npos) unit_pos = text.length();
1048     const std::string& num = text.substr(num_pos, unit_pos - num_pos);
1049
1050     switch (t->valtype())
1051     {
1052       case Textual::NUMBER:
1053         result = SASS_MEMORY_NEW(Number,
1054                                  t->pstate(),
1055                                  sass_atof(num.c_str()),
1056                                  "",
1057                                  zero);
1058         break;
1059       case Textual::PERCENTAGE:
1060         result = SASS_MEMORY_NEW(Number,
1061                                  t->pstate(),
1062                                  sass_atof(num.c_str()),
1063                                  "%",
1064                                  true);
1065         break;
1066       case Textual::DIMENSION:
1067         result = SASS_MEMORY_NEW(Number,
1068                                  t->pstate(),
1069                                  sass_atof(num.c_str()),
1070                                  Token(number(text.c_str())),
1071                                  zero);
1072         break;
1073       case Textual::HEX: {
1074         if (t->value().substr(0, 1) != "#") {
1075           result = SASS_MEMORY_NEW(String_Quoted, t->pstate(), t->value());
1076           break;
1077         }
1078         std::string hext(t->value().substr(1)); // chop off the '#'
1079         if (hext.length() == 6) {
1080           std::string r(hext.substr(0,2));
1081           std::string g(hext.substr(2,2));
1082           std::string b(hext.substr(4,2));
1083           result = SASS_MEMORY_NEW(Color,
1084                                    t->pstate(),
1085                                    static_cast<double>(strtol(r.c_str(), NULL, 16)),
1086                                    static_cast<double>(strtol(g.c_str(), NULL, 16)),
1087                                    static_cast<double>(strtol(b.c_str(), NULL, 16)),
1088                                    1, // alpha channel
1089                                    t->value());
1090         }
1091         else {
1092           result = SASS_MEMORY_NEW(Color,
1093                                    t->pstate(),
1094                                    static_cast<double>(strtol(std::string(2,hext[0]).c_str(), NULL, 16)),
1095                                    static_cast<double>(strtol(std::string(2,hext[1]).c_str(), NULL, 16)),
1096                                    static_cast<double>(strtol(std::string(2,hext[2]).c_str(), NULL, 16)),
1097                                    1, // alpha channel
1098                                    t->value());
1099         }
1100       } break;
1101     }
1102     result->is_interpolant(t->is_interpolant());
1103     return result.detach();
1104   }
1105
1106   Expression_Ptr Eval::operator()(Color_Ptr c)
1107   {
1108     return c;
1109   }
1110
1111   Expression_Ptr Eval::operator()(Number_Ptr n)
1112   {
1113     return n;
1114   }
1115
1116   Expression_Ptr Eval::operator()(Boolean_Ptr b)
1117   {
1118     return b;
1119   }
1120
1121   void Eval::interpolation(Context& ctx, std::string& res, Expression_Obj ex, bool into_quotes, bool was_itpl) {
1122
1123     bool needs_closing_brace = false;
1124
1125     if (Arguments_Ptr args = Cast<Arguments>(ex)) {
1126       List_Ptr ll = SASS_MEMORY_NEW(List, args->pstate(), 0, SASS_COMMA);
1127       for(auto arg : args->elements()) {
1128         ll->append(arg->value());
1129       }
1130       ll->is_interpolant(args->is_interpolant());
1131       needs_closing_brace = true;
1132       res += "(";
1133       ex = ll;
1134     }
1135     if (Number_Ptr nr = Cast<Number>(ex)) {
1136       if (!nr->is_valid_css_unit()) {
1137         throw Exception::InvalidValue(*nr);
1138       }
1139     }
1140     if (Argument_Ptr arg = Cast<Argument>(ex)) {
1141       ex = arg->value();
1142     }
1143     if (String_Quoted_Ptr sq = Cast<String_Quoted>(ex)) {
1144       if (was_itpl) {
1145         bool was_interpolant = ex->is_interpolant();
1146         ex = SASS_MEMORY_NEW(String_Constant, sq->pstate(), sq->value());
1147         ex->is_interpolant(was_interpolant);
1148       }
1149     }
1150
1151     if (Cast<Null>(ex)) { return; }
1152
1153     // parent selector needs another go
1154     if (Cast<Parent_Selector>(ex)) {
1155       // XXX: this is never hit via spec tests
1156       ex = ex->perform(this);
1157     }
1158
1159     if (List_Ptr l = Cast<List>(ex)) {
1160       List_Obj ll = SASS_MEMORY_NEW(List, l->pstate(), 0, l->separator());
1161       // this fixes an issue with bourbon sample, not really sure why
1162       // if (l->size() && Cast<Null>((*l)[0])) { res += ""; }
1163       for(Expression_Obj item : *l) {
1164         item->is_interpolant(l->is_interpolant());
1165         std::string rl(""); interpolation(ctx, rl, item, into_quotes, l->is_interpolant());
1166         bool is_null = Cast<Null>(item) != 0; // rl != ""
1167         if (!is_null) ll->append(SASS_MEMORY_NEW(String_Quoted, item->pstate(), rl));
1168       }
1169       // Check indicates that we probably should not get a list
1170       // here. Normally single list items are already unwrapped.
1171       if (l->size() > 1) {
1172         // string_to_output would fail "#{'_\a' '_\a'}";
1173         std::string str(ll->to_string(ctx.c_options));
1174         newline_to_space(str); // replace directly
1175         res += str; // append to result string
1176       } else {
1177         res += (ll->to_string(ctx.c_options));
1178       }
1179       ll->is_interpolant(l->is_interpolant());
1180     }
1181
1182     // Value
1183     // Textual
1184     // Function_Call
1185     // Selector_List
1186     // String_Quoted
1187     // String_Constant
1188     // Parent_Selector
1189     // Binary_Expression
1190     else {
1191       // ex = ex->perform(this);
1192       if (into_quotes && ex->is_interpolant()) {
1193         res += evacuate_escapes(ex ? ex->to_string(ctx.c_options) : "");
1194       } else {
1195         res += ex ? ex->to_string(ctx.c_options) : "";
1196       }
1197     }
1198
1199     if (needs_closing_brace) res += ")";
1200
1201   }
1202
1203   Expression_Ptr Eval::operator()(String_Schema_Ptr s)
1204   {
1205     size_t L = s->length();
1206     bool into_quotes = false;
1207     if (L > 1) {
1208       if (!Cast<String_Quoted>((*s)[0]) && !Cast<String_Quoted>((*s)[L - 1])) {
1209       if (String_Constant_Ptr l = Cast<String_Constant>((*s)[0])) {
1210         if (String_Constant_Ptr r = Cast<String_Constant>((*s)[L - 1])) {
1211           if (r->value().size() > 0) {
1212             if (l->value()[0] == '"' && r->value()[r->value().size() - 1] == '"') into_quotes = true;
1213             if (l->value()[0] == '\'' && r->value()[r->value().size() - 1] == '\'') into_quotes = true;
1214           }
1215         }
1216       }
1217       }
1218     }
1219     bool was_quoted = false;
1220     bool was_interpolant = false;
1221     std::string res("");
1222     for (size_t i = 0; i < L; ++i) {
1223       bool is_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
1224       if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
1225       else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
1226       Expression_Obj ex = (*s)[i]->perform(this);
1227       interpolation(ctx, res, ex, into_quotes, ex->is_interpolant());
1228       was_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
1229       was_interpolant = (*s)[i]->is_interpolant();
1230
1231     }
1232     if (!s->is_interpolant()) {
1233       if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(Null, s->pstate());
1234       return SASS_MEMORY_NEW(String_Constant, s->pstate(), res);
1235     }
1236     // string schema seems to have a special unquoting behavior (also handles "nested" quotes)
1237     String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), res, 0, false, false, false);
1238     // if (s->is_interpolant()) str->quote_mark(0);
1239     // String_Constant_Ptr str = SASS_MEMORY_NEW(String_Constant, s->pstate(), res);
1240     if (str->quote_mark()) str->quote_mark('*');
1241     else if (!is_in_comment) str->value(string_to_output(str->value()));
1242     str->is_interpolant(s->is_interpolant());
1243     return str.detach();
1244   }
1245
1246
1247   Expression_Ptr Eval::operator()(String_Constant_Ptr s)
1248   {
1249     if (!s->is_delayed() && name_to_color(s->value())) {
1250       Color_Ptr c = SASS_MEMORY_COPY(name_to_color(s->value())); // copy
1251       c->pstate(s->pstate());
1252       c->disp(s->value());
1253       c->is_delayed(true);
1254       return c;
1255     }
1256     return s;
1257   }
1258
1259   Expression_Ptr Eval::operator()(String_Quoted_Ptr s)
1260   {
1261     String_Quoted_Ptr str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), "");
1262     str->value(s->value());
1263     str->quote_mark(s->quote_mark());
1264     str->is_interpolant(s->is_interpolant());
1265     return str;
1266   }
1267
1268   Expression_Ptr Eval::operator()(Supports_Operator_Ptr c)
1269   {
1270     Expression_Ptr left = c->left()->perform(this);
1271     Expression_Ptr right = c->right()->perform(this);
1272     Supports_Operator_Ptr cc = SASS_MEMORY_NEW(Supports_Operator,
1273                                  c->pstate(),
1274                                  Cast<Supports_Condition>(left),
1275                                  Cast<Supports_Condition>(right),
1276                                  c->operand());
1277     return cc;
1278   }
1279
1280   Expression_Ptr Eval::operator()(Supports_Negation_Ptr c)
1281   {
1282     Expression_Ptr condition = c->condition()->perform(this);
1283     Supports_Negation_Ptr cc = SASS_MEMORY_NEW(Supports_Negation,
1284                                  c->pstate(),
1285                                  Cast<Supports_Condition>(condition));
1286     return cc;
1287   }
1288
1289   Expression_Ptr Eval::operator()(Supports_Declaration_Ptr c)
1290   {
1291     Expression_Ptr feature = c->feature()->perform(this);
1292     Expression_Ptr value = c->value()->perform(this);
1293     Supports_Declaration_Ptr cc = SASS_MEMORY_NEW(Supports_Declaration,
1294                               c->pstate(),
1295                               feature,
1296                               value);
1297     return cc;
1298   }
1299
1300   Expression_Ptr Eval::operator()(Supports_Interpolation_Ptr c)
1301   {
1302     Expression_Ptr value = c->value()->perform(this);
1303     Supports_Interpolation_Ptr cc = SASS_MEMORY_NEW(Supports_Interpolation,
1304                             c->pstate(),
1305                             value);
1306     return cc;
1307   }
1308
1309   Expression_Ptr Eval::operator()(At_Root_Query_Ptr e)
1310   {
1311     Expression_Obj feature = e->feature();
1312     feature = (feature ? feature->perform(this) : 0);
1313     Expression_Obj value = e->value();
1314     value = (value ? value->perform(this) : 0);
1315     Expression_Ptr ee = SASS_MEMORY_NEW(At_Root_Query,
1316                                      e->pstate(),
1317                                      Cast<String>(feature),
1318                                      value);
1319     return ee;
1320   }
1321
1322   Expression_Ptr Eval::operator()(Media_Query_Ptr q)
1323   {
1324     String_Obj t = q->media_type();
1325     t = static_cast<String_Ptr>(t.isNull() ? 0 : t->perform(this));
1326     Media_Query_Obj qq = SASS_MEMORY_NEW(Media_Query,
1327                                       q->pstate(),
1328                                       t,
1329                                       q->length(),
1330                                       q->is_negated(),
1331                                       q->is_restricted());
1332     for (size_t i = 0, L = q->length(); i < L; ++i) {
1333       qq->append(static_cast<Media_Query_Expression_Ptr>((*q)[i]->perform(this)));
1334     }
1335     return qq.detach();
1336   }
1337
1338   Expression_Ptr Eval::operator()(Media_Query_Expression_Ptr e)
1339   {
1340     Expression_Obj feature = e->feature();
1341     feature = (feature ? feature->perform(this) : 0);
1342     if (feature && Cast<String_Quoted>(feature)) {
1343       feature = SASS_MEMORY_NEW(String_Quoted,
1344                                   feature->pstate(),
1345                                   Cast<String_Quoted>(feature)->value());
1346     }
1347     Expression_Obj value = e->value();
1348     value = (value ? value->perform(this) : 0);
1349     if (value && Cast<String_Quoted>(value)) {
1350       // XXX: this is never hit via spec tests
1351       value = SASS_MEMORY_NEW(String_Quoted,
1352                                 value->pstate(),
1353                                 Cast<String_Quoted>(value)->value());
1354     }
1355     return SASS_MEMORY_NEW(Media_Query_Expression,
1356                            e->pstate(),
1357                            feature,
1358                            value,
1359                            e->is_interpolated());
1360   }
1361
1362   Expression_Ptr Eval::operator()(Null_Ptr n)
1363   {
1364     return n;
1365   }
1366
1367   Expression_Ptr Eval::operator()(Argument_Ptr a)
1368   {
1369     Expression_Obj val = a->value()->perform(this);
1370     bool is_rest_argument = a->is_rest_argument();
1371     bool is_keyword_argument = a->is_keyword_argument();
1372
1373     if (a->is_rest_argument()) {
1374       if (val->concrete_type() == Expression::MAP) {
1375         is_rest_argument = false;
1376         is_keyword_argument = true;
1377       }
1378       else if(val->concrete_type() != Expression::LIST) {
1379         List_Obj wrapper = SASS_MEMORY_NEW(List,
1380                                         val->pstate(),
1381                                         0,
1382                                         SASS_COMMA,
1383                                         true);
1384         wrapper->append(val);
1385         val = wrapper;
1386       }
1387     }
1388     return SASS_MEMORY_NEW(Argument,
1389                            a->pstate(),
1390                            val,
1391                            a->name(),
1392                            is_rest_argument,
1393                            is_keyword_argument);
1394   }
1395
1396   Expression_Ptr Eval::operator()(Arguments_Ptr a)
1397   {
1398     Arguments_Obj aa = SASS_MEMORY_NEW(Arguments, a->pstate());
1399     if (a->length() == 0) return aa.detach();
1400     for (size_t i = 0, L = a->length(); i < L; ++i) {
1401       Expression_Obj rv = (*a)[i]->perform(this);
1402       Argument_Ptr arg = Cast<Argument>(rv);
1403       if (!(arg->is_rest_argument() || arg->is_keyword_argument())) {
1404         aa->append(arg);
1405       }
1406     }
1407
1408     if (a->has_rest_argument()) {
1409       Expression_Obj rest = a->get_rest_argument()->perform(this);
1410       Expression_Obj splat = Cast<Argument>(rest)->value()->perform(this);
1411
1412       Sass_Separator separator = SASS_COMMA;
1413       List_Ptr ls = Cast<List>(splat);
1414       Map_Ptr ms = Cast<Map>(splat);
1415
1416       List_Obj arglist = SASS_MEMORY_NEW(List,
1417                                       splat->pstate(),
1418                                       0,
1419                                       ls ? ls->separator() : separator,
1420                                       true);
1421
1422       if (ls && ls->is_arglist()) {
1423         arglist->concat(ls);
1424       } else if (ms) {
1425         aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), ms, "", false, true));
1426       } else if (ls) {
1427         arglist->concat(ls);
1428       } else {
1429         arglist->append(splat);
1430       }
1431       if (arglist->length()) {
1432         aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), arglist, "", true));
1433       }
1434     }
1435
1436     if (a->has_keyword_argument()) {
1437       Expression_Obj rv = a->get_keyword_argument()->perform(this);
1438       Argument_Ptr rvarg = Cast<Argument>(rv);
1439       Expression_Obj kwarg = rvarg->value()->perform(this);
1440
1441       aa->append(SASS_MEMORY_NEW(Argument, kwarg->pstate(), kwarg, "", false, true));
1442     }
1443     return aa.detach();
1444   }
1445
1446   Expression_Ptr Eval::operator()(Comment_Ptr c)
1447   {
1448     return 0;
1449   }
1450
1451   inline Expression_Ptr Eval::fallback_impl(AST_Node_Ptr n)
1452   {
1453     return static_cast<Expression_Ptr>(n);
1454   }
1455
1456   // All the binary helpers.
1457
1458   bool Eval::eq(Expression_Obj lhs, Expression_Obj rhs)
1459   {
1460     // use compare operator from ast node
1461     return lhs && rhs && *lhs == *rhs;
1462   }
1463
1464   bool Eval::lt(Expression_Obj lhs, Expression_Obj rhs, std::string op)
1465   {
1466     Number_Obj l = Cast<Number>(lhs);
1467     Number_Obj r = Cast<Number>(rhs);
1468     // use compare operator from ast node
1469     if (!l || !r) throw Exception::UndefinedOperation(lhs, rhs, op);
1470     // use compare operator from ast node
1471     return *l < *r;
1472   }
1473
1474   Value_Ptr Eval::op_numbers(enum Sass_OP op, const Number& l, const Number& r, struct Sass_Inspect_Options opt, ParserState* pstate)
1475   {
1476     double lv = l.value();
1477     double rv = r.value();
1478     if (op == Sass_OP::DIV && rv == 0) {
1479       // XXX: this is never hit via spec tests
1480       return SASS_MEMORY_NEW(String_Quoted, pstate ? *pstate : l.pstate(), lv ? "Infinity" : "NaN");
1481     }
1482     if (op == Sass_OP::MOD && !rv) {
1483       // XXX: this is never hit via spec tests
1484       throw Exception::ZeroDivisionError(l, r);
1485     }
1486
1487     Number tmp(&r); // copy
1488     bool strict = op != Sass_OP::MUL && op != Sass_OP::DIV;
1489     tmp.normalize(l.find_convertible_unit(), strict);
1490     std::string l_unit(l.unit());
1491     std::string r_unit(tmp.unit());
1492     Number_Obj v = SASS_MEMORY_COPY(&l); // copy
1493     v->pstate(pstate ? *pstate : l.pstate());
1494     if (l_unit.empty() && (op == Sass_OP::ADD || op == Sass_OP::SUB || op == Sass_OP::MOD)) {
1495       v->numerator_units() = r.numerator_units();
1496       v->denominator_units() = r.denominator_units();
1497     }
1498
1499     if (op == Sass_OP::MUL) {
1500       v->value(ops[op](lv, rv));
1501       for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) {
1502         v->numerator_units().push_back(r.numerator_units()[i]);
1503       }
1504       for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) {
1505         v->denominator_units().push_back(r.denominator_units()[i]);
1506       }
1507     }
1508     else if (op == Sass_OP::DIV) {
1509       v->value(ops[op](lv, rv));
1510       for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) {
1511         v->denominator_units().push_back(r.numerator_units()[i]);
1512       }
1513       for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) {
1514         v->numerator_units().push_back(r.denominator_units()[i]);
1515       }
1516     } else {
1517       v->value(ops[op](lv, r.value() * r.convert_factor(l)));
1518       // v->normalize();
1519       return v.detach();
1520
1521       v->value(ops[op](lv, tmp.value()));
1522     }
1523     v->normalize();
1524     return v.detach();
1525   }
1526
1527   Value_Ptr Eval::op_number_color(enum Sass_OP op, const Number& l, const Color& r, struct Sass_Inspect_Options opt, ParserState* pstate)
1528   {
1529     double lv = l.value();
1530     switch (op) {
1531       case Sass_OP::ADD:
1532       case Sass_OP::MUL: {
1533         return SASS_MEMORY_NEW(Color,
1534                                pstate ? *pstate : l.pstate(),
1535                                ops[op](lv, r.r()),
1536                                ops[op](lv, r.g()),
1537                                ops[op](lv, r.b()),
1538                                r.a());
1539       } break;
1540       case Sass_OP::SUB:
1541       case Sass_OP::DIV: {
1542         std::string sep(op == Sass_OP::SUB ? "-" : "/");
1543         std::string color(r.to_string(opt));
1544         return SASS_MEMORY_NEW(String_Quoted,
1545                                pstate ? *pstate : l.pstate(),
1546                                l.to_string(opt)
1547                                + sep
1548                                + color);
1549       } break;
1550       case Sass_OP::MOD: {
1551         throw Exception::UndefinedOperation(&l, &r, sass_op_to_name(op));
1552       } break;
1553       default: break; // caller should ensure that we don't get here
1554     }
1555     // unreachable
1556     return NULL;
1557   }
1558
1559   Value_Ptr Eval::op_color_number(enum Sass_OP op, const Color& l, const Number& r, struct Sass_Inspect_Options opt, ParserState* pstate)
1560   {
1561     double rv = r.value();
1562     if (op == Sass_OP::DIV && !rv) {
1563       // comparison of Fixnum with Float failed?
1564       throw Exception::ZeroDivisionError(l, r);
1565     }
1566     return SASS_MEMORY_NEW(Color,
1567                            pstate ? *pstate : l.pstate(),
1568                            ops[op](l.r(), rv),
1569                            ops[op](l.g(), rv),
1570                            ops[op](l.b(), rv),
1571                            l.a());
1572   }
1573
1574   Value_Ptr Eval::op_colors(enum Sass_OP op, const Color& l, const Color& r, struct Sass_Inspect_Options opt, ParserState* pstate)
1575   {
1576     if (l.a() != r.a()) {
1577       throw Exception::AlphaChannelsNotEqual(&l, &r, "+");
1578     }
1579     if (op == Sass_OP::DIV && (!r.r() || !r.g() ||!r.b())) {
1580       // comparison of Fixnum with Float failed?
1581       throw Exception::ZeroDivisionError(l, r);
1582     }
1583     return SASS_MEMORY_NEW(Color,
1584                            pstate ? *pstate : l.pstate(),
1585                            ops[op](l.r(), r.r()),
1586                            ops[op](l.g(), r.g()),
1587                            ops[op](l.b(), r.b()),
1588                            l.a());
1589   }
1590
1591   Value_Ptr Eval::op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, ParserState* pstate, bool delayed)
1592   {
1593     Expression::Concrete_Type ltype = lhs.concrete_type();
1594     Expression::Concrete_Type rtype = rhs.concrete_type();
1595     enum Sass_OP op = operand.operand;
1596
1597     String_Quoted_Ptr lqstr = Cast<String_Quoted>(&lhs);
1598     String_Quoted_Ptr rqstr = Cast<String_Quoted>(&rhs);
1599
1600     std::string lstr(lqstr ? lqstr->value() : lhs.to_string(opt));
1601     std::string rstr(rqstr ? rqstr->value() : rhs.to_string(opt));
1602
1603     if (ltype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op));
1604     if (rtype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op));
1605     if (op == Sass_OP::MOD) throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op));
1606     if (op == Sass_OP::MUL) throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op));
1607     std::string sep;
1608     switch (op) {
1609       case Sass_OP::SUB: sep = "-"; break;
1610       case Sass_OP::DIV: sep = "/"; break;
1611       case Sass_OP::MUL: sep = "*"; break;
1612       case Sass_OP::MOD: sep = "%"; break;
1613       case Sass_OP::EQ:  sep = "=="; break;
1614       case Sass_OP::NEQ:  sep = "!="; break;
1615       case Sass_OP::LT:  sep = "<"; break;
1616       case Sass_OP::GT:  sep = ">"; break;
1617       case Sass_OP::LTE:  sep = "<="; break;
1618       case Sass_OP::GTE:  sep = ">="; break;
1619       default:                      break;
1620     }
1621
1622     if ( (sep == "") /* &&
1623          (sep != "/" || !rqstr || !rqstr->quote_mark()) */
1624     ) {
1625       // create a new string that might be quoted on output (but do not unquote what we pass)
1626       return SASS_MEMORY_NEW(String_Quoted, pstate ? *pstate : lhs.pstate(), lstr + rstr, 0, false, true);
1627     }
1628
1629     if (sep != "" && !delayed) {
1630       if (operand.ws_before) sep = " " + sep;
1631       if (operand.ws_after) sep = sep + " ";
1632     }
1633
1634     if (op == Sass_OP::SUB || op == Sass_OP::DIV) {
1635       if (lqstr && lqstr->quote_mark()) lstr = quote(lstr);
1636       if (rqstr && rqstr->quote_mark()) rstr = quote(rstr);
1637     }
1638
1639     return SASS_MEMORY_NEW(String_Constant, pstate ? *pstate : lhs.pstate(), lstr + sep + rstr);
1640   }
1641
1642   Expression_Ptr cval_to_astnode(union Sass_Value* v, Backtrace* backtrace, ParserState pstate)
1643   {
1644     using std::strlen;
1645     using std::strcpy;
1646     Expression_Ptr e = NULL;
1647     switch (sass_value_get_tag(v)) {
1648       case SASS_BOOLEAN: {
1649         e = SASS_MEMORY_NEW(Boolean, pstate, !!sass_boolean_get_value(v));
1650       } break;
1651       case SASS_NUMBER: {
1652         e = SASS_MEMORY_NEW(Number, pstate, sass_number_get_value(v), sass_number_get_unit(v));
1653       } break;
1654       case SASS_COLOR: {
1655         e = SASS_MEMORY_NEW(Color, pstate, sass_color_get_r(v), sass_color_get_g(v), sass_color_get_b(v), sass_color_get_a(v));
1656       } break;
1657       case SASS_STRING: {
1658         if (sass_string_is_quoted(v))
1659           e = SASS_MEMORY_NEW(String_Quoted, pstate, sass_string_get_value(v));
1660         else {
1661           e = SASS_MEMORY_NEW(String_Constant, pstate, sass_string_get_value(v));
1662         }
1663       } break;
1664       case SASS_LIST: {
1665         List_Ptr l = SASS_MEMORY_NEW(List, pstate, sass_list_get_length(v), sass_list_get_separator(v));
1666         for (size_t i = 0, L = sass_list_get_length(v); i < L; ++i) {
1667           l->append(cval_to_astnode(sass_list_get_value(v, i), backtrace, pstate));
1668         }
1669         l->is_bracketed(sass_list_get_is_bracketed(v));
1670         e = l;
1671       } break;
1672       case SASS_MAP: {
1673         Map_Ptr m = SASS_MEMORY_NEW(Map, pstate);
1674         for (size_t i = 0, L = sass_map_get_length(v); i < L; ++i) {
1675           *m << std::make_pair(
1676             cval_to_astnode(sass_map_get_key(v, i), backtrace, pstate),
1677             cval_to_astnode(sass_map_get_value(v, i), backtrace, pstate));
1678         }
1679         e = m;
1680       } break;
1681       case SASS_NULL: {
1682         e = SASS_MEMORY_NEW(Null, pstate);
1683       } break;
1684       case SASS_ERROR: {
1685         error("Error in C function: " + std::string(sass_error_get_message(v)), pstate, backtrace);
1686       } break;
1687       case SASS_WARNING: {
1688         error("Warning in C function: " + std::string(sass_warning_get_message(v)), pstate, backtrace);
1689       } break;
1690     }
1691     return e;
1692   }
1693
1694   Selector_List_Ptr Eval::operator()(Selector_List_Ptr s)
1695   {
1696     std::vector<Selector_List_Obj> rv;
1697     Selector_List_Obj sl = SASS_MEMORY_NEW(Selector_List, s->pstate());
1698     sl->is_optional(s->is_optional());
1699     sl->media_block(s->media_block());
1700     sl->is_optional(s->is_optional());
1701     for (size_t i = 0, iL = s->length(); i < iL; ++i) {
1702       rv.push_back(operator()((*s)[i]));
1703     }
1704
1705     // we should actually permutate parent first
1706     // but here we have permutated the selector first
1707     size_t round = 0;
1708     while (round != std::string::npos) {
1709       bool abort = true;
1710       for (size_t i = 0, iL = rv.size(); i < iL; ++i) {
1711         if (rv[i]->length() > round) {
1712           sl->append((*rv[i])[round]);
1713           abort = false;
1714         }
1715       }
1716       if (abort) {
1717         round = std::string::npos;
1718       } else {
1719         ++ round;
1720       }
1721
1722     }
1723     return sl.detach();
1724   }
1725
1726
1727   Selector_List_Ptr Eval::operator()(Complex_Selector_Ptr s)
1728   {
1729     bool implicit_parent = !exp.old_at_root_without_rule;
1730     return s->resolve_parent_refs(ctx, exp.selector_stack, implicit_parent);
1731   }
1732
1733   // XXX: this is never hit via spec tests
1734   Attribute_Selector_Ptr Eval::operator()(Attribute_Selector_Ptr s)
1735   {
1736     String_Obj attr = s->value();
1737     if (attr) { attr = static_cast<String_Ptr>(attr->perform(this)); }
1738     Attribute_Selector_Ptr ss = SASS_MEMORY_COPY(s);
1739     ss->value(attr);
1740     return ss;
1741   }
1742
1743   Selector_List_Ptr Eval::operator()(Selector_Schema_Ptr s)
1744   {
1745     // the parser will look for a brace to end the selector
1746     Expression_Obj sel = s->contents()->perform(this);
1747     std::string result_str(sel->to_string(ctx.c_options));
1748     result_str = unquote(Util::rtrim(result_str));
1749     Parser p = Parser::from_c_str(result_str.c_str(), ctx, s->pstate());
1750     p.last_media_block = s->media_block();
1751     // a selector schema may or may not connect to parent?
1752     bool chroot = s->connect_parent() == false;
1753     Selector_List_Obj sl = p.parse_selector_list(chroot);
1754     return operator()(sl);
1755   }
1756
1757   Expression_Ptr Eval::operator()(Parent_Selector_Ptr p)
1758   {
1759     if (Selector_List_Obj pr = selector()) {
1760       exp.selector_stack.pop_back();
1761       Selector_List_Obj rv = operator()(pr);
1762       exp.selector_stack.push_back(rv);
1763       return rv.detach();
1764     } else {
1765       return SASS_MEMORY_NEW(Null, p->pstate());
1766     }
1767   }
1768
1769 }