Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defer creation of hash maps into eval stage #1736

Merged
merged 1 commit into from
Jan 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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