|
Packit Service |
7770af |
#include "sass.hpp"
|
|
Packit Service |
7770af |
#include <cstdlib>
|
|
Packit Service |
7770af |
#include <cmath>
|
|
Packit Service |
7770af |
#include <iostream>
|
|
Packit Service |
7770af |
#include <sstream>
|
|
Packit Service |
7770af |
#include <iomanip>
|
|
Packit Service |
7770af |
#include <typeinfo>
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
#include "file.hpp"
|
|
Packit Service |
7770af |
#include "eval.hpp"
|
|
Packit Service |
7770af |
#include "ast.hpp"
|
|
Packit Service |
7770af |
#include "bind.hpp"
|
|
Packit Service |
7770af |
#include "util.hpp"
|
|
Packit Service |
7770af |
#include "inspect.hpp"
|
|
Packit Service |
7770af |
#include "environment.hpp"
|
|
Packit Service |
7770af |
#include "position.hpp"
|
|
Packit Service |
7770af |
#include "sass/values.h"
|
|
Packit Service |
7770af |
#include "to_value.hpp"
|
|
Packit Service |
7770af |
#include "to_c.hpp"
|
|
Packit Service |
7770af |
#include "context.hpp"
|
|
Packit Service |
7770af |
#include "backtrace.hpp"
|
|
Packit Service |
7770af |
#include "lexer.hpp"
|
|
Packit Service |
7770af |
#include "prelexer.hpp"
|
|
Packit Service |
7770af |
#include "parser.hpp"
|
|
Packit Service |
7770af |
#include "expand.hpp"
|
|
Packit Service |
7770af |
#include "color_maps.hpp"
|
|
Packit Service |
7770af |
#include "sass_functions.hpp"
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
namespace Sass {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
inline double add(double x, double y) { return x + y; }
|
|
Packit Service |
7770af |
inline double sub(double x, double y) { return x - y; }
|
|
Packit Service |
7770af |
inline double mul(double x, double y) { return x * y; }
|
|
Packit Service |
7770af |
inline double div(double x, double y) { return x / y; } // x/0 checked by caller
|
|
Packit Service |
7770af |
inline double mod(double x, double y) { // x/0 checked by caller
|
|
Packit Service |
7770af |
if ((x > 0 && y < 0) || (x < 0 && y > 0)) {
|
|
Packit Service |
7770af |
double ret = std::fmod(x, y);
|
|
Packit Service |
7770af |
return ret ? ret + y : ret;
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
return std::fmod(x, y);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
typedef double (*bop)(double, double);
|
|
Packit Service |
7770af |
bop ops[Sass_OP::NUM_OPS] = {
|
|
Packit Service |
7770af |
0, 0, // and, or
|
|
Packit Service |
7770af |
0, 0, 0, 0, 0, 0, // eq, neq, gt, gte, lt, lte
|
|
Packit Service |
7770af |
add, sub, mul, div, mod
|
|
Packit Service |
7770af |
};
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Eval::Eval(Expand& exp)
|
|
Packit Service |
7770af |
: exp(exp),
|
|
Packit Service |
7770af |
ctx(exp.ctx),
|
|
Packit Service |
7770af |
force(false),
|
|
Packit Service |
7770af |
is_in_comment(false),
|
|
Packit Service |
7770af |
is_in_selector_schema(false)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
bool_true = SASS_MEMORY_NEW(Boolean, "[NA]", true);
|
|
Packit Service |
7770af |
bool_false = SASS_MEMORY_NEW(Boolean, "[NA]", false);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
Eval::~Eval() { }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Env* Eval::environment()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return exp.environment();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Selector_List_Obj Eval::selector()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return exp.selector();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Backtrace* Eval::backtrace()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return exp.backtrace();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Block_Ptr b)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Ptr val = 0;
|
|
Packit Service |
7770af |
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
|
Packit Service |
7770af |
val = b->at(i)->perform(this);
|
|
Packit Service |
7770af |
if (val) return val;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return val;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Assignment_Ptr a)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Env* env = exp.environment();
|
|
Packit Service |
7770af |
std::string var(a->variable());
|
|
Packit Service |
7770af |
if (a->is_global()) {
|
|
Packit Service |
7770af |
if (a->is_default()) {
|
|
Packit Service |
7770af |
if (env->has_global(var)) {
|
|
Packit Service |
7770af |
Expression_Ptr e = Cast<Expression>(env->get_global(var));
|
|
Packit Service |
7770af |
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
|
Packit Service |
7770af |
env->set_global(var, a->value()->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
env->set_global(var, a->value()->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
env->set_global(var, a->value()->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (a->is_default()) {
|
|
Packit Service |
7770af |
if (env->has_lexical(var)) {
|
|
Packit Service |
7770af |
auto cur = env;
|
|
Packit Service |
7770af |
while (cur && cur->is_lexical()) {
|
|
Packit Service |
7770af |
if (cur->has_local(var)) {
|
|
Packit Service |
7770af |
if (AST_Node_Obj node = cur->get_local(var)) {
|
|
Packit Service |
7770af |
Expression_Ptr e = Cast<Expression>(node);
|
|
Packit Service |
7770af |
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
|
Packit Service |
7770af |
cur->set_local(var, a->value()->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
throw std::runtime_error("Env not in sync");
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
cur = cur->parent();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
throw std::runtime_error("Env not in sync");
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (env->has_global(var)) {
|
|
Packit Service |
7770af |
if (AST_Node_Obj node = env->get_global(var)) {
|
|
Packit Service |
7770af |
Expression_Ptr e = Cast<Expression>(node);
|
|
Packit Service |
7770af |
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
|
Packit Service |
7770af |
env->set_global(var, a->value()->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (env->is_lexical()) {
|
|
Packit Service |
7770af |
env->set_local(var, a->value()->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
env->set_local(var, a->value()->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
env->set_lexical(var, a->value()->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(If_Ptr i)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Obj rv = 0;
|
|
Packit Service |
7770af |
Env env(exp.environment());
|
|
Packit Service |
7770af |
exp.env_stack.push_back(&env;;
|
|
Packit Service |
7770af |
Expression_Obj cond = i->predicate()->perform(this);
|
|
Packit Service |
7770af |
if (!cond->is_false()) {
|
|
Packit Service |
7770af |
rv = i->block()->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
Block_Obj alt = i->alternative();
|
|
Packit Service |
7770af |
if (alt) rv = alt->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
exp.env_stack.pop_back();
|
|
Packit Service |
7770af |
return rv.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// For does not create a new env scope
|
|
Packit Service |
7770af |
// But iteration vars are reset afterwards
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(For_Ptr f)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::string variable(f->variable());
|
|
Packit Service |
7770af |
Expression_Obj low = f->lower_bound()->perform(this);
|
|
Packit Service |
7770af |
if (low->concrete_type() != Expression::NUMBER) {
|
|
Packit Service |
7770af |
throw Exception::TypeMismatch(*low, "integer");
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
Expression_Obj high = f->upper_bound()->perform(this);
|
|
Packit Service |
7770af |
if (high->concrete_type() != Expression::NUMBER) {
|
|
Packit Service |
7770af |
throw Exception::TypeMismatch(*high, "integer");
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
Number_Obj sass_start = Cast<Number>(low);
|
|
Packit Service |
7770af |
Number_Obj sass_end = Cast<Number>(high);
|
|
Packit Service |
7770af |
// check if units are valid for sequence
|
|
Packit Service |
7770af |
if (sass_start->unit() != sass_end->unit()) {
|
|
Packit Service |
7770af |
std::stringstream msg; msg << "Incompatible units: '"
|
|
Packit Service |
7770af |
<< sass_end->unit() << "' and '"
|
|
Packit Service |
7770af |
<< sass_start->unit() << "'.";
|
|
Packit Service |
7770af |
error(msg.str(), low->pstate(), backtrace());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
double start = sass_start->value();
|
|
Packit Service |
7770af |
double end = sass_end->value();
|
|
Packit Service |
7770af |
// only create iterator once in this environment
|
|
Packit Service |
7770af |
Env env(environment(), true);
|
|
Packit Service |
7770af |
exp.env_stack.push_back(&env;;
|
|
Packit Service |
7770af |
Block_Obj body = f->block();
|
|
Packit Service |
7770af |
Expression_Ptr val = 0;
|
|
Packit Service |
7770af |
if (start < end) {
|
|
Packit Service |
7770af |
if (f->is_inclusive()) ++end;
|
|
Packit Service |
7770af |
for (double i = start;
|
|
Packit Service |
7770af |
i < end;
|
|
Packit Service |
7770af |
++i) {
|
|
Packit Service |
7770af |
Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
|
|
Packit Service |
7770af |
env.set_local(variable, it);
|
|
Packit Service |
7770af |
val = body->perform(this);
|
|
Packit Service |
7770af |
if (val) break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
if (f->is_inclusive()) --end;
|
|
Packit Service |
7770af |
for (double i = start;
|
|
Packit Service |
7770af |
i > end;
|
|
Packit Service |
7770af |
--i) {
|
|
Packit Service |
7770af |
Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
|
|
Packit Service |
7770af |
env.set_local(variable, it);
|
|
Packit Service |
7770af |
val = body->perform(this);
|
|
Packit Service |
7770af |
if (val) break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
exp.env_stack.pop_back();
|
|
Packit Service |
7770af |
return val;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Eval does not create a new env scope
|
|
Packit Service |
7770af |
// But iteration vars are reset afterwards
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Each_Ptr e)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::vector<std::string> variables(e->variables());
|
|
Packit Service |
7770af |
Expression_Obj expr = e->list()->perform(this);
|
|
Packit Service |
7770af |
Env env(environment(), true);
|
|
Packit Service |
7770af |
exp.env_stack.push_back(&env;;
|
|
Packit Service |
7770af |
List_Obj list = 0;
|
|
Packit Service |
7770af |
Map_Ptr map = 0;
|
|
Packit Service |
7770af |
if (expr->concrete_type() == Expression::MAP) {
|
|
Packit Service |
7770af |
map = Cast<Map>(expr);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (Selector_List_Ptr ls = Cast<Selector_List>(expr)) {
|
|
Packit Service |
7770af |
Listize listize;
|
|
Packit Service |
7770af |
Expression_Obj rv = ls->perform(&listize);
|
|
Packit Service |
7770af |
list = Cast<List>(rv);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (expr->concrete_type() != Expression::LIST) {
|
|
Packit Service |
7770af |
list = SASS_MEMORY_NEW(List, expr->pstate(), 1, SASS_COMMA);
|
|
Packit Service |
7770af |
list->append(expr);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
list = Cast<List>(expr);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Block_Obj body = e->block();
|
|
Packit Service |
7770af |
Expression_Obj val = 0;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (map) {
|
|
Packit Service |
7770af |
for (Expression_Obj key : map->keys()) {
|
|
Packit Service |
7770af |
Expression_Obj value = map->at(key);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (variables.size() == 1) {
|
|
Packit Service |
7770af |
List_Ptr variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE);
|
|
Packit Service |
7770af |
variable->append(key);
|
|
Packit Service |
7770af |
variable->append(value);
|
|
Packit Service |
7770af |
env.set_local(variables[0], variable);
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
env.set_local(variables[0], key);
|
|
Packit Service |
7770af |
env.set_local(variables[1], value);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
val = body->perform(this);
|
|
Packit Service |
7770af |
if (val) break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
if (list->length() == 1 && Cast<Selector_List>(list)) {
|
|
Packit Service |
7770af |
list = Cast<List>(list);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
for (size_t i = 0, L = list->length(); i < L; ++i) {
|
|
Packit Service |
7770af |
Expression_Ptr item = list->at(i);
|
|
Packit Service |
7770af |
// unwrap value if the expression is an argument
|
|
Packit Service |
7770af |
if (Argument_Ptr arg = Cast<Argument>(item)) item = arg->value();
|
|
Packit Service |
7770af |
// check if we got passed a list of args (investigate)
|
|
Packit Service |
7770af |
if (List_Ptr scalars = Cast<List>(item)) {
|
|
Packit Service |
7770af |
if (variables.size() == 1) {
|
|
Packit Service |
7770af |
Expression_Ptr var = scalars;
|
|
Packit Service |
7770af |
env.set_local(variables[0], var);
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
// XXX: this is never hit via spec tests
|
|
Packit Service |
7770af |
for (size_t j = 0, K = variables.size(); j < K; ++j) {
|
|
Packit Service |
7770af |
Expression_Ptr res = j >= scalars->length()
|
|
Packit Service |
7770af |
? SASS_MEMORY_NEW(Null, expr->pstate())
|
|
Packit Service |
7770af |
: scalars->at(j);
|
|
Packit Service |
7770af |
env.set_local(variables[j], res);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
if (variables.size() > 0) {
|
|
Packit Service |
7770af |
env.set_local(variables.at(0), item);
|
|
Packit Service |
7770af |
for (size_t j = 1, K = variables.size(); j < K; ++j) {
|
|
Packit Service |
7770af |
// XXX: this is never hit via spec tests
|
|
Packit Service |
7770af |
Expression_Ptr res = SASS_MEMORY_NEW(Null, expr->pstate());
|
|
Packit Service |
7770af |
env.set_local(variables[j], res);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
val = body->perform(this);
|
|
Packit Service |
7770af |
if (val) break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
exp.env_stack.pop_back();
|
|
Packit Service |
7770af |
return val.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(While_Ptr w)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Obj pred = w->predicate();
|
|
Packit Service |
7770af |
Block_Obj body = w->block();
|
|
Packit Service |
7770af |
Env env(environment(), true);
|
|
Packit Service |
7770af |
exp.env_stack.push_back(&env;;
|
|
Packit Service |
7770af |
Expression_Obj cond = pred->perform(this);
|
|
Packit Service |
7770af |
while (!cond->is_false()) {
|
|
Packit Service |
7770af |
Expression_Obj val = body->perform(this);
|
|
Packit Service |
7770af |
if (val) {
|
|
Packit Service |
7770af |
exp.env_stack.pop_back();
|
|
Packit Service |
7770af |
return val.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
cond = pred->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
exp.env_stack.pop_back();
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Return_Ptr r)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return r->value()->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Warning_Ptr w)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Sass_Output_Style outstyle = ctx.c_options.output_style;
|
|
Packit Service |
7770af |
ctx.c_options.output_style = NESTED;
|
|
Packit Service |
7770af |
Expression_Obj message = w->message()->perform(this);
|
|
Packit Service |
7770af |
Env* env = exp.environment();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// try to use generic function
|
|
Packit Service |
7770af |
if (env->has("@warn[f]")) {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// add call stack entry
|
|
Packit Service |
7770af |
ctx.callee_stack.push_back({
|
|
Packit Service |
7770af |
"@warn",
|
|
Packit Service |
7770af |
w->pstate().path,
|
|
Packit Service |
7770af |
w->pstate().line + 1,
|
|
Packit Service |
7770af |
w->pstate().column + 1,
|
|
Packit Service |
7770af |
SASS_CALLEE_FUNCTION,
|
|
Packit Service |
7770af |
{ env }
|
|
Packit Service |
7770af |
});
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Definition_Ptr def = Cast<Definition>((*env)["@warn[f]"]);
|
|
Packit Service |
7770af |
// Block_Obj body = def->block();
|
|
Packit Service |
7770af |
// Native_Function func = def->native_function();
|
|
Packit Service |
7770af |
Sass_Function_Entry c_function = def->c_function();
|
|
Packit Service |
7770af |
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
To_C to_c;
|
|
Packit Service |
7770af |
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
|
|
Packit Service |
7770af |
sass_list_set_value(c_args, 0, message->perform(&to_c));
|
|
Packit Service |
7770af |
union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
|
|
Packit Service |
7770af |
ctx.c_options.output_style = outstyle;
|
|
Packit Service |
7770af |
ctx.callee_stack.pop_back();
|
|
Packit Service |
7770af |
sass_delete_value(c_args);
|
|
Packit Service |
7770af |
sass_delete_value(c_val);
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string result(unquote(message->to_sass()));
|
|
Packit Service |
7770af |
Backtrace top(backtrace(), w->pstate(), "");
|
|
Packit Service |
7770af |
std::cerr << "WARNING: " << result;
|
|
Packit Service |
7770af |
std::cerr << top.to_string();
|
|
Packit Service |
7770af |
std::cerr << std::endl << std::endl;
|
|
Packit Service |
7770af |
ctx.c_options.output_style = outstyle;
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Error_Ptr e)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Sass_Output_Style outstyle = ctx.c_options.output_style;
|
|
Packit Service |
7770af |
ctx.c_options.output_style = NESTED;
|
|
Packit Service |
7770af |
Expression_Obj message = e->message()->perform(this);
|
|
Packit Service |
7770af |
Env* env = exp.environment();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// try to use generic function
|
|
Packit Service |
7770af |
if (env->has("@error[f]")) {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// add call stack entry
|
|
Packit Service |
7770af |
ctx.callee_stack.push_back({
|
|
Packit Service |
7770af |
"@error",
|
|
Packit Service |
7770af |
e->pstate().path,
|
|
Packit Service |
7770af |
e->pstate().line + 1,
|
|
Packit Service |
7770af |
e->pstate().column + 1,
|
|
Packit Service |
7770af |
SASS_CALLEE_FUNCTION,
|
|
Packit Service |
7770af |
{ env }
|
|
Packit Service |
7770af |
});
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Definition_Ptr def = Cast<Definition>((*env)["@error[f]"]);
|
|
Packit Service |
7770af |
// Block_Obj body = def->block();
|
|
Packit Service |
7770af |
// Native_Function func = def->native_function();
|
|
Packit Service |
7770af |
Sass_Function_Entry c_function = def->c_function();
|
|
Packit Service |
7770af |
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
To_C to_c;
|
|
Packit Service |
7770af |
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
|
|
Packit Service |
7770af |
sass_list_set_value(c_args, 0, message->perform(&to_c));
|
|
Packit Service |
7770af |
union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
|
|
Packit Service |
7770af |
ctx.c_options.output_style = outstyle;
|
|
Packit Service |
7770af |
ctx.callee_stack.pop_back();
|
|
Packit Service |
7770af |
sass_delete_value(c_args);
|
|
Packit Service |
7770af |
sass_delete_value(c_val);
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string result(unquote(message->to_sass()));
|
|
Packit Service |
7770af |
ctx.c_options.output_style = outstyle;
|
|
Packit Service |
7770af |
error(result, e->pstate());
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Debug_Ptr d)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Sass_Output_Style outstyle = ctx.c_options.output_style;
|
|
Packit Service |
7770af |
ctx.c_options.output_style = NESTED;
|
|
Packit Service |
7770af |
Expression_Obj message = d->value()->perform(this);
|
|
Packit Service |
7770af |
Env* env = exp.environment();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// try to use generic function
|
|
Packit Service |
7770af |
if (env->has("@debug[f]")) {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// add call stack entry
|
|
Packit Service |
7770af |
ctx.callee_stack.push_back({
|
|
Packit Service |
7770af |
"@debug",
|
|
Packit Service |
7770af |
d->pstate().path,
|
|
Packit Service |
7770af |
d->pstate().line + 1,
|
|
Packit Service |
7770af |
d->pstate().column + 1,
|
|
Packit Service |
7770af |
SASS_CALLEE_FUNCTION,
|
|
Packit Service |
7770af |
{ env }
|
|
Packit Service |
7770af |
});
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Definition_Ptr def = Cast<Definition>((*env)["@debug[f]"]);
|
|
Packit Service |
7770af |
// Block_Obj body = def->block();
|
|
Packit Service |
7770af |
// Native_Function func = def->native_function();
|
|
Packit Service |
7770af |
Sass_Function_Entry c_function = def->c_function();
|
|
Packit Service |
7770af |
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
To_C to_c;
|
|
Packit Service |
7770af |
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
|
|
Packit Service |
7770af |
sass_list_set_value(c_args, 0, message->perform(&to_c));
|
|
Packit Service |
7770af |
union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
|
|
Packit Service |
7770af |
ctx.c_options.output_style = outstyle;
|
|
Packit Service |
7770af |
ctx.callee_stack.pop_back();
|
|
Packit Service |
7770af |
sass_delete_value(c_args);
|
|
Packit Service |
7770af |
sass_delete_value(c_val);
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string cwd(ctx.cwd());
|
|
Packit Service |
7770af |
std::string result(unquote(message->to_sass()));
|
|
Packit Service |
7770af |
std::string abs_path(Sass::File::rel2abs(d->pstate().path, cwd, cwd));
|
|
Packit Service |
7770af |
std::string rel_path(Sass::File::abs2rel(d->pstate().path, cwd, cwd));
|
|
Packit Service |
7770af |
std::string output_path(Sass::File::path_for_console(rel_path, abs_path, d->pstate().path));
|
|
Packit Service |
7770af |
ctx.c_options.output_style = outstyle;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::cerr << output_path << ":" << d->pstate().line+1 << " DEBUG: " << result;
|
|
Packit Service |
7770af |
std::cerr << std::endl;
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(List_Ptr l)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// special case for unevaluated map
|
|
Packit Service |
7770af |
if (l->separator() == SASS_HASH) {
|
|
Packit Service |
7770af |
Map_Obj lm = SASS_MEMORY_NEW(Map,
|
|
Packit Service |
7770af |
l->pstate(),
|
|
Packit Service |
7770af |
l->length() / 2);
|
|
Packit Service |
7770af |
for (size_t i = 0, L = l->length(); i < L; i += 2)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Obj key = (*l)[i+0]->perform(this);
|
|
Packit Service |
7770af |
Expression_Obj val = (*l)[i+1]->perform(this);
|
|
Packit Service |
7770af |
// make sure the color key never displays its real name
|
|
Packit Service |
7770af |
key->is_delayed(true); // verified
|
|
Packit Service |
7770af |
*lm << std::make_pair(key, val);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (lm->has_duplicate_key()) {
|
|
Packit Service |
7770af |
throw Exception::DuplicateKeyError(*lm, *l);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
lm->is_interpolant(l->is_interpolant());
|
|
Packit Service |
7770af |
return lm->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// check if we should expand it
|
|
Packit Service |
7770af |
if (l->is_expanded()) return l;
|
|
Packit Service |
7770af |
// regular case for unevaluated lists
|
|
Packit Service |
7770af |
List_Obj ll = SASS_MEMORY_NEW(List,
|
|
Packit Service |
7770af |
l->pstate(),
|
|
Packit Service |
7770af |
l->length(),
|
|
Packit Service |
7770af |
l->separator(),
|
|
Packit Service |
7770af |
l->is_arglist());
|
|
Packit Service |
7770af |
for (size_t i = 0, L = l->length(); i < L; ++i) {
|
|
Packit Service |
7770af |
ll->append((*l)[i]->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
ll->is_interpolant(l->is_interpolant());
|
|
Packit Service |
7770af |
ll->from_selector(l->from_selector());
|
|
Packit Service |
7770af |
ll->is_expanded(true);
|
|
Packit Service |
7770af |
return ll.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Map_Ptr m)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (m->is_expanded()) return m;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// make sure we're not starting with duplicate keys.
|
|
Packit Service |
7770af |
// the duplicate key state will have been set in the parser phase.
|
|
Packit Service |
7770af |
if (m->has_duplicate_key()) {
|
|
Packit Service |
7770af |
throw Exception::DuplicateKeyError(*m, *m);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Map_Obj mm = SASS_MEMORY_NEW(Map,
|
|
Packit Service |
7770af |
m->pstate(),
|
|
Packit Service |
7770af |
m->length());
|
|
Packit Service |
7770af |
for (auto key : m->keys()) {
|
|
Packit Service |
7770af |
Expression_Ptr ex_key = key->perform(this);
|
|
Packit Service |
7770af |
Expression_Ptr ex_val = m->at(key)->perform(this);
|
|
Packit Service |
7770af |
*mm << std::make_pair(ex_key, ex_val);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// check the evaluated keys aren't duplicates.
|
|
Packit Service |
7770af |
if (mm->has_duplicate_key()) {
|
|
Packit Service |
7770af |
throw Exception::DuplicateKeyError(*mm, *m);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
mm->is_expanded(true);
|
|
Packit Service |
7770af |
return mm.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Binary_Expression_Ptr b_in)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Obj lhs = b_in->left();
|
|
Packit Service |
7770af |
Expression_Obj rhs = b_in->right();
|
|
Packit Service |
7770af |
enum Sass_OP op_type = b_in->optype();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (op_type == Sass_OP::AND) {
|
|
Packit Service |
7770af |
// LOCAL_FLAG(force, true);
|
|
Packit Service |
7770af |
lhs = lhs->perform(this);
|
|
Packit Service |
7770af |
if (!*lhs) return lhs.detach();
|
|
Packit Service |
7770af |
return rhs->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (op_type == Sass_OP::OR) {
|
|
Packit Service |
7770af |
// LOCAL_FLAG(force, true);
|
|
Packit Service |
7770af |
lhs = lhs->perform(this);
|
|
Packit Service |
7770af |
if (*lhs) return lhs.detach();
|
|
Packit Service |
7770af |
return rhs->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Evaluate variables as early o
|
|
Packit Service |
7770af |
while (Variable_Ptr l_v = Cast<Variable>(lhs)) {
|
|
Packit Service |
7770af |
lhs = operator()(l_v);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
while (Variable_Ptr r_v = Cast<Variable>(rhs)) {
|
|
Packit Service |
7770af |
rhs = operator()(r_v);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Binary_Expression_Obj b = b_in;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Evaluate sub-expressions early on
|
|
Packit Service |
7770af |
while (Binary_Expression_Ptr l_b = Cast<Binary_Expression>(lhs)) {
|
|
Packit Service |
7770af |
if (!force && l_b->is_delayed()) break;
|
|
Packit Service |
7770af |
lhs = operator()(l_b);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
while (Binary_Expression_Ptr r_b = Cast<Binary_Expression>(rhs)) {
|
|
Packit Service |
7770af |
if (!force && r_b->is_delayed()) break;
|
|
Packit Service |
7770af |
rhs = operator()(r_b);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// don't eval delayed expressions (the '/' when used as a separator)
|
|
Packit Service |
7770af |
if (!force && op_type == Sass_OP::DIV && b->is_delayed()) {
|
|
Packit Service |
7770af |
b->right(b->right()->perform(this));
|
|
Packit Service |
7770af |
b->left(b->left()->perform(this));
|
|
Packit Service |
7770af |
return b.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// specific types we know are final
|
|
Packit Service |
7770af |
// handle them early to avoid overhead
|
|
Packit Service |
7770af |
if (Number_Ptr l_n = Cast<Number>(lhs)) {
|
|
Packit Service |
7770af |
// lhs is number and rhs is number
|
|
Packit Service |
7770af |
if (Number_Ptr r_n = Cast<Number>(rhs)) {
|
|
Packit Service |
7770af |
try {
|
|
Packit Service |
7770af |
switch (op_type) {
|
|
Packit Service |
7770af |
case Sass_OP::EQ: return *l_n == *r_n ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::NEQ: return *l_n == *r_n ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::LT: return *l_n < *r_n ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::GTE: return *l_n < *r_n ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::LTE: return *l_n < *r_n || *l_n == *r_n ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::GT: return *l_n < *r_n || *l_n == *r_n ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
|
|
Packit Service |
7770af |
return op_numbers(op_type, *l_n, *r_n, ctx.c_options, b_in->pstate());
|
|
Packit Service |
7770af |
default: break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
catch (Exception::OperationError& err)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
throw Exception::SassValueError(b_in->pstate(), err);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// lhs is number and rhs is color
|
|
Packit Service |
7770af |
else if (Color_Ptr r_c = Cast<Color>(rhs)) {
|
|
Packit Service |
7770af |
try {
|
|
Packit Service |
7770af |
switch (op_type) {
|
|
Packit Service |
7770af |
case Sass_OP::EQ: return *l_n == *r_c ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::NEQ: return *l_n == *r_c ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::LT: return *l_n < *r_c ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::GTE: return *l_n < *r_c ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::LTE: return *l_n < *r_c || *l_n == *r_c ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::GT: return *l_n < *r_c || *l_n == *r_c ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
|
|
Packit Service |
7770af |
return op_number_color(op_type, *l_n, *r_c, ctx.c_options, b_in->pstate());
|
|
Packit Service |
7770af |
default: break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
catch (Exception::OperationError& err)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
throw Exception::SassValueError(b_in->pstate(), err);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (Color_Ptr l_c = Cast<Color>(lhs)) {
|
|
Packit Service |
7770af |
// lhs is color and rhs is color
|
|
Packit Service |
7770af |
if (Color_Ptr r_c = Cast<Color>(rhs)) {
|
|
Packit Service |
7770af |
try {
|
|
Packit Service |
7770af |
switch (op_type) {
|
|
Packit Service |
7770af |
case Sass_OP::EQ: return *l_c == *r_c ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::NEQ: return *l_c == *r_c ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::LT: return *l_c < *r_c ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::GTE: return *l_c < *r_c ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::LTE: return *l_c < *r_c || *l_c == *r_c ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::GT: return *l_c < *r_c || *l_c == *r_c ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
|
|
Packit Service |
7770af |
return op_colors(op_type, *l_c, *r_c, ctx.c_options, b_in->pstate());
|
|
Packit Service |
7770af |
default: break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
catch (Exception::OperationError& err)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
throw Exception::SassValueError(b_in->pstate(), err);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// lhs is color and rhs is number
|
|
Packit Service |
7770af |
else if (Number_Ptr r_n = Cast<Number>(rhs)) {
|
|
Packit Service |
7770af |
try {
|
|
Packit Service |
7770af |
switch (op_type) {
|
|
Packit Service |
7770af |
case Sass_OP::EQ: return *l_c == *r_n ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::NEQ: return *l_c == *r_n ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::LT: return *l_c < *r_n ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::GTE: return *l_c < *r_n ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::LTE: return *l_c < *r_n || *l_c == *r_n ? bool_true : bool_false;
|
|
Packit Service |
7770af |
case Sass_OP::GT: return *l_c < *r_n || *l_c == *r_n ? bool_false : bool_true;
|
|
Packit Service |
7770af |
case Sass_OP::ADD: case Sass_OP::SUB: case Sass_OP::MUL: case Sass_OP::DIV: case Sass_OP::MOD:
|
|
Packit Service |
7770af |
return op_color_number(op_type, *l_c, *r_n, ctx.c_options, b_in->pstate());
|
|
Packit Service |
7770af |
default: break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
catch (Exception::OperationError& err)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
throw Exception::SassValueError(b_in->pstate(), err);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
String_Schema_Obj ret_schema;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// only the last item will be used to eval the binary expression
|
|
Packit Service |
7770af |
if (String_Schema_Ptr s_l = Cast<String_Schema>(b->left())) {
|
|
Packit Service |
7770af |
if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) {
|
|
Packit Service |
7770af |
ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
|
|
Packit Service |
7770af |
Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
|
|
Packit Service |
7770af |
b->op(), s_l->last(), b->right());
|
|
Packit Service |
7770af |
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // unverified
|
|
Packit Service |
7770af |
for (size_t i = 0; i < s_l->length() - 1; ++i) {
|
|
Packit Service |
7770af |
ret_schema->append(s_l->at(i)->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
ret_schema->append(bin_ex->perform(this));
|
|
Packit Service |
7770af |
return ret_schema->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (String_Schema_Ptr s_r = Cast<String_Schema>(b->right())) {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) {
|
|
Packit Service |
7770af |
ret_schema = SASS_MEMORY_NEW(String_Schema, b->pstate());
|
|
Packit Service |
7770af |
Binary_Expression_Obj bin_ex = SASS_MEMORY_NEW(Binary_Expression, b->pstate(),
|
|
Packit Service |
7770af |
b->op(), b->left(), s_r->first());
|
|
Packit Service |
7770af |
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // verified
|
|
Packit Service |
7770af |
ret_schema->append(bin_ex->perform(this));
|
|
Packit Service |
7770af |
for (size_t i = 1; i < s_r->length(); ++i) {
|
|
Packit Service |
7770af |
ret_schema->append(s_r->at(i)->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return ret_schema->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// fully evaluate their values
|
|
Packit Service |
7770af |
if (op_type == Sass_OP::EQ ||
|
|
Packit Service |
7770af |
op_type == Sass_OP::NEQ ||
|
|
Packit Service |
7770af |
op_type == Sass_OP::GT ||
|
|
Packit Service |
7770af |
op_type == Sass_OP::GTE ||
|
|
Packit Service |
7770af |
op_type == Sass_OP::LT ||
|
|
Packit Service |
7770af |
op_type == Sass_OP::LTE)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
LOCAL_FLAG(force, true);
|
|
Packit Service |
7770af |
lhs->is_expanded(false);
|
|
Packit Service |
7770af |
lhs->set_delayed(false);
|
|
Packit Service |
7770af |
lhs = lhs->perform(this);
|
|
Packit Service |
7770af |
rhs->is_expanded(false);
|
|
Packit Service |
7770af |
rhs->set_delayed(false);
|
|
Packit Service |
7770af |
rhs = rhs->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
lhs = lhs->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// not a logical connective, so go ahead and eval the rhs
|
|
Packit Service |
7770af |
rhs = rhs->perform(this);
|
|
Packit Service |
7770af |
AST_Node_Obj lu = lhs;
|
|
Packit Service |
7770af |
AST_Node_Obj ru = rhs;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression::Concrete_Type l_type;
|
|
Packit Service |
7770af |
Expression::Concrete_Type r_type;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Is one of the operands an interpolant?
|
|
Packit Service |
7770af |
String_Schema_Obj s1 = Cast<String_Schema>(b->left());
|
|
Packit Service |
7770af |
String_Schema_Obj s2 = Cast<String_Schema>(b->right());
|
|
Packit Service |
7770af |
Binary_Expression_Obj b1 = Cast<Binary_Expression>(b->left());
|
|
Packit Service |
7770af |
Binary_Expression_Obj b2 = Cast<Binary_Expression>(b->right());
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool schema_op = false;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool force_delay = (s2 && s2->is_left_interpolant()) ||
|
|
Packit Service |
7770af |
(s1 && s1->is_right_interpolant()) ||
|
|
Packit Service |
7770af |
(b1 && b1->is_right_interpolant()) ||
|
|
Packit Service |
7770af |
(b2 && b2->is_left_interpolant());
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if ((s1 && s1->has_interpolants()) || (s2 && s2->has_interpolants()) || force_delay)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
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 ||
|
|
Packit Service |
7770af |
op_type == Sass_OP::EQ) {
|
|
Packit Service |
7770af |
// If possible upgrade LHS to a number (for number to string compare)
|
|
Packit Service |
7770af |
if (String_Constant_Ptr str = Cast<String_Constant>(lhs)) {
|
|
Packit Service |
7770af |
std::string value(str->value());
|
|
Packit Service |
7770af |
const char* start = value.c_str();
|
|
Packit Service |
7770af |
if (Prelexer::sequence < Prelexer::dimension, Prelexer::end_of_file >(start) != 0) {
|
|
Packit Service |
7770af |
lhs = Parser::lexed_dimension(b->pstate(), str->value());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// If possible upgrade RHS to a number (for string to number compare)
|
|
Packit Service |
7770af |
if (String_Constant_Ptr str = Cast<String_Constant>(rhs)) {
|
|
Packit Service |
7770af |
std::string value(str->value());
|
|
Packit Service |
7770af |
const char* start = value.c_str();
|
|
Packit Service |
7770af |
if (Prelexer::sequence < Prelexer::dimension, Prelexer::number >(start) != 0) {
|
|
Packit Service |
7770af |
rhs = Parser::lexed_dimension(b->pstate(), str->value());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
To_Value to_value(ctx);
|
|
Packit Service |
7770af |
Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
|
|
Packit Service |
7770af |
Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (force_delay) {
|
|
Packit Service |
7770af |
std::string str("");
|
|
Packit Service |
7770af |
str += v_l->to_string(ctx.c_options);
|
|
Packit Service |
7770af |
if (b->op().ws_before) str += " ";
|
|
Packit Service |
7770af |
str += b->separator();
|
|
Packit Service |
7770af |
if (b->op().ws_after) str += " ";
|
|
Packit Service |
7770af |
str += v_r->to_string(ctx.c_options);
|
|
Packit Service |
7770af |
String_Constant_Ptr val = SASS_MEMORY_NEW(String_Constant, b->pstate(), str);
|
|
Packit Service |
7770af |
val->is_interpolant(b->left()->has_interpolant());
|
|
Packit Service |
7770af |
return val;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// see if it's a relational expression
|
|
Packit Service |
7770af |
try {
|
|
Packit Service |
7770af |
switch(op_type) {
|
|
Packit Service |
7770af |
case Sass_OP::EQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), eq(lhs, rhs));
|
|
Packit Service |
7770af |
case Sass_OP::NEQ: return SASS_MEMORY_NEW(Boolean, b->pstate(), !eq(lhs, rhs));
|
|
Packit Service |
7770af |
case Sass_OP::GT: return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gt") && !eq(lhs, rhs));
|
|
Packit Service |
7770af |
case Sass_OP::GTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), !lt(lhs, rhs, "gte"));
|
|
Packit Service |
7770af |
case Sass_OP::LT: return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lt"));
|
|
Packit Service |
7770af |
case Sass_OP::LTE: return SASS_MEMORY_NEW(Boolean, b->pstate(), lt(lhs, rhs, "lte") || eq(lhs, rhs));
|
|
Packit Service |
7770af |
default: break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
catch (Exception::OperationError& err)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// throw Exception::Base(b->pstate(), err.what());
|
|
Packit Service |
7770af |
throw Exception::SassValueError(b->pstate(), err);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
l_type = lhs->concrete_type();
|
|
Packit Service |
7770af |
r_type = rhs->concrete_type();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// ToDo: throw error in op functions
|
|
Packit Service |
7770af |
// ToDo: then catch and re-throw them
|
|
Packit Service |
7770af |
Expression_Obj rv;
|
|
Packit Service |
7770af |
try {
|
|
Packit Service |
7770af |
ParserState pstate(b->pstate());
|
|
Packit Service |
7770af |
if (l_type == Expression::NUMBER && r_type == Expression::NUMBER) {
|
|
Packit Service |
7770af |
Number_Ptr l_n = Cast<Number>(lhs);
|
|
Packit Service |
7770af |
Number_Ptr r_n = Cast<Number>(rhs);
|
|
Packit Service |
7770af |
rv = op_numbers(op_type, *l_n, *r_n, ctx.c_options, pstate);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (l_type == Expression::NUMBER && r_type == Expression::COLOR) {
|
|
Packit Service |
7770af |
Number_Ptr l_n = Cast<Number>(lhs);
|
|
Packit Service |
7770af |
Color_Ptr r_c = Cast<Color>(rhs);
|
|
Packit Service |
7770af |
rv = op_number_color(op_type, *l_n, *r_c, ctx.c_options, pstate);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (l_type == Expression::COLOR && r_type == Expression::NUMBER) {
|
|
Packit Service |
7770af |
Color_Ptr l_c = Cast<Color>(lhs);
|
|
Packit Service |
7770af |
Number_Ptr r_n = Cast<Number>(rhs);
|
|
Packit Service |
7770af |
rv = op_color_number(op_type, *l_c, *r_n, ctx.c_options, pstate);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (l_type == Expression::COLOR && r_type == Expression::COLOR) {
|
|
Packit Service |
7770af |
Color_Ptr l_c = Cast<Color>(lhs);
|
|
Packit Service |
7770af |
Color_Ptr r_c = Cast<Color>(rhs);
|
|
Packit Service |
7770af |
rv = op_colors(op_type, *l_c, *r_c, ctx.c_options, pstate);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
To_Value to_value(ctx);
|
|
Packit Service |
7770af |
// this will leak if perform does not return a value!
|
|
Packit Service |
7770af |
Value_Obj v_l = Cast<Value>(lhs->perform(&to_value));
|
|
Packit Service |
7770af |
Value_Obj v_r = Cast<Value>(rhs->perform(&to_value));
|
|
Packit Service |
7770af |
bool interpolant = b->is_right_interpolant() ||
|
|
Packit Service |
7770af |
b->is_left_interpolant() ||
|
|
Packit Service |
7770af |
b->is_interpolant();
|
|
Packit Service |
7770af |
if (op_type == Sass_OP::SUB) interpolant = false;
|
|
Packit Service |
7770af |
// if (op_type == Sass_OP::DIV) interpolant = true;
|
|
Packit Service |
7770af |
// check for type violations
|
|
Packit Service |
7770af |
if (l_type == Expression::MAP) {
|
|
Packit Service |
7770af |
throw Exception::InvalidValue(*v_l);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (r_type == Expression::MAP) {
|
|
Packit Service |
7770af |
throw Exception::InvalidValue(*v_r);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
Value_Ptr ex = op_strings(b->op(), *v_l, *v_r, ctx.c_options, pstate, !interpolant); // pass true to compress
|
|
Packit Service |
7770af |
if (String_Constant_Ptr str = Cast<String_Constant>(ex))
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (str->concrete_type() == Expression::STRING)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
String_Constant_Ptr lstr = Cast<String_Constant>(lhs);
|
|
Packit Service |
7770af |
String_Constant_Ptr rstr = Cast<String_Constant>(rhs);
|
|
Packit Service |
7770af |
if (op_type != Sass_OP::SUB) {
|
|
Packit Service |
7770af |
if (String_Constant_Ptr org = lstr ? lstr : rstr)
|
|
Packit Service |
7770af |
{ str->quote_mark(org->quote_mark()); }
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
ex->is_interpolant(b->is_interpolant());
|
|
Packit Service |
7770af |
rv = ex;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
catch (Exception::OperationError& err)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// throw Exception::Base(b->pstate(), err.what());
|
|
Packit Service |
7770af |
throw Exception::SassValueError(b->pstate(), err);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (rv) {
|
|
Packit Service |
7770af |
if (schema_op) {
|
|
Packit Service |
7770af |
// XXX: this is never hit via spec tests
|
|
Packit Service |
7770af |
(*s2)[0] = rv;
|
|
Packit Service |
7770af |
rv = s2->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
return rv.detach();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Unary_Expression_Ptr u)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Obj operand = u->operand()->perform(this);
|
|
Packit Service |
7770af |
if (u->optype() == Unary_Expression::NOT) {
|
|
Packit Service |
7770af |
Boolean_Ptr result = SASS_MEMORY_NEW(Boolean, u->pstate(), (bool)*operand);
|
|
Packit Service |
7770af |
result->value(!result->value());
|
|
Packit Service |
7770af |
return result;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (Number_Obj nr = Cast<Number>(operand)) {
|
|
Packit Service |
7770af |
// negate value for minus unary expression
|
|
Packit Service |
7770af |
if (u->optype() == Unary_Expression::MINUS) {
|
|
Packit Service |
7770af |
Number_Obj cpy = SASS_MEMORY_COPY(nr);
|
|
Packit Service |
7770af |
cpy->value( - cpy->value() ); // negate value
|
|
Packit Service |
7770af |
return cpy.detach(); // return the copy
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (u->optype() == Unary_Expression::SLASH) {
|
|
Packit Service |
7770af |
std::string str = '/' + nr->to_string(ctx.c_options);
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(String_Constant, u->pstate(), str);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// nothing for positive
|
|
Packit Service |
7770af |
return nr.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
// Special cases: +/- variables which evaluate to null ouput just +/-,
|
|
Packit Service |
7770af |
// but +/- null itself outputs the string
|
|
Packit Service |
7770af |
if (operand->concrete_type() == Expression::NULL_VAL && Cast<Variable>(u->operand())) {
|
|
Packit Service |
7770af |
u->operand(SASS_MEMORY_NEW(String_Quoted, u->pstate(), ""));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// Never apply unary opertions on colors @see #2140
|
|
Packit Service |
7770af |
else if (Color_Ptr color = Cast<Color>(operand)) {
|
|
Packit Service |
7770af |
// Use the color name if this was eval with one
|
|
Packit Service |
7770af |
if (color->disp().length() > 0) {
|
|
Packit Service |
7770af |
operand = SASS_MEMORY_NEW(String_Constant, operand->pstate(), color->disp());
|
|
Packit Service |
7770af |
u->operand(operand);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
u->operand(operand);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(String_Quoted,
|
|
Packit Service |
7770af |
u->pstate(),
|
|
Packit Service |
7770af |
u->inspect());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// unreachable
|
|
Packit Service |
7770af |
return u;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Function_Call_Ptr c)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (backtrace()->parent != NULL && backtrace()->depth() > Constants::MaxCallStack) {
|
|
Packit Service |
7770af |
// XXX: this is never hit via spec tests
|
|
Packit Service |
7770af |
std::ostringstream stm;
|
|
Packit Service |
7770af |
stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
|
|
Packit Service |
7770af |
error(stm.str(), c->pstate(), backtrace());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
std::string name(Util::normalize_underscores(c->name()));
|
|
Packit Service |
7770af |
std::string full_name(name + "[f]");
|
|
Packit Service |
7770af |
// we make a clone here, need to implement that further
|
|
Packit Service |
7770af |
Arguments_Obj args = c->arguments();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Env* env = environment();
|
|
Packit Service |
7770af |
if (!env->has(full_name) || (!c->via_call() && Prelexer::re_special_fun(name.c_str()))) {
|
|
Packit Service |
7770af |
if (!env->has("*[f]")) {
|
|
Packit Service |
7770af |
for (Argument_Obj arg : args->elements()) {
|
|
Packit Service |
7770af |
if (List_Obj ls = Cast<List>(arg->value())) {
|
|
Packit Service |
7770af |
if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
args = Cast<Arguments>(args->perform(this));
|
|
Packit Service |
7770af |
Function_Call_Obj lit = SASS_MEMORY_NEW(Function_Call,
|
|
Packit Service |
7770af |
c->pstate(),
|
|
Packit Service |
7770af |
c->name(),
|
|
Packit Service |
7770af |
args);
|
|
Packit Service |
7770af |
if (args->has_named_arguments()) {
|
|
Packit Service |
7770af |
error("Function " + c->name() + " doesn't support keyword arguments", c->pstate());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
String_Quoted_Ptr str = SASS_MEMORY_NEW(String_Quoted,
|
|
Packit Service |
7770af |
c->pstate(),
|
|
Packit Service |
7770af |
lit->to_string(ctx.c_options));
|
|
Packit Service |
7770af |
str->is_interpolant(c->is_interpolant());
|
|
Packit Service |
7770af |
return str;
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
// call generic function
|
|
Packit Service |
7770af |
full_name = "*[f]";
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// further delay for calls
|
|
Packit Service |
7770af |
if (full_name != "call[f]") {
|
|
Packit Service |
7770af |
args->set_delayed(false); // verified
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (full_name != "if[f]") {
|
|
Packit Service |
7770af |
args = Cast<Arguments>(args->perform(this));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
Definition_Ptr def = Cast<Definition>((*env)[full_name]);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (def->is_overload_stub()) {
|
|
Packit Service |
7770af |
std::stringstream ss;
|
|
Packit Service |
7770af |
size_t L = args->length();
|
|
Packit Service |
7770af |
// account for rest arguments
|
|
Packit Service |
7770af |
if (args->has_rest_argument() && args->length() > 0) {
|
|
Packit Service |
7770af |
// get the rest arguments list
|
|
Packit Service |
7770af |
List_Ptr rest = Cast<List>(args->last()->value());
|
|
Packit Service |
7770af |
// arguments before rest argument plus rest
|
|
Packit Service |
7770af |
if (rest) L += rest->length() - 1;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
ss << full_name << L;
|
|
Packit Service |
7770af |
full_name = ss.str();
|
|
Packit Service |
7770af |
std::string resolved_name(full_name);
|
|
Packit Service |
7770af |
if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate());
|
|
Packit Service |
7770af |
def = Cast<Definition>((*env)[resolved_name]);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Obj result = c;
|
|
Packit Service |
7770af |
Block_Obj body = def->block();
|
|
Packit Service |
7770af |
Native_Function func = def->native_function();
|
|
Packit Service |
7770af |
Sass_Function_Entry c_function = def->c_function();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Parameters_Obj params = def->parameters();
|
|
Packit Service |
7770af |
Env fn_env(def->environment());
|
|
Packit Service |
7770af |
exp.env_stack.push_back(&fn_env);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (func || body) {
|
|
Packit Service |
7770af |
bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this);
|
|
Packit Service |
7770af |
Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`");
|
|
Packit Service |
7770af |
exp.backtrace_stack.push_back(&here;;
|
|
Packit Service |
7770af |
ctx.callee_stack.push_back({
|
|
Packit Service |
7770af |
c->name().c_str(),
|
|
Packit Service |
7770af |
c->pstate().path,
|
|
Packit Service |
7770af |
c->pstate().line + 1,
|
|
Packit Service |
7770af |
c->pstate().column + 1,
|
|
Packit Service |
7770af |
SASS_CALLEE_FUNCTION,
|
|
Packit Service |
7770af |
{ env }
|
|
Packit Service |
7770af |
});
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// eval the body if user-defined or special, invoke underlying CPP function if native
|
|
Packit Service |
7770af |
if (body /* && !Prelexer::re_special_fun(name.c_str()) */) {
|
|
Packit Service |
7770af |
result = body->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (func) {
|
|
Packit Service |
7770af |
result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace(), exp.selector_stack);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (!result) {
|
|
Packit Service |
7770af |
error(std::string("Function ") + c->name() + " did not return a value", c->pstate());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
exp.backtrace_stack.pop_back();
|
|
Packit Service |
7770af |
ctx.callee_stack.pop_back();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// else if it's a user-defined c function
|
|
Packit Service |
7770af |
// convert call into C-API compatible form
|
|
Packit Service |
7770af |
else if (c_function) {
|
|
Packit Service |
7770af |
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
|
Packit Service |
7770af |
if (full_name == "*[f]") {
|
|
Packit Service |
7770af |
String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, c->pstate(), c->name());
|
|
Packit Service |
7770af |
Arguments_Obj new_args = SASS_MEMORY_NEW(Arguments, c->pstate());
|
|
Packit Service |
7770af |
new_args->append(SASS_MEMORY_NEW(Argument, c->pstate(), str));
|
|
Packit Service |
7770af |
new_args->concat(args);
|
|
Packit Service |
7770af |
args = new_args;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// populates env with default values for params
|
|
Packit Service |
7770af |
std::string ff(c->name());
|
|
Packit Service |
7770af |
bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`");
|
|
Packit Service |
7770af |
exp.backtrace_stack.push_back(&here;;
|
|
Packit Service |
7770af |
ctx.callee_stack.push_back({
|
|
Packit Service |
7770af |
c->name().c_str(),
|
|
Packit Service |
7770af |
c->pstate().path,
|
|
Packit Service |
7770af |
c->pstate().line + 1,
|
|
Packit Service |
7770af |
c->pstate().column + 1,
|
|
Packit Service |
7770af |
SASS_CALLEE_C_FUNCTION,
|
|
Packit Service |
7770af |
{ env }
|
|
Packit Service |
7770af |
});
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
To_C to_c;
|
|
Packit Service |
7770af |
union Sass_Value* c_args = sass_make_list(params->length(), SASS_COMMA);
|
|
Packit Service |
7770af |
for(size_t i = 0; i < params->length(); i++) {
|
|
Packit Service |
7770af |
Parameter_Obj param = params->at(i);
|
|
Packit Service |
7770af |
std::string key = param->name();
|
|
Packit Service |
7770af |
AST_Node_Obj node = fn_env.get_local(key);
|
|
Packit Service |
7770af |
Expression_Obj arg = Cast<Expression>(node);
|
|
Packit Service |
7770af |
sass_list_set_value(c_args, i, arg->perform(&to_c));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
union Sass_Value* c_val = c_func(c_args, c_function, ctx.c_compiler);
|
|
Packit Service |
7770af |
if (sass_value_get_tag(c_val) == SASS_ERROR) {
|
|
Packit Service |
7770af |
error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), backtrace());
|
|
Packit Service |
7770af |
} else if (sass_value_get_tag(c_val) == SASS_WARNING) {
|
|
Packit Service |
7770af |
error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->pstate(), backtrace());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
result = cval_to_astnode(c_val, backtrace(), c->pstate());
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
exp.backtrace_stack.pop_back();
|
|
Packit Service |
7770af |
ctx.callee_stack.pop_back();
|
|
Packit Service |
7770af |
sass_delete_value(c_args);
|
|
Packit Service |
7770af |
if (c_val != c_args)
|
|
Packit Service |
7770af |
sass_delete_value(c_val);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// link back to function definition
|
|
Packit Service |
7770af |
// only do this for custom functions
|
|
Packit Service |
7770af |
if (result->pstate().file == std::string::npos)
|
|
Packit Service |
7770af |
result->pstate(c->pstate());
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
result = result->perform(this);
|
|
Packit Service |
7770af |
result->is_interpolant(c->is_interpolant());
|
|
Packit Service |
7770af |
exp.env_stack.pop_back();
|
|
Packit Service |
7770af |
return result.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Function_Call_Schema_Ptr s)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Ptr evaluated_name = s->name()->perform(this);
|
|
Packit Service |
7770af |
Expression_Ptr evaluated_args = s->arguments()->perform(this);
|
|
Packit Service |
7770af |
String_Schema_Obj ss = SASS_MEMORY_NEW(String_Schema, s->pstate(), 2);
|
|
Packit Service |
7770af |
ss->append(evaluated_name);
|
|
Packit Service |
7770af |
ss->append(evaluated_args);
|
|
Packit Service |
7770af |
return ss->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Variable_Ptr v)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Obj value = 0;
|
|
Packit Service |
7770af |
Env* env = environment();
|
|
Packit Service |
7770af |
const std::string& name(v->name());
|
|
Packit Service |
7770af |
EnvResult rv(env->find(name));
|
|
Packit Service |
7770af |
if (rv.found) value = static_cast<Expression*>(rv.it->second.ptr());
|
|
Packit Service |
7770af |
else error("Undefined variable: \"" + v->name() + "\".", v->pstate());
|
|
Packit Service |
7770af |
if (Argument_Ptr arg = Cast<Argument>(value)) value = arg->value();
|
|
Packit Service |
7770af |
if (Number_Ptr nr = Cast<Number>(value)) nr->zero(true); // force flag
|
|
Packit Service |
7770af |
value->is_interpolant(v->is_interpolant());
|
|
Packit Service |
7770af |
if (force) value->is_expanded(false);
|
|
Packit Service |
7770af |
value->set_delayed(false); // verified
|
|
Packit Service |
7770af |
value = value->perform(this);
|
|
Packit Service |
7770af |
if(!force) rv.it->second = value;
|
|
Packit Service |
7770af |
return value.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Color_Ptr c)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return c;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Number_Ptr n)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return n;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Boolean_Ptr b)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return b;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void Eval::interpolation(Context& ctx, std::string& res, Expression_Obj ex, bool into_quotes, bool was_itpl) {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool needs_closing_brace = false;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (Arguments_Ptr args = Cast<Arguments>(ex)) {
|
|
Packit Service |
7770af |
List_Ptr ll = SASS_MEMORY_NEW(List, args->pstate(), 0, SASS_COMMA);
|
|
Packit Service |
7770af |
for(auto arg : args->elements()) {
|
|
Packit Service |
7770af |
ll->append(arg->value());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
ll->is_interpolant(args->is_interpolant());
|
|
Packit Service |
7770af |
needs_closing_brace = true;
|
|
Packit Service |
7770af |
res += "(";
|
|
Packit Service |
7770af |
ex = ll;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (Number_Ptr nr = Cast<Number>(ex)) {
|
|
Packit Service |
7770af |
if (!nr->is_valid_css_unit()) {
|
|
Packit Service |
7770af |
throw Exception::InvalidValue(*nr);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (Argument_Ptr arg = Cast<Argument>(ex)) {
|
|
Packit Service |
7770af |
ex = arg->value();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (String_Quoted_Ptr sq = Cast<String_Quoted>(ex)) {
|
|
Packit Service |
7770af |
if (was_itpl) {
|
|
Packit Service |
7770af |
bool was_interpolant = ex->is_interpolant();
|
|
Packit Service |
7770af |
ex = SASS_MEMORY_NEW(String_Constant, sq->pstate(), sq->value());
|
|
Packit Service |
7770af |
ex->is_interpolant(was_interpolant);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (Cast<Null>(ex)) { return; }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// parent selector needs another go
|
|
Packit Service |
7770af |
if (Cast<Parent_Selector>(ex)) {
|
|
Packit Service |
7770af |
// XXX: this is never hit via spec tests
|
|
Packit Service |
7770af |
ex = ex->perform(this);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (List_Ptr l = Cast<List>(ex)) {
|
|
Packit Service |
7770af |
List_Obj ll = SASS_MEMORY_NEW(List, l->pstate(), 0, l->separator());
|
|
Packit Service |
7770af |
// this fixes an issue with bourbon sample, not really sure why
|
|
Packit Service |
7770af |
// if (l->size() && Cast<Null>((*l)[0])) { res += ""; }
|
|
Packit Service |
7770af |
for(Expression_Obj item : *l) {
|
|
Packit Service |
7770af |
item->is_interpolant(l->is_interpolant());
|
|
Packit Service |
7770af |
std::string rl(""); interpolation(ctx, rl, item, into_quotes, l->is_interpolant());
|
|
Packit Service |
7770af |
bool is_null = Cast<Null>(item) != 0; // rl != ""
|
|
Packit Service |
7770af |
if (!is_null) ll->append(SASS_MEMORY_NEW(String_Quoted, item->pstate(), rl));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// Check indicates that we probably should not get a list
|
|
Packit Service |
7770af |
// here. Normally single list items are already unwrapped.
|
|
Packit Service |
7770af |
if (l->size() > 1) {
|
|
Packit Service |
7770af |
// string_to_output would fail "#{'_\a' '_\a'}";
|
|
Packit Service |
7770af |
std::string str(ll->to_string(ctx.c_options));
|
|
Packit Service |
7770af |
str = read_hex_escapes(str); // read escapes
|
|
Packit Service |
7770af |
newline_to_space(str); // replace directly
|
|
Packit Service |
7770af |
res += str; // append to result string
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
res += (ll->to_string(ctx.c_options));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
ll->is_interpolant(l->is_interpolant());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Value
|
|
Packit Service |
7770af |
// Function_Call
|
|
Packit Service |
7770af |
// Selector_List
|
|
Packit Service |
7770af |
// String_Quoted
|
|
Packit Service |
7770af |
// String_Constant
|
|
Packit Service |
7770af |
// Parent_Selector
|
|
Packit Service |
7770af |
// Binary_Expression
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
// ex = ex->perform(this);
|
|
Packit Service |
7770af |
if (into_quotes && ex->is_interpolant()) {
|
|
Packit Service |
7770af |
res += evacuate_escapes(ex ? ex->to_string(ctx.c_options) : "");
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
std::string str(ex ? ex->to_string(ctx.c_options) : "");
|
|
Packit Service |
7770af |
if (into_quotes) str = read_hex_escapes(str);
|
|
Packit Service |
7770af |
res += str; // append to result string
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (needs_closing_brace) res += ")";
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(String_Schema_Ptr s)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
size_t L = s->length();
|
|
Packit Service |
7770af |
bool into_quotes = false;
|
|
Packit Service |
7770af |
if (L > 1) {
|
|
Packit Service |
7770af |
if (!Cast<String_Quoted>((*s)[0]) && !Cast<String_Quoted>((*s)[L - 1])) {
|
|
Packit Service |
7770af |
if (String_Constant_Ptr l = Cast<String_Constant>((*s)[0])) {
|
|
Packit Service |
7770af |
if (String_Constant_Ptr r = Cast<String_Constant>((*s)[L - 1])) {
|
|
Packit Service |
7770af |
if (r->value().size() > 0) {
|
|
Packit Service |
7770af |
if (l->value()[0] == '"' && r->value()[r->value().size() - 1] == '"') into_quotes = true;
|
|
Packit Service |
7770af |
if (l->value()[0] == '\'' && r->value()[r->value().size() - 1] == '\'') into_quotes = true;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
bool was_quoted = false;
|
|
Packit Service |
7770af |
bool was_interpolant = false;
|
|
Packit Service |
7770af |
std::string res("");
|
|
Packit Service |
7770af |
for (size_t i = 0; i < L; ++i) {
|
|
Packit Service |
7770af |
bool is_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
|
|
Packit Service |
7770af |
if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
|
Packit Service |
7770af |
else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
|
Packit Service |
7770af |
Expression_Obj ex = (*s)[i]->perform(this);
|
|
Packit Service |
7770af |
interpolation(ctx, res, ex, into_quotes, ex->is_interpolant());
|
|
Packit Service |
7770af |
was_quoted = Cast<String_Quoted>((*s)[i]) != NULL;
|
|
Packit Service |
7770af |
was_interpolant = (*s)[i]->is_interpolant();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (!s->is_interpolant()) {
|
|
Packit Service |
7770af |
if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(Null, s->pstate());
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(String_Constant, s->pstate(), res);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// string schema seems to have a special unquoting behavior (also handles "nested" quotes)
|
|
Packit Service |
7770af |
String_Quoted_Obj str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), res, 0, false, false, false);
|
|
Packit Service |
7770af |
// if (s->is_interpolant()) str->quote_mark(0);
|
|
Packit Service |
7770af |
// String_Constant_Ptr str = SASS_MEMORY_NEW(String_Constant, s->pstate(), res);
|
|
Packit Service |
7770af |
if (str->quote_mark()) str->quote_mark('*');
|
|
Packit Service |
7770af |
else if (!is_in_comment) str->value(string_to_output(str->value()));
|
|
Packit Service |
7770af |
str->is_interpolant(s->is_interpolant());
|
|
Packit Service |
7770af |
return str.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(String_Constant_Ptr s)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (!s->is_delayed() && name_to_color(s->value())) {
|
|
Packit Service |
7770af |
Color_Ptr c = SASS_MEMORY_COPY(name_to_color(s->value())); // copy
|
|
Packit Service |
7770af |
c->pstate(s->pstate());
|
|
Packit Service |
7770af |
c->disp(s->value());
|
|
Packit Service |
7770af |
c->is_delayed(true);
|
|
Packit Service |
7770af |
return c;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return s;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(String_Quoted_Ptr s)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
String_Quoted_Ptr str = SASS_MEMORY_NEW(String_Quoted, s->pstate(), "");
|
|
Packit Service |
7770af |
str->value(s->value());
|
|
Packit Service |
7770af |
str->quote_mark(s->quote_mark());
|
|
Packit Service |
7770af |
str->is_interpolant(s->is_interpolant());
|
|
Packit Service |
7770af |
return str;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Supports_Operator_Ptr c)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Ptr left = c->left()->perform(this);
|
|
Packit Service |
7770af |
Expression_Ptr right = c->right()->perform(this);
|
|
Packit Service |
7770af |
Supports_Operator_Ptr cc = SASS_MEMORY_NEW(Supports_Operator,
|
|
Packit Service |
7770af |
c->pstate(),
|
|
Packit Service |
7770af |
Cast<Supports_Condition>(left),
|
|
Packit Service |
7770af |
Cast<Supports_Condition>(right),
|
|
Packit Service |
7770af |
c->operand());
|
|
Packit Service |
7770af |
return cc;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Supports_Negation_Ptr c)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Ptr condition = c->condition()->perform(this);
|
|
Packit Service |
7770af |
Supports_Negation_Ptr cc = SASS_MEMORY_NEW(Supports_Negation,
|
|
Packit Service |
7770af |
c->pstate(),
|
|
Packit Service |
7770af |
Cast<Supports_Condition>(condition));
|
|
Packit Service |
7770af |
return cc;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Supports_Declaration_Ptr c)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Ptr feature = c->feature()->perform(this);
|
|
Packit Service |
7770af |
Expression_Ptr value = c->value()->perform(this);
|
|
Packit Service |
7770af |
Supports_Declaration_Ptr cc = SASS_MEMORY_NEW(Supports_Declaration,
|
|
Packit Service |
7770af |
c->pstate(),
|
|
Packit Service |
7770af |
feature,
|
|
Packit Service |
7770af |
value);
|
|
Packit Service |
7770af |
return cc;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Supports_Interpolation_Ptr c)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Ptr value = c->value()->perform(this);
|
|
Packit Service |
7770af |
Supports_Interpolation_Ptr cc = SASS_MEMORY_NEW(Supports_Interpolation,
|
|
Packit Service |
7770af |
c->pstate(),
|
|
Packit Service |
7770af |
value);
|
|
Packit Service |
7770af |
return cc;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(At_Root_Query_Ptr e)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Obj feature = e->feature();
|
|
Packit Service |
7770af |
feature = (feature ? feature->perform(this) : 0);
|
|
Packit Service |
7770af |
Expression_Obj value = e->value();
|
|
Packit Service |
7770af |
value = (value ? value->perform(this) : 0);
|
|
Packit Service |
7770af |
Expression_Ptr ee = SASS_MEMORY_NEW(At_Root_Query,
|
|
Packit Service |
7770af |
e->pstate(),
|
|
Packit Service |
7770af |
Cast<String>(feature),
|
|
Packit Service |
7770af |
value);
|
|
Packit Service |
7770af |
return ee;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Media_Query_Ptr Eval::operator()(Media_Query_Ptr q)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
String_Obj t = q->media_type();
|
|
Packit Service |
7770af |
t = static_cast<String_Ptr>(t.isNull() ? 0 : t->perform(this));
|
|
Packit Service |
7770af |
Media_Query_Obj qq = SASS_MEMORY_NEW(Media_Query,
|
|
Packit Service |
7770af |
q->pstate(),
|
|
Packit Service |
7770af |
t,
|
|
Packit Service |
7770af |
q->length(),
|
|
Packit Service |
7770af |
q->is_negated(),
|
|
Packit Service |
7770af |
q->is_restricted());
|
|
Packit Service |
7770af |
for (size_t i = 0, L = q->length(); i < L; ++i) {
|
|
Packit Service |
7770af |
qq->append(static_cast<Media_Query_Expression_Ptr>((*q)[i]->perform(this)));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return qq.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Media_Query_Expression_Ptr e)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Obj feature = e->feature();
|
|
Packit Service |
7770af |
feature = (feature ? feature->perform(this) : 0);
|
|
Packit Service |
7770af |
if (feature && Cast<String_Quoted>(feature)) {
|
|
Packit Service |
7770af |
feature = SASS_MEMORY_NEW(String_Quoted,
|
|
Packit Service |
7770af |
feature->pstate(),
|
|
Packit Service |
7770af |
Cast<String_Quoted>(feature)->value());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
Expression_Obj value = e->value();
|
|
Packit Service |
7770af |
value = (value ? value->perform(this) : 0);
|
|
Packit Service |
7770af |
if (value && Cast<String_Quoted>(value)) {
|
|
Packit Service |
7770af |
// XXX: this is never hit via spec tests
|
|
Packit Service |
7770af |
value = SASS_MEMORY_NEW(String_Quoted,
|
|
Packit Service |
7770af |
value->pstate(),
|
|
Packit Service |
7770af |
Cast<String_Quoted>(value)->value());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(Media_Query_Expression,
|
|
Packit Service |
7770af |
e->pstate(),
|
|
Packit Service |
7770af |
feature,
|
|
Packit Service |
7770af |
value,
|
|
Packit Service |
7770af |
e->is_interpolated());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Null_Ptr n)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return n;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Argument_Ptr a)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression_Obj val = a->value()->perform(this);
|
|
Packit Service |
7770af |
bool is_rest_argument = a->is_rest_argument();
|
|
Packit Service |
7770af |
bool is_keyword_argument = a->is_keyword_argument();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (a->is_rest_argument()) {
|
|
Packit Service |
7770af |
if (val->concrete_type() == Expression::MAP) {
|
|
Packit Service |
7770af |
is_rest_argument = false;
|
|
Packit Service |
7770af |
is_keyword_argument = true;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if(val->concrete_type() != Expression::LIST) {
|
|
Packit Service |
7770af |
List_Obj wrapper = SASS_MEMORY_NEW(List,
|
|
Packit Service |
7770af |
val->pstate(),
|
|
Packit Service |
7770af |
0,
|
|
Packit Service |
7770af |
SASS_COMMA,
|
|
Packit Service |
7770af |
true);
|
|
Packit Service |
7770af |
wrapper->append(val);
|
|
Packit Service |
7770af |
val = wrapper;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(Argument,
|
|
Packit Service |
7770af |
a->pstate(),
|
|
Packit Service |
7770af |
val,
|
|
Packit Service |
7770af |
a->name(),
|
|
Packit Service |
7770af |
is_rest_argument,
|
|
Packit Service |
7770af |
is_keyword_argument);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Arguments_Ptr a)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Arguments_Obj aa = SASS_MEMORY_NEW(Arguments, a->pstate());
|
|
Packit Service |
7770af |
if (a->length() == 0) return aa.detach();
|
|
Packit Service |
7770af |
for (size_t i = 0, L = a->length(); i < L; ++i) {
|
|
Packit Service |
7770af |
Expression_Obj rv = (*a)[i]->perform(this);
|
|
Packit Service |
7770af |
Argument_Ptr arg = Cast<Argument>(rv);
|
|
Packit Service |
7770af |
if (!(arg->is_rest_argument() || arg->is_keyword_argument())) {
|
|
Packit Service |
7770af |
aa->append(arg);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (a->has_rest_argument()) {
|
|
Packit Service |
7770af |
Expression_Obj rest = a->get_rest_argument()->perform(this);
|
|
Packit Service |
7770af |
Expression_Obj splat = Cast<Argument>(rest)->value()->perform(this);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Sass_Separator separator = SASS_COMMA;
|
|
Packit Service |
7770af |
List_Ptr ls = Cast<List>(splat);
|
|
Packit Service |
7770af |
Map_Ptr ms = Cast<Map>(splat);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
List_Obj arglist = SASS_MEMORY_NEW(List,
|
|
Packit Service |
7770af |
splat->pstate(),
|
|
Packit Service |
7770af |
0,
|
|
Packit Service |
7770af |
ls ? ls->separator() : separator,
|
|
Packit Service |
7770af |
true);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (ls && ls->is_arglist()) {
|
|
Packit Service |
7770af |
arglist->concat(ls);
|
|
Packit Service |
7770af |
} else if (ms) {
|
|
Packit Service |
7770af |
aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), ms, "", false, true));
|
|
Packit Service |
7770af |
} else if (ls) {
|
|
Packit Service |
7770af |
arglist->concat(ls);
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
arglist->append(splat);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (arglist->length()) {
|
|
Packit Service |
7770af |
aa->append(SASS_MEMORY_NEW(Argument, splat->pstate(), arglist, "", true));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (a->has_keyword_argument()) {
|
|
Packit Service |
7770af |
Expression_Obj rv = a->get_keyword_argument()->perform(this);
|
|
Packit Service |
7770af |
Argument_Ptr rvarg = Cast<Argument>(rv);
|
|
Packit Service |
7770af |
Expression_Obj kwarg = rvarg->value()->perform(this);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
aa->append(SASS_MEMORY_NEW(Argument, kwarg->pstate(), kwarg, "", false, true));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return aa.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Comment_Ptr c)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
inline Expression_Ptr Eval::fallback_impl(AST_Node_Ptr n)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return static_cast<Expression_Ptr>(n);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// All the binary helpers.
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool Eval::eq(Expression_Obj lhs, Expression_Obj rhs)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// use compare operator from ast node
|
|
Packit Service |
7770af |
return lhs && rhs && *lhs == *rhs;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool Eval::lt(Expression_Obj lhs, Expression_Obj rhs, std::string op)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Number_Obj l = Cast<Number>(lhs);
|
|
Packit Service |
7770af |
Number_Obj r = Cast<Number>(rhs);
|
|
Packit Service |
7770af |
// use compare operator from ast node
|
|
Packit Service |
7770af |
if (!l || !r) throw Exception::UndefinedOperation(lhs, rhs, op);
|
|
Packit Service |
7770af |
// use compare operator from ast node
|
|
Packit Service |
7770af |
return *l < *r;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Value_Ptr Eval::op_numbers(enum Sass_OP op, const Number& l, const Number& r, struct Sass_Inspect_Options opt, const ParserState& pstate)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
double lv = l.value();
|
|
Packit Service |
7770af |
double rv = r.value();
|
|
Packit Service |
7770af |
if (op == Sass_OP::DIV && rv == 0) {
|
|
Packit Service |
7770af |
// XXX: this is never hit via spec tests
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(String_Quoted, pstate, lv ? "Infinity" : "NaN");
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (op == Sass_OP::MOD && !rv) {
|
|
Packit Service |
7770af |
// XXX: this is never hit via spec tests
|
|
Packit Service |
7770af |
throw Exception::ZeroDivisionError(l, r);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
size_t l_n_units = l.numerator_units().size();
|
|
Packit Service |
7770af |
size_t l_d_units = l.numerator_units().size();
|
|
Packit Service |
7770af |
size_t r_n_units = r.denominator_units().size();
|
|
Packit Service |
7770af |
size_t r_d_units = r.denominator_units().size();
|
|
Packit Service |
7770af |
// optimize out the most common and simplest case
|
|
Packit Service |
7770af |
if (l_n_units == r_n_units && l_d_units == r_d_units) {
|
|
Packit Service |
7770af |
if (l_n_units + l_d_units <= 1 && r_n_units + r_d_units <= 1) {
|
|
Packit Service |
7770af |
if (l.numerator_units() == r.numerator_units()) {
|
|
Packit Service |
7770af |
if (l.denominator_units() == r.denominator_units()) {
|
|
Packit Service |
7770af |
Number_Ptr v = SASS_MEMORY_COPY(&l);
|
|
Packit Service |
7770af |
v->value(ops[op](lv, rv));
|
|
Packit Service |
7770af |
return v;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Number tmp(&r); // copy
|
|
Packit Service |
7770af |
bool strict = op != Sass_OP::MUL && op != Sass_OP::DIV;
|
|
Packit Service |
7770af |
tmp.normalize(l.find_convertible_unit(), strict);
|
|
Packit Service |
7770af |
std::string l_unit(l.unit());
|
|
Packit Service |
7770af |
std::string r_unit(tmp.unit());
|
|
Packit Service |
7770af |
Number_Obj v = SASS_MEMORY_COPY(&l); // copy
|
|
Packit Service |
7770af |
v->pstate(pstate);
|
|
Packit Service |
7770af |
if (l_unit.empty() && (op == Sass_OP::ADD || op == Sass_OP::SUB || op == Sass_OP::MOD)) {
|
|
Packit Service |
7770af |
v->numerator_units() = r.numerator_units();
|
|
Packit Service |
7770af |
v->denominator_units() = r.denominator_units();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (op == Sass_OP::MUL) {
|
|
Packit Service |
7770af |
v->value(ops[op](lv, rv));
|
|
Packit Service |
7770af |
for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) {
|
|
Packit Service |
7770af |
v->numerator_units().push_back(r.numerator_units()[i]);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) {
|
|
Packit Service |
7770af |
v->denominator_units().push_back(r.denominator_units()[i]);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (op == Sass_OP::DIV) {
|
|
Packit Service |
7770af |
v->value(ops[op](lv, rv));
|
|
Packit Service |
7770af |
for (size_t i = 0, S = r.numerator_units().size(); i < S; ++i) {
|
|
Packit Service |
7770af |
v->denominator_units().push_back(r.numerator_units()[i]);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
for (size_t i = 0, S = r.denominator_units().size(); i < S; ++i) {
|
|
Packit Service |
7770af |
v->numerator_units().push_back(r.denominator_units()[i]);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
v->value(ops[op](lv, r.value() * r.convert_factor(l)));
|
|
Packit Service |
7770af |
// v->normalize();
|
|
Packit Service |
7770af |
return v.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
v->normalize();
|
|
Packit Service |
7770af |
return v.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Value_Ptr Eval::op_number_color(enum Sass_OP op, const Number& l, const Color& r, struct Sass_Inspect_Options opt, const ParserState& pstate)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
double lv = l.value();
|
|
Packit Service |
7770af |
switch (op) {
|
|
Packit Service |
7770af |
case Sass_OP::ADD:
|
|
Packit Service |
7770af |
case Sass_OP::MUL: {
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(Color,
|
|
Packit Service |
7770af |
pstate,
|
|
Packit Service |
7770af |
ops[op](lv, r.r()),
|
|
Packit Service |
7770af |
ops[op](lv, r.g()),
|
|
Packit Service |
7770af |
ops[op](lv, r.b()),
|
|
Packit Service |
7770af |
r.a());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
case Sass_OP::SUB:
|
|
Packit Service |
7770af |
case Sass_OP::DIV: {
|
|
Packit Service |
7770af |
std::string sep(op == Sass_OP::SUB ? "-" : "/");
|
|
Packit Service |
7770af |
std::string color(r.to_string(opt));
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(String_Quoted,
|
|
Packit Service |
7770af |
pstate,
|
|
Packit Service |
7770af |
l.to_string(opt)
|
|
Packit Service |
7770af |
+ sep
|
|
Packit Service |
7770af |
+ color);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
case Sass_OP::MOD: {
|
|
Packit Service |
7770af |
throw Exception::UndefinedOperation(&l, &r, sass_op_to_name(op));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
default: break; // caller should ensure that we don't get here
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// unreachable
|
|
Packit Service |
7770af |
return NULL;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Value_Ptr Eval::op_color_number(enum Sass_OP op, const Color& l, const Number& r, struct Sass_Inspect_Options opt, const ParserState& pstate)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
double rv = r.value();
|
|
Packit Service |
7770af |
if (op == Sass_OP::DIV && !rv) {
|
|
Packit Service |
7770af |
// comparison of Fixnum with Float failed?
|
|
Packit Service |
7770af |
throw Exception::ZeroDivisionError(l, r);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(Color,
|
|
Packit Service |
7770af |
pstate,
|
|
Packit Service |
7770af |
ops[op](l.r(), rv),
|
|
Packit Service |
7770af |
ops[op](l.g(), rv),
|
|
Packit Service |
7770af |
ops[op](l.b(), rv),
|
|
Packit Service |
7770af |
l.a());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Value_Ptr Eval::op_colors(enum Sass_OP op, const Color& l, const Color& r, struct Sass_Inspect_Options opt, const ParserState& pstate)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (l.a() != r.a()) {
|
|
Packit Service |
7770af |
throw Exception::AlphaChannelsNotEqual(&l, &r, "+");
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (op == Sass_OP::DIV && (!r.r() || !r.g() ||!r.b())) {
|
|
Packit Service |
7770af |
// comparison of Fixnum with Float failed?
|
|
Packit Service |
7770af |
throw Exception::ZeroDivisionError(l, r);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(Color,
|
|
Packit Service |
7770af |
pstate,
|
|
Packit Service |
7770af |
ops[op](l.r(), r.r()),
|
|
Packit Service |
7770af |
ops[op](l.g(), r.g()),
|
|
Packit Service |
7770af |
ops[op](l.b(), r.b()),
|
|
Packit Service |
7770af |
l.a());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Value_Ptr Eval::op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Expression::Concrete_Type ltype = lhs.concrete_type();
|
|
Packit Service |
7770af |
Expression::Concrete_Type rtype = rhs.concrete_type();
|
|
Packit Service |
7770af |
enum Sass_OP op = operand.operand;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
String_Quoted_Ptr lqstr = Cast<String_Quoted>(&lhs;;
|
|
Packit Service |
7770af |
String_Quoted_Ptr rqstr = Cast<String_Quoted>(&rhs;;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string lstr(lqstr ? lqstr->value() : lhs.to_string(opt));
|
|
Packit Service |
7770af |
std::string rstr(rqstr ? rqstr->value() : rhs.to_string(opt));
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (ltype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op));
|
|
Packit Service |
7770af |
if (rtype == Expression::NULL_VAL) throw Exception::InvalidNullOperation(&lhs, &rhs, sass_op_to_name(op));
|
|
Packit Service |
7770af |
std::string sep;
|
|
Packit Service |
7770af |
switch (op) {
|
|
Packit Service |
7770af |
case Sass_OP::SUB: sep = "-"; break;
|
|
Packit Service |
7770af |
case Sass_OP::DIV: sep = "/"; break;
|
|
Packit Service |
7770af |
// cases are already handled above
|
|
Packit Service |
7770af |
case Sass_OP::EQ: sep = "=="; break;
|
|
Packit Service |
7770af |
case Sass_OP::NEQ: sep = "!="; break;
|
|
Packit Service |
7770af |
case Sass_OP::LT: sep = "<"; break;
|
|
Packit Service |
7770af |
case Sass_OP::GT: sep = ">"; break;
|
|
Packit Service |
7770af |
case Sass_OP::LTE: sep = "<="; break;
|
|
Packit Service |
7770af |
case Sass_OP::GTE: sep = ">="; break;
|
|
Packit Service |
7770af |
case Sass_OP::MUL: throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op));
|
|
Packit Service |
7770af |
case Sass_OP::MOD: throw Exception::UndefinedOperation(&lhs, &rhs, sass_op_to_name(op));
|
|
Packit Service |
7770af |
default: break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if ( (sep == "") /* &&
|
|
Packit Service |
7770af |
(sep != "/" || !rqstr || !rqstr->quote_mark()) */
|
|
Packit Service |
7770af |
) {
|
|
Packit Service |
7770af |
// create a new string that might be quoted on output (but do not unquote what we pass)
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(String_Quoted, pstate, lstr + rstr, 0, false, true);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (sep != "" && !delayed) {
|
|
Packit Service |
7770af |
if (operand.ws_before) sep = " " + sep;
|
|
Packit Service |
7770af |
if (operand.ws_after) sep = sep + " ";
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (op == Sass_OP::SUB || op == Sass_OP::DIV) {
|
|
Packit Service |
7770af |
if (lqstr && lqstr->quote_mark()) lstr = quote(lstr);
|
|
Packit Service |
7770af |
if (rqstr && rqstr->quote_mark()) rstr = quote(rstr);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(String_Constant, pstate, lstr + sep + rstr);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr cval_to_astnode(union Sass_Value* v, Backtrace* backtrace, ParserState pstate)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
using std::strlen;
|
|
Packit Service |
7770af |
using std::strcpy;
|
|
Packit Service |
7770af |
Expression_Ptr e = NULL;
|
|
Packit Service |
7770af |
switch (sass_value_get_tag(v)) {
|
|
Packit Service |
7770af |
case SASS_BOOLEAN: {
|
|
Packit Service |
7770af |
e = SASS_MEMORY_NEW(Boolean, pstate, !!sass_boolean_get_value(v));
|
|
Packit Service |
7770af |
} break;
|
|
Packit Service |
7770af |
case SASS_NUMBER: {
|
|
Packit Service |
7770af |
e = SASS_MEMORY_NEW(Number, pstate, sass_number_get_value(v), sass_number_get_unit(v));
|
|
Packit Service |
7770af |
} break;
|
|
Packit Service |
7770af |
case SASS_COLOR: {
|
|
Packit Service |
7770af |
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));
|
|
Packit Service |
7770af |
} break;
|
|
Packit Service |
7770af |
case SASS_STRING: {
|
|
Packit Service |
7770af |
if (sass_string_is_quoted(v))
|
|
Packit Service |
7770af |
e = SASS_MEMORY_NEW(String_Quoted, pstate, sass_string_get_value(v));
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
e = SASS_MEMORY_NEW(String_Constant, pstate, sass_string_get_value(v));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
} break;
|
|
Packit Service |
7770af |
case SASS_LIST: {
|
|
Packit Service |
7770af |
List_Ptr l = SASS_MEMORY_NEW(List, pstate, sass_list_get_length(v), sass_list_get_separator(v));
|
|
Packit Service |
7770af |
for (size_t i = 0, L = sass_list_get_length(v); i < L; ++i) {
|
|
Packit Service |
7770af |
l->append(cval_to_astnode(sass_list_get_value(v, i), backtrace, pstate));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
e = l;
|
|
Packit Service |
7770af |
} break;
|
|
Packit Service |
7770af |
case SASS_MAP: {
|
|
Packit Service |
7770af |
Map_Ptr m = SASS_MEMORY_NEW(Map, pstate);
|
|
Packit Service |
7770af |
for (size_t i = 0, L = sass_map_get_length(v); i < L; ++i) {
|
|
Packit Service |
7770af |
*m << std::make_pair(
|
|
Packit Service |
7770af |
cval_to_astnode(sass_map_get_key(v, i), backtrace, pstate),
|
|
Packit Service |
7770af |
cval_to_astnode(sass_map_get_value(v, i), backtrace, pstate));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
e = m;
|
|
Packit Service |
7770af |
} break;
|
|
Packit Service |
7770af |
case SASS_NULL: {
|
|
Packit Service |
7770af |
e = SASS_MEMORY_NEW(Null, pstate);
|
|
Packit Service |
7770af |
} break;
|
|
Packit Service |
7770af |
case SASS_ERROR: {
|
|
Packit Service |
7770af |
error("Error in C function: " + std::string(sass_error_get_message(v)), pstate, backtrace);
|
|
Packit Service |
7770af |
} break;
|
|
Packit Service |
7770af |
case SASS_WARNING: {
|
|
Packit Service |
7770af |
error("Warning in C function: " + std::string(sass_warning_get_message(v)), pstate, backtrace);
|
|
Packit Service |
7770af |
} break;
|
|
Packit Service |
7770af |
default: break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return e;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Selector_List_Ptr Eval::operator()(Selector_List_Ptr s)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::vector<Selector_List_Obj> rv;
|
|
Packit Service |
7770af |
Selector_List_Obj sl = SASS_MEMORY_NEW(Selector_List, s->pstate());
|
|
Packit Service |
7770af |
sl->is_optional(s->is_optional());
|
|
Packit Service |
7770af |
sl->media_block(s->media_block());
|
|
Packit Service |
7770af |
sl->is_optional(s->is_optional());
|
|
Packit Service |
7770af |
for (size_t i = 0, iL = s->length(); i < iL; ++i) {
|
|
Packit Service |
7770af |
rv.push_back(operator()((*s)[i]));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// we should actually permutate parent first
|
|
Packit Service |
7770af |
// but here we have permutated the selector first
|
|
Packit Service |
7770af |
size_t round = 0;
|
|
Packit Service |
7770af |
while (round != std::string::npos) {
|
|
Packit Service |
7770af |
bool abort = true;
|
|
Packit Service |
7770af |
for (size_t i = 0, iL = rv.size(); i < iL; ++i) {
|
|
Packit Service |
7770af |
if (rv[i]->length() > round) {
|
|
Packit Service |
7770af |
sl->append((*rv[i])[round]);
|
|
Packit Service |
7770af |
abort = false;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (abort) {
|
|
Packit Service |
7770af |
round = std::string::npos;
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
++ round;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return sl.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Selector_List_Ptr Eval::operator()(Complex_Selector_Ptr s)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
bool implicit_parent = !exp.old_at_root_without_rule;
|
|
Packit Service |
7770af |
if (is_in_selector_schema) exp.selector_stack.push_back(0);
|
|
Packit Service |
7770af |
Selector_List_Obj resolved = s->resolve_parent_refs(exp.selector_stack, implicit_parent);
|
|
Packit Service |
7770af |
if (is_in_selector_schema) exp.selector_stack.pop_back();
|
|
Packit Service |
7770af |
return resolved.detach();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// XXX: this is never hit via spec tests
|
|
Packit Service |
7770af |
Attribute_Selector_Ptr Eval::operator()(Attribute_Selector_Ptr s)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
String_Obj attr = s->value();
|
|
Packit Service |
7770af |
if (attr) { attr = static_cast<String_Ptr>(attr->perform(this)); }
|
|
Packit Service |
7770af |
Attribute_Selector_Ptr ss = SASS_MEMORY_COPY(s);
|
|
Packit Service |
7770af |
ss->value(attr);
|
|
Packit Service |
7770af |
return ss;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Selector_List_Ptr Eval::operator()(Selector_Schema_Ptr s)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
LOCAL_FLAG(is_in_selector_schema, true);
|
|
Packit Service |
7770af |
// the parser will look for a brace to end the selector
|
|
Packit Service |
7770af |
Expression_Obj sel = s->contents()->perform(this);
|
|
Packit Service |
7770af |
std::string result_str(sel->to_string(ctx.c_options));
|
|
Packit Service |
7770af |
result_str = unquote(Util::rtrim(result_str));
|
|
Packit Service |
7770af |
Parser p = Parser::from_c_str(result_str.c_str(), ctx, s->pstate());
|
|
Packit Service |
7770af |
p.last_media_block = s->media_block();
|
|
Packit Service |
7770af |
// a selector schema may or may not connect to parent?
|
|
Packit Service |
7770af |
bool chroot = s->connect_parent() == false;
|
|
Packit Service |
7770af |
Selector_List_Obj sl = p.parse_selector_list(chroot);
|
|
Packit Service |
7770af |
flag_is_in_selector_schema.reset();
|
|
Packit Service |
7770af |
return operator()(sl);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Expression_Ptr Eval::operator()(Parent_Selector_Ptr p)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (Selector_List_Obj pr = selector()) {
|
|
Packit Service |
7770af |
exp.selector_stack.pop_back();
|
|
Packit Service |
7770af |
Selector_List_Obj rv = operator()(pr);
|
|
Packit Service |
7770af |
exp.selector_stack.push_back(rv);
|
|
Packit Service |
7770af |
return rv.detach();
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
return SASS_MEMORY_NEW(Null, p->pstate());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|