Commit 350f04a1 by Aaron Leung

Redoing the arithmetic. Should fix some erroneous behavior on complex…

Redoing the arithmetic. Should fix some erroneous behavior on complex expressions in weird contexts.
parent 6cda1442
...@@ -224,15 +224,19 @@ namespace Sass { ...@@ -224,15 +224,19 @@ namespace Sass {
} break; } break;
case Node::expression: { case Node::expression: {
Node acc(new_Node(Node::expression, expr.path(), expr.line(), 1)); for (size_t i = 0, S = expr.size(); i < S; ++i) {
acc << eval(expr[0], prefix, env, f_env, new_Node, ctx); expr[i] = eval(expr[i], prefix, env, f_env, new_Node, ctx);
Node rhs(eval(expr[2], prefix, env, f_env, new_Node, ctx));
accumulate(expr[1].type(), acc, rhs, new_Node);
for (size_t i = 3, S = expr.size(); i < S; i += 2) {
Node rhs(eval(expr[i+1], prefix, env, f_env, new_Node, ctx));
accumulate(expr[i].type(), acc, rhs, new_Node);
} }
return acc.size() == 1 ? acc[0] : acc; return reduce(expr, 0, Node(), new_Node);
// Node acc(new_Node(Node::expression, expr.path(), expr.line(), 1));
// acc << eval(expr[0], prefix, env, f_env, new_Node, ctx);
// Node rhs(eval(expr[2], prefix, env, f_env, new_Node, ctx));
// accumulate(expr[1].type(), acc, rhs, new_Node);
// for (size_t i = 3, S = expr.size(); i < S; i += 2) {
// Node rhs(eval(expr[i+1], prefix, env, f_env, new_Node, ctx));
// accumulate(expr[i].type(), acc, rhs, new_Node);
// }
// return acc.size() == 1 ? acc[0] : acc;
} break; } break;
case Node::term: { case Node::term: {
...@@ -487,6 +491,46 @@ namespace Sass { ...@@ -487,6 +491,46 @@ namespace Sass {
// expressions are stored as vectors of operands with operators interspersed, // expressions are stored as vectors of operands with operators interspersed,
// rather than as the usual binary tree. // rather than as the usual binary tree.
Node reduce(Node list, size_t head, Node acc, Node_Factory& new_Node)
{
if (head >= list.size()) return acc;
Node rhs(list[head]);
Node op(list[head + 1]);
Node::Type optype = op.type();
if (acc.is_string()) {
acc = new_Node(Node::concatenation, list.path(), list.line(), 2);
if (optype == Node::sub || optype == Node::div || optype == Node::mul) {
acc << op;
}
acc << rhs;
}
Node::Type ltype = acc.type();
Node::Type rtype = rhs.type();
if (ltype == Node::number && rtype == Node::number) {
acc = new_Node(list.path(), list.line(), operate(optype, acc.numeric_value(), rhs.numeric_value()));
}
else if (ltype == Node::number && rtype == Node::numeric_dimension) {
acc = new_Node(list.path(), list.line(), operate(optype, acc.numeric_value(), rhs.numeric_value()), rhs.unit());
}
else if (ltype == Node::number && rtype == Node::numeric_dimension) {
acc = new_Node(list.path(), list.line(), operate(optype, acc.numeric_value(), rhs.numeric_value()), acc.unit());
}
else if (ltype == Node::numeric_dimension && rtype == Node::numeric_dimension) {
// TO DO: TRUE UNIT ARITHMETIC
if (optype == Node::div) {
acc = new_Node(list.path(), list.line(), operate(optype, acc.numeric_value(), rhs.numeric_value()));
}
else {
acc = new_Node(list.path(), list.line(), operate(optype, acc.numeric_value(), rhs.numeric_value()), acc.unit());
}
}
else if (ltype == Node::number && rtype == Node::numeric_color) {
}
return reduce(list, head + 3, acc, new_Node);
}
Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node) Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node)
{ {
Node lhs(acc.back()); Node lhs(acc.back());
......
...@@ -193,6 +193,7 @@ namespace Sass { ...@@ -193,6 +193,7 @@ namespace Sass {
bool& is_unquoted() const; // for strings bool& is_unquoted() const; // for strings
bool& is_quoted() const; // for identifiers bool& is_quoted() const; // for identifiers
bool is_numeric() const; bool is_numeric() const;
bool is_string() const; // for all string-like types
bool is_guarded() const; bool is_guarded() const;
bool& has_been_extended() const; bool& has_been_extended() const;
bool is_false() const; bool is_false() const;
...@@ -293,6 +294,27 @@ namespace Sass { ...@@ -293,6 +294,27 @@ namespace Sass {
bool is_numeric() bool is_numeric()
{ return type >= Node::number && type <= Node::numeric_dimension; } { return type >= Node::number && type <= Node::numeric_dimension; }
bool is_string()
{
switch (type)
{
case Node::string_t:
case Node::identifier:
case Node::value_schema:
case Node::identifier_schema:
case Node::string_constant:
case Node::string_schema:
case Node::concatenation: {
return true;
} break;
default: {
return false;
} break;
}
return false;
}
size_t size() size_t size()
{ return children.size(); } { return children.size(); }
...@@ -405,6 +427,7 @@ namespace Sass { ...@@ -405,6 +427,7 @@ namespace Sass {
inline bool& Node::is_unquoted() const { return ip_->is_unquoted; } inline bool& Node::is_unquoted() const { return ip_->is_unquoted; }
inline bool& Node::is_quoted() const { return ip_->is_quoted; } inline bool& Node::is_quoted() const { return ip_->is_quoted; }
inline bool Node::is_numeric() const { return ip_->is_numeric(); } inline bool Node::is_numeric() const { return ip_->is_numeric(); }
inline bool Node::is_string() const { return ip_->is_string(); }
inline bool Node::is_guarded() const { return (type() == assignment) && (size() == 3); } inline bool Node::is_guarded() const { return (type() == assignment) && (size() == 3); }
inline bool& Node::has_been_extended() const { return ip_->has_been_extended; } inline bool& Node::has_been_extended() const { return ip_->has_been_extended; }
inline bool Node::is_false() const { return (type() == boolean) && (boolean_value() == false); } inline bool Node::is_false() const { return (type() == boolean) && (boolean_value() == false); }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment