Skip to content

Commit

Permalink
Merge pull request #1736 from mgreter/bugfix/issue_1169
Browse files Browse the repository at this point in the history
Defer creation of hash maps into eval stage
  • Loading branch information
mgreter committed Jan 9, 2016
2 parents 2b5869c + 7713511 commit 79a0e66
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 18 deletions.
3 changes: 2 additions & 1 deletion include/sass/values.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ enum Sass_Tag {
// Tags for denoting Sass list separators
enum Sass_Separator {
SASS_COMMA,
SASS_SPACE
SASS_SPACE,
SASS_HASH
};

// Value Operators
Expand Down
149 changes: 146 additions & 3 deletions src/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1880,19 +1880,114 @@ namespace Sass {
if (empty()) return res;
if (is_invisible()) return res;
bool items_output = false;
std::string sep = separator() == SASS_COMMA ? "," : " ";
std::string sep = separator() == SASS_SPACE ? " " : ",";
if (!compressed && sep == ",") sep += " ";
for (size_t i = 0, L = size(); i < L; ++i) {
if (separator_ == SASS_HASH)
{ sep[0] = i % 2 ? ':' : ','; }
Expression* item = (*this)[i];
if (item->is_invisible()) continue;
if (items_output) res += sep;
if (Value* v_val = dynamic_cast<Value*>(item))
{ res += v_val->to_string(compressed, precision); }
if (Expression* ex = dynamic_cast<Expression*>(item))
{ res += ex->to_string(compressed, precision); }
// else if (Function_Call* v_fn = dynamic_cast<Function_Call*>(item))
// { res += v_fn->to_string(compressed, precision); }
else { res += "[unknown type]"; }
items_output = true;
}
return res;
}

std::string Function_Call::to_string(bool compressed, int precision) const
{
std::string str(name());
str += "(";
str += arguments()->to_string(compressed, precision);
str += ")";
return str;
}

std::string Arguments::to_string(bool compressed, int precision) const
{
std::string str("");
for(auto arg : elements()) {
if (str != "") str += compressed ? "," : ", ";
str += arg->to_string(compressed, precision);
}
return str;
}

std::string Argument::to_string(bool compressed, int precision) const
{
return value()->to_string(compressed, precision);
}

std::string Binary_Expression::to_string(bool compressed, int precision) const
{
std::string str("");
str += left()->to_string(compressed, precision);
if (!compressed) str += " ";
switch (type()) {
case Sass_OP::AND: str += "and"; break;
case Sass_OP::OR: str += "or"; break;
case Sass_OP::EQ: str += "=="; break;
case Sass_OP::NEQ: str += "!="; break;
case Sass_OP::GT: str += ">"; break;
case Sass_OP::GTE: str += ">="; break;
case Sass_OP::LT: str += "<"; break;
case Sass_OP::LTE: str += "<="; break;
case Sass_OP::ADD: str += "+"; break;
case Sass_OP::SUB: str += "-"; break;
case Sass_OP::MUL: str += "*"; break;
case Sass_OP::DIV: str += "/"; break;
case Sass_OP::MOD: str += "%"; break;
default: break; // shouldn't get here
}
if (!compressed) str += " ";
str += right()->to_string(compressed, precision);
return str;
}
std::string Textual::to_string(bool compressed, int precision) const
{
return value();
}
std::string Variable::to_string(bool compressed, int precision) const
{
return name();
}

// For now it seems easiest to just implement these, since we need it to
// ie. report the values as is for error reporting (like duplicate keys).
// We cannot use inspect since we do not always have a context object.
std::string Unary_Expression::to_string(bool compressed, int precision) const
{
return "[Unary_Expression.to_string not implemented]";
}
std::string Function_Call_Schema::to_string(bool compressed, int precision) const
{
return "[Function_Call_Schema.to_string not implemented]";
}
std::string Media_Query::to_string(bool compressed, int precision) const
{
return "[Media_Query.to_string not implemented]";
}
std::string Media_Query_Expression::to_string(bool compressed, int precision) const
{
return "[Media_Query_Expression.to_string not implemented]";
}
std::string Supports_Condition::to_string(bool compressed, int precision) const
{
return "[Supports_Condition.to_string not implemented]";
}
std::string At_Root_Expression::to_string(bool compressed, int precision) const
{
return "[At_Root_Expression.to_string not implemented]";
}
std::string Thunk::to_string(bool compressed, int precision) const
{
return "[Thunk.to_string not implemented]";
}

std::string String_Schema::to_string(bool compressed, int precision) const
{
std::string res("");
Expand Down Expand Up @@ -1923,6 +2018,54 @@ namespace Sass {
else return c;
}

std::string Color::to_hex(bool compressed, int precision) const
{

std::stringstream ss;

// original color name
// maybe an unknown token
std::string name = disp();

// resolved color
std::string res_name = name;

double r = Sass::round(cap_channel<0xff>(r_));
double g = Sass::round(cap_channel<0xff>(g_));
double b = Sass::round(cap_channel<0xff>(b_));
double a = cap_channel<1> (a_);

// get color from given name (if one was given at all)
if (name != "" && name_to_color(name)) {
const Color* n = name_to_color(name);
r = Sass::round(cap_channel<0xff>(n->r()));
g = Sass::round(cap_channel<0xff>(n->g()));
b = Sass::round(cap_channel<0xff>(n->b()));
a = cap_channel<1> (n->a());
}
// otherwise get the possible resolved color name
else {
double numval = r * 0x10000 + g * 0x100 + b;
if (color_to_name(numval))
res_name = color_to_name(numval);
}

std::stringstream hexlet;
hexlet << '#' << std::setw(1) << std::setfill('0');
// create a short color hexlet if there is any need for it
if (compressed && is_color_doublet(r, g, b) && a == 1) {
hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(r) >> 4);
hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(g) >> 4);
hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(b) >> 4);
} else {
hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(r);
hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(g);
hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(b);
}

return hexlet.str();

}
std::string Color::to_string(bool compressed, int precision) const
{
std::stringstream ss;
Expand Down
46 changes: 37 additions & 9 deletions src/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,23 @@ namespace Sass {
virtual bool is_false() { return false; }
virtual bool operator== (const Expression& rhs) const { return false; }
virtual void set_delayed(bool delayed) { is_delayed(delayed); }
virtual std::string to_string(bool compressed = false, int precision = 5) const = 0;
virtual size_t hash() { return 0; }
};

//////////////////////////////////////////////////////////////////////
// Still just an expression, but with a to_string method
//////////////////////////////////////////////////////////////////////
class PreValue : public Expression {
public:
PreValue(ParserState pstate,
bool d = false, bool e = false, bool i = false, Concrete_Type ct = NONE)
: Expression(pstate, d, e, i, ct)
{ }
virtual std::string to_string(bool compressed = false, int precision = 5) const = 0;
virtual ~PreValue() { }
};

//////////////////////////////////////////////////////////////////////
// base class for values that support operations
//////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -846,8 +860,8 @@ namespace Sass {
std::string type() { return is_arglist_ ? "arglist" : "list"; }
static std::string type_name() { return "list"; }
const char* sep_string(bool compressed = false) const {
return separator() == SASS_COMMA ?
(compressed ? "," : ", ") : " ";
return separator() == SASS_SPACE ?
" " : (compressed ? "," : ", ");
}
bool is_invisible() const { return empty(); }
Expression* value_at_index(size_t i);
Expand Down Expand Up @@ -915,7 +929,7 @@ namespace Sass {
// operations. Templatized to avoid large switch statements and repetitive
// subclassing.
//////////////////////////////////////////////////////////////////////////
class Binary_Expression : public Expression {
class Binary_Expression : public PreValue {
private:
ADD_HASHED(Operand, op)
ADD_HASHED(Expression*, left)
Expand All @@ -924,7 +938,7 @@ namespace Sass {
public:
Binary_Expression(ParserState pstate,
Operand op, Expression* lhs, Expression* rhs)
: Expression(pstate), op_(op), left_(lhs), right_(rhs), hash_(0)
: PreValue(pstate), op_(op), left_(lhs), right_(rhs), hash_(0)
{ }
const std::string type_name() {
switch (type()) {
Expand Down Expand Up @@ -997,6 +1011,7 @@ namespace Sass {
}
return hash_;
}
virtual std::string to_string(bool compressed = false, int precision = 5) const;
enum Sass_OP type() const { return op_.operand; }
ATTACH_OPERATIONS()
};
Expand Down Expand Up @@ -1046,6 +1061,7 @@ namespace Sass {
};
return hash_;
}
virtual std::string to_string(bool compressed = false, int precision = 5) const;
ATTACH_OPERATIONS()
};

Expand Down Expand Up @@ -1091,6 +1107,7 @@ namespace Sass {
return hash_;
}

virtual std::string to_string(bool compressed = false, int precision = 5) const;
ATTACH_OPERATIONS()
};

Expand All @@ -1113,6 +1130,7 @@ namespace Sass {
has_rest_argument_(false),
has_keyword_argument_(false)
{ }
virtual std::string to_string(bool compressed = false, int precision = 5) const;

Argument* get_rest_argument();
Argument* get_keyword_argument();
Expand All @@ -1123,17 +1141,17 @@ namespace Sass {
//////////////////
// Function calls.
//////////////////
class Function_Call : public Expression {
class Function_Call : public PreValue {
ADD_HASHED(std::string, name)
ADD_HASHED(Arguments*, arguments)
ADD_PROPERTY(void*, cookie)
size_t hash_;
public:
Function_Call(ParserState pstate, std::string n, Arguments* args, void* cookie)
: Expression(pstate), name_(n), arguments_(args), cookie_(cookie), hash_(0)
: PreValue(pstate), name_(n), arguments_(args), cookie_(cookie), hash_(0)
{ concrete_type(STRING); }
Function_Call(ParserState pstate, std::string n, Arguments* args)
: Expression(pstate), name_(n), arguments_(args), cookie_(0), hash_(0)
: PreValue(pstate), name_(n), arguments_(args), cookie_(0), hash_(0)
{ concrete_type(STRING); }

virtual bool operator==(const Expression& rhs) const
Expand Down Expand Up @@ -1164,6 +1182,7 @@ namespace Sass {
return hash_;
}

virtual std::string to_string(bool compressed = false, int precision = 5) const;
ATTACH_OPERATIONS()
};

Expand All @@ -1177,17 +1196,18 @@ namespace Sass {
Function_Call_Schema(ParserState pstate, String* n, Arguments* args)
: Expression(pstate), name_(n), arguments_(args)
{ concrete_type(STRING); }
virtual std::string to_string(bool compressed = false, int precision = 5) const;
ATTACH_OPERATIONS()
};

///////////////////////
// Variable references.
///////////////////////
class Variable : public Expression {
class Variable : public PreValue {
ADD_PROPERTY(std::string, name)
public:
Variable(ParserState pstate, std::string n)
: Expression(pstate), name_(n)
: PreValue(pstate), name_(n)
{ }

virtual bool operator==(const Expression& rhs) const
Expand All @@ -1208,6 +1228,7 @@ namespace Sass {
{
return std::hash<std::string>()(name());
}
virtual std::string to_string(bool compressed = false, int precision = 5) const;

ATTACH_OPERATIONS()
};
Expand Down Expand Up @@ -1251,6 +1272,7 @@ namespace Sass {
}
return hash_;
}
virtual std::string to_string(bool compressed = false, int precision = 5) const;

ATTACH_OPERATIONS()
};
Expand Down Expand Up @@ -1330,6 +1352,7 @@ namespace Sass {
}

virtual bool operator== (const Expression& rhs) const;
virtual std::string to_hex(bool compressed = false, int precision = 5) const;
virtual std::string to_string(bool compressed = false, int precision = 5) const;

ATTACH_OPERATIONS()
Expand Down Expand Up @@ -1513,6 +1536,7 @@ namespace Sass {
: Expression(pstate), Vectorized<Media_Query_Expression*>(s),
media_type_(t), is_negated_(n), is_restricted_(r)
{ }
virtual std::string to_string(bool compressed = false, int precision = 5) const;
ATTACH_OPERATIONS()
};

Expand All @@ -1528,6 +1552,7 @@ namespace Sass {
Expression* f, Expression* v, bool i = false)
: Expression(pstate), feature_(f), value_(v), is_interpolated_(i)
{ }
virtual std::string to_string(bool compressed = false, int precision = 5) const;
ATTACH_OPERATIONS()
};

Expand All @@ -1554,6 +1579,7 @@ namespace Sass {
: Expression(pstate)
{ }
virtual bool needs_parens(Supports_Condition* cond) const { return false; }
virtual std::string to_string(bool compressed = false, int precision = 5) const;
ATTACH_OPERATIONS()
};

Expand Down Expand Up @@ -1658,6 +1684,7 @@ namespace Sass {
return false;
}
}
virtual std::string to_string(bool compressed = false, int precision = 5) const;
ATTACH_OPERATIONS()
};

Expand Down Expand Up @@ -1731,6 +1758,7 @@ namespace Sass {
Thunk(ParserState pstate, Expression* exp, Env* env = 0)
: Expression(pstate), expression_(exp), environment_(env)
{ }
virtual std::string to_string(bool compressed = false, int precision = 5) const;
};

/////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/debugger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ inline void debug_ast(AST_Node* node, std::string ind, Env* env)
std::cerr << ind << "List " << expression;
std::cerr << " (" << pstate_source_position(node) << ")";
std::cerr << " (" << expression->length() << ") " <<
(expression->separator() == SASS_COMMA ? "Comma " : "Space ") <<
(expression->separator() == SASS_COMMA ? "Comma " : expression->separator() == SASS_HASH ? "Map" : "Space ") <<
" [delayed: " << expression->is_delayed() << "] " <<
" [interpolant: " << expression->is_interpolant() << "] " <<
" [arglist: " << expression->is_arglist() << "] " <<
Expand Down
Loading

0 comments on commit 79a0e66

Please sign in to comment.