Skip to content

Commit

Permalink
Merge fixes and features for 3.2.3
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed May 8, 2015
9 parents ae310a7 + 081decb + 558b54b + 8bc46e4 + 2653a4a + 47bc665 + 3030315 + 9c74c7a + 8ae3917 commit f802410
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 116 deletions.
17 changes: 10 additions & 7 deletions ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ namespace Sass {
// skip already canceled out unit
if (exponents[denom] >= 0) continue;
// skip all units we don't know how to convert
if (string_to_unit(denom) == INCOMMENSURABLE) continue;
if (string_to_unit(denom) == UNKNOWN) continue;
// now search for nominator
while (nom_it != nom_end)
{
Expand All @@ -672,7 +672,7 @@ namespace Sass {
// skip already canceled out unit
if (exponents[nom] <= 0) continue;
// skip all units we don't know how to convert
if (string_to_unit(nom) == INCOMMENSURABLE) continue;
if (string_to_unit(nom) == UNKNOWN) continue;
// we now have two convertable units
// add factor for current conversion
factor *= conversion_factor(nom, denom);
Expand Down Expand Up @@ -707,7 +707,10 @@ namespace Sass {

// maybe convert to other unit
// easier implemented on its own
convert(prefered);
try { convert(prefered); }
catch (incompatibleUnits& err)
{ error(err.what(), pstate()); }
catch (...) { throw; }

}

Expand Down Expand Up @@ -743,7 +746,7 @@ namespace Sass {
// skip already canceled out unit
if (exponents[denom] >= 0) continue;
// skip all units we don't know how to convert
if (string_to_unit(denom) == INCOMMENSURABLE) continue;
if (string_to_unit(denom) == UNKNOWN) continue;
// we now have two convertable units
// add factor for current conversion
factor *= conversion_factor(denom, prefered);
Expand All @@ -764,7 +767,7 @@ namespace Sass {
// skip already canceled out unit
if (exponents[nom] <= 0) continue;
// skip all units we don't know how to convert
if (string_to_unit(nom) == INCOMMENSURABLE) continue;
if (string_to_unit(nom) == UNKNOWN) continue;
// we now have two convertable units
// add factor for current conversion
factor *= conversion_factor(nom, prefered);
Expand Down Expand Up @@ -801,11 +804,11 @@ namespace Sass {
{
for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
string u(numerator_units_[i]);
if (string_to_unit(u) != INCOMMENSURABLE) return u;
if (string_to_unit(u) != UNKNOWN) return u;
}
for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
string u(denominator_units_[i]);
if (string_to_unit(u) != INCOMMENSURABLE) return u;
if (string_to_unit(u) != UNKNOWN) return u;
}
return string();
}
Expand Down
44 changes: 8 additions & 36 deletions debugger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
cerr << ind << "If " << block;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " " << block->tabs() << endl;
debug_ast(block->predicate(), ind + " = ");
debug_ast(block->consequent(), ind + " <>");
debug_ast(block->alternative(), ind + " ><");
} else if (dynamic_cast<Return*>(node)) {
Return* block = dynamic_cast<Return*>(node);
cerr << ind << "Return " << block;
Expand All @@ -290,7 +293,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
cerr << ind << "Import " << block;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " " << block->tabs() << endl;
debug_ast(block->media_queries(), ind + " @ ");
// debug_ast(block->media_queries(), ind + " @ ");
// vector<string> files_;
for (auto imp : block->urls()) debug_ast(imp, "@ ", env);
} else if (dynamic_cast<Assignment*>(node)) {
Expand Down Expand Up @@ -390,39 +393,26 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
if (env && env->has(name)) debug_ast(static_cast<Expression*>((*env)[name]), ind + " -> ", env);
} else if (dynamic_cast<Function_Call_Schema*>(node)) {
Function_Call_Schema* expression = dynamic_cast<Function_Call_Schema*>(node);
cerr << ind << "Function_Call_Schema " << expression << "]";
if (expression->is_delayed()) cerr << " [delayed]";
cerr << endl;
cerr << ind << "Function_Call_Schema " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << "" << endl;
debug_ast(expression->name(), ind + "name: ", env);
debug_ast(expression->arguments(), ind + " args: ", env);
} else if (dynamic_cast<Function_Call*>(node)) {
Function_Call* expression = dynamic_cast<Function_Call*>(node);
cerr << ind << "Function_Call " << expression << " [" << expression->name() << "]";
if (expression->is_delayed()) cerr << " [delayed]";
cerr << endl;
cerr << ind << "Function_Call " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " [" << expression->name() << "]" << endl;
debug_ast(expression->arguments(), ind + " args: ", env);
} else if (dynamic_cast<Arguments*>(node)) {
Arguments* expression = dynamic_cast<Arguments*>(node);
cerr << ind << "Arguments " << expression << "]";
if (expression->is_delayed()) cerr << " [delayed]";
cerr << endl;
cerr << ind << "Arguments " << expression;
if (expression->is_delayed()) cerr << " [delayed]";
cerr << " (" << pstate_source_position(node) << ")";
cerr << endl;
for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
} else if (dynamic_cast<Argument*>(node)) {
Argument* expression = dynamic_cast<Argument*>(node);
cerr << ind << "Argument " << expression << " [" << expression->value() << "]";
if (expression->is_delayed()) cerr << " [delayed]";
if (expression->is_rest_argument()) cerr << " [is_rest_argument]";
if (expression->is_keyword_argument()) cerr << " [is_keyword_argument]";
cerr << endl;
cerr << ind << "Argument " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " [" << expression->value() << "]";
Expand All @@ -447,18 +437,12 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
cerr << " [rest: " << expression->is_rest_parameter() << "] " << endl;
} else if (dynamic_cast<Unary_Expression*>(node)) {
Unary_Expression* expression = dynamic_cast<Unary_Expression*>(node);
cerr << ind << "Unary_Expression " << expression << " [" << expression->type_name() << "]";
if (expression->is_delayed()) cerr << " [delayed]";
cerr << endl;
cerr << ind << "Unary_Expression " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " [" << expression->type() << "]" << endl;
debug_ast(expression->operand(), ind + " operand: ", env);
} else if (dynamic_cast<Binary_Expression*>(node)) {
Binary_Expression* expression = dynamic_cast<Binary_Expression*>(node);
cerr << ind << "Binary_Expression " << expression << " [" << expression->type_name() << "]";
if (expression->is_delayed()) cerr << " [delayed]";
cerr << endl;
cerr << ind << "Binary_Expression " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " [" << expression->type() << "]" << endl;
Expand All @@ -476,9 +460,6 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
cerr << " (" << expression->length() << ") " <<
(expression->separator() == Sass::List::Separator::COMMA ? "Comma " : "Space ") <<
" [delayed: " << expression->is_delayed() << "] " <<
" [interpolant: " << expression->is_interpolant() << "]";
if (expression->is_arglist()) cerr << " [is_arglist]";
cerr << endl;
" [interpolant: " << expression->is_interpolant() << "] " <<
" [arglist: " << expression->is_arglist() << "] " <<
endl;
Expand All @@ -490,25 +471,16 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
cerr << " [Statement]" << endl;
} else if (dynamic_cast<Boolean*>(node)) {
Boolean* expression = dynamic_cast<Boolean*>(node);
cerr << ind << "Boolean " << expression << " [" << expression->value() << "]";
if (expression->is_delayed()) cerr << " [delayed]";
cerr << endl;
cerr << ind << "Boolean " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " [" << expression->value() << "]" << endl;
} else if (dynamic_cast<Color*>(node)) {
Color* expression = dynamic_cast<Color*>(node);
cerr << ind << "Color " << expression << " [" << expression->r() << ":" << expression->g() << ":" << expression->b() << "@" << expression->a() << "]";
if (expression->is_delayed()) cerr << " [delayed]";
cerr << endl;
cerr << ind << "Color " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " [" << expression->r() << ":" << expression->g() << ":" << expression->b() << "@" << expression->a() << "]" << endl;
} else if (dynamic_cast<Number*>(node)) {
Number* expression = dynamic_cast<Number*>(node);
cerr << ind << "Number " << expression << " [" << expression->value() << expression->unit() << "]";
if (expression->is_delayed()) cerr << " [delayed]";
cerr << endl;
cerr << ind << "Number " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " [" << expression->value() << expression->unit() << "]" << endl;
Expand All @@ -533,7 +505,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
cerr << " [" << prettyprint(expression->value()) << "]";
if (expression->is_delayed()) cerr << " [delayed]";
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
cerr " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
cerr << ind << "String_Constant : " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " [" << prettyprint(expression->value()) << "]" <<
Expand All @@ -546,7 +518,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
cerr << ind << "String_Schema " << expression << " [" << expression->concrete_type() << "]";
if (expression->is_delayed()) cerr << " [delayed]";
if (expression->has_interpolants()) cerr << " [has_interpolants]";
cerr " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
cerr << ind << "String_Schema " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << " " << expression->concrete_type() <<
Expand All @@ -557,7 +529,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
String* expression = dynamic_cast<String*>(node);
cerr << ind << "String " << expression << expression->concrete_type();
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
cerr " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
cerr << ind << "String " << expression;
cerr << " (" << pstate_source_position(node) << ")";
cerr << expression->concrete_type() <<
Expand Down
13 changes: 9 additions & 4 deletions eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,7 @@ namespace Sass {
Expression* value = static_cast<Expression*>((*env)[name]);
return evacuate_quotes(interpolation(value));
} else if (Binary_Expression* var = dynamic_cast<Binary_Expression*>(s)) {
var->is_delayed(false);
Expression* ex = var->perform(this);
return evacuate_quotes(interpolation(ex));
} else if (Function_Call* var = dynamic_cast<Function_Call*>(s)) {
Expand All @@ -901,9 +902,9 @@ namespace Sass {
{
string acc;
for (size_t i = 0, L = s->length(); i < L; ++i) {
if (String_Quoted* str_quoted = dynamic_cast<String_Quoted*>((*s)[i])) {
if (!str_quoted->is_delayed()) str_quoted->value(string_eval_escapes(str_quoted->value()));
}
// if (String_Quoted* str_quoted = dynamic_cast<String_Quoted*>((*s)[i])) {
// if (!str_quoted->is_delayed()) str_quoted->value(string_eval_escapes(str_quoted->value()));
// }
acc += interpolation((*s)[i]);
}
String_Quoted* str = new (ctx.mem) String_Quoted(s->pstate(), acc);
Expand Down Expand Up @@ -1047,9 +1048,13 @@ namespace Sass {

Expression* Eval::operator()(Parent_Selector* p)
{
// no idea why both calls are needed
Selector* s = p->perform(contextualize);
if (!s) s = p->selector()->perform(contextualize);
// access to parent selector may return 0
Selector_List* l = static_cast<Selector_List*>(s);
// some spec tests cause this (might be a valid case!)
// if (!s) { cerr << "Parent Selector eval error" << endl; }
if (!s) { l = new (ctx.mem) Selector_List(p->pstate()); }
return l->perform(listize);
}
Expand Down Expand Up @@ -1186,7 +1191,7 @@ namespace Sass {
} else {
v->value(ops[op](lv, tmp.value()));
}
// v->normalize();
v->normalize();
return v;
}

Expand Down
13 changes: 12 additions & 1 deletion functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,18 @@ namespace Sass {
else if (sep_str == "comma") result->separator(List::COMMA);
else if (sep_str != "auto") error("argument `$separator` of `" + string(sig) + "` must be `space`, `comma`, or `auto`", pstate);
*result += l;
*result << v;
bool is_arglist = l->is_arglist();
result->is_arglist(is_arglist);
if (is_arglist) {
*result << new (ctx.mem) Argument(v->pstate(),
v,
"",
false,
false);

} else {
*result << v;
}
return result;
}

Expand Down
108 changes: 78 additions & 30 deletions inspect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,43 +416,91 @@ namespace Sass {

void Inspect::operator()(Number* n)
{

string res;

// init stuff
n->normalize();
int precision = 5;
double value = n->value();
// get option from optional context
if (ctx) precision = ctx->precision;

// check if the fractional part of the value equals to zero
// neat trick from http://stackoverflow.com/a/1521682/1550314
// double int_part; bool is_int = modf(value, &int_part) == 0.0;

// this all cannot be done with one run only, since fixed
// output differs from normal output and regular output
// can contain scientific notation which we do not want!

// first sample
stringstream ss;
ss.precision(ctx ? ctx->precision : 5);
ss << fixed << n->value();
string d(ss.str());
// store if the value did not equal zero
// if after applying precsision, the value gets
// truncated to zero, sass emits 0.0 instead of 0
bool nonzero = n->value() != 0;
size_t decimal = d.find('.');
if (decimal != string::npos) {
for (size_t i = d.length()-1; d[i] == '0' && i >= decimal; --i) {
d.resize(d.length()-1);
}
}
if (d[d.length()-1] == '.') d.resize(d.length()-1);
ss.precision(12);
ss << value;

// check if we got scientific notation in result
if (ss.str().find_first_of("e") != string::npos) {
ss.clear(); ss.str(string());
ss.precision(max(12, precision));
ss << fixed << value;
}

string tmp = ss.str();
size_t pos_point = tmp.find_first_of(".,");
size_t pos_fract = tmp.find_last_not_of("0");
bool is_int = pos_point == pos_fract ||
pos_point == string::npos;

// reset stream for another run
ss.clear(); ss.str(string());

// take a shortcut for integers
if (is_int)
{
ss.precision(0);
ss << fixed << value;
res = string(ss.str());
}
// process floats
else
{
// do we have have too much precision?
if (pos_fract < precision + pos_point)
{ precision = pos_fract - pos_point; }
// round value again
ss.precision(precision);
ss << fixed << value;
res = string(ss.str());
// maybe we truncated up to decimal point
size_t pos = res.find_last_not_of("0");
bool at_dec_point = res[pos] == '.' ||
res[pos] == ',';
// don't leave a blank point
if (at_dec_point) ++ pos;
res.resize (pos + 1);
}

// some final cosmetics
if (res == "-0.0") res.erase(0, 1);
else if (res == "-0") res.erase(0, 1);

// add unit now
res += n->unit();

// check for a valid unit here
// includes result for reporting
if (n->numerator_units().size() > 1 ||
n->denominator_units().size() > 0 ||
(n->numerator_units().size() && n->numerator_units()[0].find_first_of('/') != string::npos) ||
(n->numerator_units().size() && n->numerator_units()[0].find_first_of('*') != string::npos)
) {
error(d + n->unit() + " isn't a valid CSS value.", n->pstate());
}
if (!n->zero() && !in_declaration_list) {
if (d.substr(0, 3) == "-0.") d.erase(1, 1);
if (d.substr(0, 2) == "0.") d.erase(0, 1);
}
// remove the leading minus
if (d == "-0") d.erase(0, 1);
// use fractional output if we had
// a value before it got truncated
if (d == "0" && nonzero) d = "0.0";
// if the precision is 0 sass cast
// casts to a float with precision 1
if (ctx->precision == 0) d += ".0";
// append number and unit
append_token(d + n->unit(), n);
error(res + " isn't a valid CSS value.", n->pstate());
}

// output the final token
append_token(res, n);

}

// helper function for serializing colors
Expand Down
Loading

0 comments on commit f802410

Please sign in to comment.