Skip to content

Commit b5ac186

Browse files
committed
Enable full evaluation before logical operators
1 parent 060c498 commit b5ac186

File tree

4 files changed

+150
-26
lines changed

4 files changed

+150
-26
lines changed

ast.cpp

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -813,19 +813,46 @@ namespace Sass {
813813

814814
bool Number::operator== (Expression* rhs) const
815815
{
816-
Number l(pstate_, value_, unit());
817-
Number& r = dynamic_cast<Number&>(*rhs);
818-
l.normalize(find_convertible_unit());
819-
r.normalize(find_convertible_unit());
820-
return l.unit() == r.unit() &&
821-
l.value() == r.value();
816+
try
817+
{
818+
Number l(pstate_, value_, unit());
819+
Number& r = dynamic_cast<Number&>(*rhs);
820+
l.normalize(find_convertible_unit());
821+
r.normalize(find_convertible_unit());
822+
return l.unit() == r.unit() &&
823+
l.value() == r.value();
824+
}
825+
catch (std::bad_cast&) {}
826+
catch (...) { throw; }
827+
return false;
822828
}
823829

824830
bool Number::operator== (Expression& rhs) const
825831
{
826832
return operator==(&rhs);
827833
}
828834

835+
bool List::operator==(Expression* rhs) const
836+
{
837+
try
838+
{
839+
List* r = dynamic_cast<List*>(rhs);
840+
if (!r || length() != r->length()) return false;
841+
if (separator() != r->separator()) return false;
842+
for (size_t i = 0, L = r->length(); i < L; ++i)
843+
if (*elements()[i] != *(*r)[i]) return false;
844+
return true;
845+
}
846+
catch (std::bad_cast&) {}
847+
catch (...) { throw; }
848+
return false;
849+
}
850+
851+
bool List::operator== (Expression& rhs) const
852+
{
853+
return operator==(&rhs);
854+
}
855+
829856
Expression* Hashed::at(Expression* k) const
830857
{
831858
if (elements_.count(k))

ast.hpp

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ namespace Sass {
113113
static string type_name() { return ""; }
114114
virtual bool is_false() { return false; }
115115
virtual bool operator==( Expression& rhs) const { return false; }
116+
virtual void set_delayed(bool delayed) { is_delayed(delayed); }
116117
virtual size_t hash() { return 0; }
117118
};
118119
}
@@ -756,23 +757,8 @@ namespace Sass {
756757
bool is_invisible() { return !length(); }
757758
Expression* value_at_index(size_t i);
758759

759-
virtual bool operator==(Expression& rhs) const
760-
{
761-
try
762-
{
763-
List& l = dynamic_cast<List&>(rhs);
764-
if (!(l && length() == l.length() && separator() == l.separator())) return false;
765-
for (size_t i = 0, L = l.length(); i < L; ++i)
766-
if (!(*(elements()[i]) == *(l[i]))) return false;
767-
return true;
768-
}
769-
catch (std::bad_cast&)
770-
{
771-
return false;
772-
}
773-
catch (...) { throw; }
774-
775-
}
760+
virtual bool operator==(Expression& rhs) const;
761+
virtual bool operator==(Expression* rhs) const;
776762

777763
virtual size_t hash()
778764
{
@@ -786,6 +772,13 @@ namespace Sass {
786772
return hash_;
787773
}
788774

775+
virtual void set_delayed(bool delayed)
776+
{
777+
for (size_t i = 0, L = length(); i < L; ++i)
778+
(elements()[i])->set_delayed(delayed);
779+
is_delayed(delayed);
780+
}
781+
789782
ATTACH_OPERATIONS();
790783
};
791784

@@ -857,6 +850,31 @@ namespace Sass {
857850
Type t, Expression* lhs, Expression* rhs)
858851
: Expression(pstate), type_(t), left_(lhs), right_(rhs), hash_(0)
859852
{ }
853+
const string type_name() {
854+
switch (type_) {
855+
case AND: return "and"; break;
856+
case OR: return "or"; break;
857+
case EQ: return "eq"; break;
858+
case NEQ: return "neq"; break;
859+
case GT: return "gt"; break;
860+
case GTE: return "gte"; break;
861+
case LT: return "lt"; break;
862+
case LTE: return "lte"; break;
863+
case ADD: return "add"; break;
864+
case SUB: return "sub"; break;
865+
case MUL: return "mul"; break;
866+
case DIV: return "div"; break;
867+
case MOD: return "mod"; break;
868+
case NUM_OPS: return "num_ops"; break;
869+
default: return "invalid"; break;
870+
}
871+
}
872+
virtual void set_delayed(bool delayed)
873+
{
874+
right()->set_delayed(delayed);
875+
left()->set_delayed(delayed);
876+
is_delayed(delayed);
877+
}
860878
virtual bool operator==(Expression& rhs) const
861879
{
862880
try
@@ -896,6 +914,14 @@ namespace Sass {
896914
Unary_Expression(ParserState pstate, Type t, Expression* o)
897915
: Expression(pstate), type_(t), operand_(o), hash_(0)
898916
{ }
917+
const string type_name() {
918+
switch (type_) {
919+
case PLUS: return "plus"; break;
920+
case MINUS: return "minus"; break;
921+
case NOT: return "not"; break;
922+
default: return "invalid"; break;
923+
}
924+
}
899925
virtual bool operator==(Expression& rhs) const
900926
{
901927
try

debugger.hpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
290290
cerr << ind << "Import " << block;
291291
cerr << " (" << pstate_source_position(node) << ")";
292292
cerr << " " << block->tabs() << endl;
293+
debug_ast(block->media_queries(), ind + " @ ");
293294
// vector<string> files_;
294295
for (auto imp : block->urls()) debug_ast(imp, "@ ", env);
295296
} else if (dynamic_cast<Assignment*>(node)) {
@@ -374,35 +375,54 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
374375
else if (expression->type() == Textual::PERCENTAGE) cerr << " [PERCENTAGE]";
375376
else if (expression->type() == Textual::DIMENSION) cerr << " [DIMENSION]";
376377
else if (expression->type() == Textual::HEX) cerr << " [HEX]";
377-
cerr << expression << " [" << expression->value() << "]" << endl;
378+
cerr << expression << " [" << expression->value() << "]";
379+
if (expression->is_delayed()) cerr << " [delayed]";
380+
cerr << endl;
378381
} else if (dynamic_cast<Variable*>(node)) {
379382
Variable* expression = dynamic_cast<Variable*>(node);
383+
cerr << ind << "Variable " << expression << " [" << expression->name() << "]";
384+
if (expression->is_delayed()) cerr << " [delayed]";
385+
cerr << endl;
380386
cerr << ind << "Variable " << expression;
381387
cerr << " (" << pstate_source_position(node) << ")";
382388
cerr << " [" << expression->name() << "]" << endl;
383389
string name(expression->name());
384390
if (env && env->has(name)) debug_ast(static_cast<Expression*>((*env)[name]), ind + " -> ", env);
385391
} else if (dynamic_cast<Function_Call_Schema*>(node)) {
386392
Function_Call_Schema* expression = dynamic_cast<Function_Call_Schema*>(node);
393+
cerr << ind << "Function_Call_Schema " << expression << "]";
394+
if (expression->is_delayed()) cerr << " [delayed]";
395+
cerr << endl;
387396
cerr << ind << "Function_Call_Schema " << expression;
388397
cerr << " (" << pstate_source_position(node) << ")";
389398
cerr << "" << endl;
390399
debug_ast(expression->name(), ind + "name: ", env);
391400
debug_ast(expression->arguments(), ind + " args: ", env);
392401
} else if (dynamic_cast<Function_Call*>(node)) {
393402
Function_Call* expression = dynamic_cast<Function_Call*>(node);
403+
cerr << ind << "Function_Call " << expression << " [" << expression->name() << "]";
404+
if (expression->is_delayed()) cerr << " [delayed]";
405+
cerr << endl;
394406
cerr << ind << "Function_Call " << expression;
395407
cerr << " (" << pstate_source_position(node) << ")";
396408
cerr << " [" << expression->name() << "]" << endl;
397409
debug_ast(expression->arguments(), ind + " args: ", env);
398410
} else if (dynamic_cast<Arguments*>(node)) {
399411
Arguments* expression = dynamic_cast<Arguments*>(node);
412+
cerr << ind << "Arguments " << expression << "]";
413+
if (expression->is_delayed()) cerr << " [delayed]";
414+
cerr << endl;
400415
cerr << ind << "Arguments " << expression;
401416
cerr << " (" << pstate_source_position(node) << ")";
402417
cerr << endl;
403418
for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
404419
} else if (dynamic_cast<Argument*>(node)) {
405420
Argument* expression = dynamic_cast<Argument*>(node);
421+
cerr << ind << "Argument " << expression << " [" << expression->value() << "]";
422+
if (expression->is_delayed()) cerr << " [delayed]";
423+
if (expression->is_rest_argument()) cerr << " [is_rest_argument]";
424+
if (expression->is_keyword_argument()) cerr << " [is_keyword_argument]";
425+
cerr << endl;
406426
cerr << ind << "Argument " << expression;
407427
cerr << " (" << pstate_source_position(node) << ")";
408428
cerr << " [" << expression->value() << "]";
@@ -427,12 +447,18 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
427447
cerr << " [rest: " << expression->is_rest_parameter() << "] " << endl;
428448
} else if (dynamic_cast<Unary_Expression*>(node)) {
429449
Unary_Expression* expression = dynamic_cast<Unary_Expression*>(node);
450+
cerr << ind << "Unary_Expression " << expression << " [" << expression->type_name() << "]";
451+
if (expression->is_delayed()) cerr << " [delayed]";
452+
cerr << endl;
430453
cerr << ind << "Unary_Expression " << expression;
431454
cerr << " (" << pstate_source_position(node) << ")";
432455
cerr << " [" << expression->type() << "]" << endl;
433456
debug_ast(expression->operand(), ind + " operand: ", env);
434457
} else if (dynamic_cast<Binary_Expression*>(node)) {
435458
Binary_Expression* expression = dynamic_cast<Binary_Expression*>(node);
459+
cerr << ind << "Binary_Expression " << expression << " [" << expression->type_name() << "]";
460+
if (expression->is_delayed()) cerr << " [delayed]";
461+
cerr << endl;
436462
cerr << ind << "Binary_Expression " << expression;
437463
cerr << " (" << pstate_source_position(node) << ")";
438464
cerr << " [" << expression->type() << "]" << endl;
@@ -450,6 +476,9 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
450476
cerr << " (" << expression->length() << ") " <<
451477
(expression->separator() == Sass::List::Separator::COMMA ? "Comma " : "Space ") <<
452478
" [delayed: " << expression->is_delayed() << "] " <<
479+
" [interpolant: " << expression->is_interpolant() << "]";
480+
if (expression->is_arglist()) cerr << " [is_arglist]";
481+
cerr << endl;
453482
" [interpolant: " << expression->is_interpolant() << "] " <<
454483
" [arglist: " << expression->is_arglist() << "] " <<
455484
endl;
@@ -461,21 +490,36 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
461490
cerr << " [Statement]" << endl;
462491
} else if (dynamic_cast<Boolean*>(node)) {
463492
Boolean* expression = dynamic_cast<Boolean*>(node);
493+
cerr << ind << "Boolean " << expression << " [" << expression->value() << "]";
494+
if (expression->is_delayed()) cerr << " [delayed]";
495+
cerr << endl;
464496
cerr << ind << "Boolean " << expression;
465497
cerr << " (" << pstate_source_position(node) << ")";
466498
cerr << " [" << expression->value() << "]" << endl;
467499
} else if (dynamic_cast<Color*>(node)) {
468500
Color* expression = dynamic_cast<Color*>(node);
501+
cerr << ind << "Color " << expression << " [" << expression->r() << ":" << expression->g() << ":" << expression->b() << "@" << expression->a() << "]";
502+
if (expression->is_delayed()) cerr << " [delayed]";
503+
cerr << endl;
469504
cerr << ind << "Color " << expression;
470505
cerr << " (" << pstate_source_position(node) << ")";
471506
cerr << " [" << expression->r() << ":" << expression->g() << ":" << expression->b() << "@" << expression->a() << "]" << endl;
472507
} else if (dynamic_cast<Number*>(node)) {
473508
Number* expression = dynamic_cast<Number*>(node);
509+
cerr << ind << "Number " << expression << " [" << expression->value() << expression->unit() << "]";
510+
if (expression->is_delayed()) cerr << " [delayed]";
511+
cerr << endl;
474512
cerr << ind << "Number " << expression;
475513
cerr << " (" << pstate_source_position(node) << ")";
476514
cerr << " [" << expression->value() << expression->unit() << "]" << endl;
477515
} else if (dynamic_cast<String_Quoted*>(node)) {
478516
String_Quoted* expression = dynamic_cast<String_Quoted*>(node);
517+
cerr << ind << "String_Quoted : " << expression << " [";
518+
cerr << prettyprint(expression->value()) << "]";
519+
if (expression->is_delayed()) cerr << " [delayed]";
520+
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
521+
if (expression->quote_mark()) cerr << " [quote_mark]";
522+
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
479523
cerr << ind << "String_Quoted : " << expression;
480524
cerr << " (" << pstate_source_position(node) << ")";
481525
cerr << " [" << prettyprint(expression->value()) << "]" <<
@@ -486,6 +530,11 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
486530
} else if (dynamic_cast<String_Constant*>(node)) {
487531
String_Constant* expression = dynamic_cast<String_Constant*>(node);
488532
cerr << ind << "String_Constant : " << expression;
533+
cerr << " [" << prettyprint(expression->value()) << "]";
534+
if (expression->is_delayed()) cerr << " [delayed]";
535+
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
536+
cerr " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
537+
cerr << ind << "String_Constant : " << expression;
489538
cerr << " (" << pstate_source_position(node) << ")";
490539
cerr << " [" << prettyprint(expression->value()) << "]" <<
491540
(expression->is_delayed() ? " {delayed}" : "") <<
@@ -494,6 +543,10 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
494543
" <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
495544
} else if (dynamic_cast<String_Schema*>(node)) {
496545
String_Schema* expression = dynamic_cast<String_Schema*>(node);
546+
cerr << ind << "String_Schema " << expression << " [" << expression->concrete_type() << "]";
547+
if (expression->is_delayed()) cerr << " [delayed]";
548+
if (expression->has_interpolants()) cerr << " [has_interpolants]";
549+
cerr " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
497550
cerr << ind << "String_Schema " << expression;
498551
cerr << " (" << pstate_source_position(node) << ")";
499552
cerr << " " << expression->concrete_type() <<
@@ -502,6 +555,9 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
502555
for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
503556
} else if (dynamic_cast<String*>(node)) {
504557
String* expression = dynamic_cast<String*>(node);
558+
cerr << ind << "String " << expression << expression->concrete_type();
559+
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
560+
cerr " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
505561
cerr << ind << "String " << expression;
506562
cerr << " (" << pstate_source_position(node) << ")";
507563
cerr << expression->concrete_type() <<

eval.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,23 @@ namespace Sass {
435435
}
436436
// not a logical connective, so go ahead and eval the rhs
437437
Expression* rhs = b->right()->perform(this);
438-
rhs->is_delayed(false);
439-
while (typeid(*rhs) == typeid(Binary_Expression)) rhs = rhs->perform(this);
438+
// maybe fully evaluate structure
439+
if (op_type == Binary_Expression::EQ ||
440+
op_type == Binary_Expression::NEQ ||
441+
op_type == Binary_Expression::GT ||
442+
op_type == Binary_Expression::GTE ||
443+
op_type == Binary_Expression::LT ||
444+
op_type == Binary_Expression::LTE)
445+
{
446+
rhs->is_expanded(false);
447+
rhs->set_delayed(false);
448+
rhs = rhs->perform(this);
449+
}
450+
else
451+
{
452+
rhs->is_delayed(false);
453+
rhs = rhs->perform(this);
454+
}
440455

441456
// see if it's a relational expression
442457
switch(op_type) {

0 commit comments

Comments
 (0)