diff --git a/src/ast.cpp b/src/ast.cpp index 07edd83737..d8c67e339e 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -2,6 +2,7 @@ #include "ast.hpp" #include "context.hpp" #include "node.hpp" +#include "eval.hpp" #include "extend.hpp" #include "emitter.hpp" #include "color_maps.hpp" @@ -126,7 +127,7 @@ namespace Sass { return length() < rhs.length(); } - bool Compound_Selector::has_parent_ref() + bool Compound_Selector::has_parent_ref() const { for (Simple_Selector_Obj s : *this) { if (s && s->has_parent_ref()) return true; @@ -134,7 +135,7 @@ namespace Sass { return false; } - bool Compound_Selector::has_real_parent_ref() + bool Compound_Selector::has_real_parent_ref() const { for (Simple_Selector_Obj s : *this) { if (s && s->has_real_parent_ref()) return true; @@ -142,13 +143,13 @@ namespace Sass { return false; } - bool Complex_Selector::has_parent_ref() + bool Complex_Selector::has_parent_ref() const { return (head() && head()->has_parent_ref()) || (tail() && tail()->has_parent_ref()); } - bool Complex_Selector::has_real_parent_ref() + bool Complex_Selector::has_real_parent_ref() const { return (head() && head()->has_real_parent_ref()) || (tail() && tail()->has_real_parent_ref()); @@ -1185,7 +1186,14 @@ namespace Sass { } } + } + Selector_List_Obj Selector_List::eval(Eval& eval) + { + Selector_List_Obj list = schema() ? + eval(schema()) : eval(this); + list->schema(schema()); + return list; } Selector_List_Ptr Selector_List::resolve_parent_refs(Context& ctx, std::vector& pstack, bool implicit_parent) @@ -1472,7 +1480,31 @@ namespace Sass { } } - bool Selector_List::has_parent_ref() + size_t Wrapped_Selector::hash() + { + if (hash_ == 0) { + hash_combine(hash_, Simple_Selector::hash()); + if (selector_) hash_combine(hash_, selector_->hash()); + } + return hash_; + } + bool Wrapped_Selector::has_parent_ref() const { + // if (has_reference()) return true; + if (!selector()) return false; + return selector()->has_parent_ref(); + } + bool Wrapped_Selector::has_real_parent_ref() const { + // if (has_reference()) return true; + if (!selector()) return false; + return selector()->has_real_parent_ref(); + } + unsigned long Wrapped_Selector::specificity() const + { + return selector_ ? selector_->specificity() : 0; + } + + + bool Selector_List::has_parent_ref() const { for (Complex_Selector_Obj s : elements()) { if (s && s->has_parent_ref()) return true; @@ -1480,7 +1512,7 @@ namespace Sass { return false; } - bool Selector_List::has_real_parent_ref() + bool Selector_List::has_real_parent_ref() const { for (Complex_Selector_Obj s : elements()) { if (s && s->has_real_parent_ref()) return true; @@ -1488,7 +1520,7 @@ namespace Sass { return false; } - bool Selector_Schema::has_parent_ref() + bool Selector_Schema::has_parent_ref() const { if (String_Schema_Obj schema = Cast(contents())) { return schema->length() > 0 && Cast(schema->at(0)) != NULL; @@ -1496,7 +1528,7 @@ namespace Sass { return false; } - bool Selector_Schema::has_real_parent_ref() + bool Selector_Schema::has_real_parent_ref() const { if (String_Schema_Obj schema = Cast(contents())) { Parent_Selector_Obj p = Cast(schema->at(0)); diff --git a/src/ast.hpp b/src/ast.hpp index 7674311832..d41e434c0e 100644 --- a/src/ast.hpp +++ b/src/ast.hpp @@ -201,7 +201,7 @@ namespace Sass { { } virtual operator bool() { return true; } virtual ~Expression() { } - virtual std::string type() { return ""; /* TODO: raise an error? */ } + virtual std::string type() const { return ""; /* TODO: raise an error? */ } virtual bool is_invisible() const { return false; } static std::string type_name() { return ""; } virtual bool is_false() { return false; } @@ -521,10 +521,10 @@ namespace Sass { // of style declarations. ///////////////////////////////////////////////////////////////////////////// class Ruleset : public Has_Block { - ADD_PROPERTY(Selector_Obj, selector) + ADD_PROPERTY(Selector_List_Obj, selector) ADD_PROPERTY(bool, is_root); public: - Ruleset(ParserState pstate, Selector_Obj s = 0, Block_Obj b = 0) + Ruleset(ParserState pstate, Selector_List_Obj s = 0, Block_Obj b = 0) : Has_Block(pstate, b), selector_(s), is_root_(false) { statement_type(RULESET); } Ruleset(const Ruleset* ptr) @@ -598,10 +598,10 @@ namespace Sass { /////////////////////////////////////////////////////////////////////// class Directive : public Has_Block { ADD_CONSTREF(std::string, keyword) - ADD_PROPERTY(Selector_Obj, selector) + ADD_PROPERTY(Selector_List_Obj, selector) ADD_PROPERTY(Expression_Obj, value) public: - Directive(ParserState pstate, std::string kwd, Selector_Obj sel = 0, Block_Obj b = 0, Expression_Obj val = 0) + Directive(ParserState pstate, std::string kwd, Selector_List_Obj sel = 0, Block_Obj b = 0, Expression_Obj val = 0) : Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed { statement_type(DIRECTIVE); } Directive(const Directive* ptr) @@ -633,7 +633,7 @@ namespace Sass { class Keyframe_Rule : public Has_Block { // according to css spec, this should be // = | - ADD_PROPERTY(Selector_Obj, name) + ADD_PROPERTY(Selector_List_Obj, name) public: Keyframe_Rule(ParserState pstate, Block_Obj b) : Has_Block(pstate, b), name_() @@ -911,9 +911,9 @@ namespace Sass { // The Sass `@extend` directive. //////////////////////////////// class Extension : public Statement { - ADD_PROPERTY(Selector_Obj, selector) + ADD_PROPERTY(Selector_List_Obj, selector) public: - Extension(ParserState pstate, Selector_Obj s) + Extension(ParserState pstate, Selector_List_Obj s) : Statement(pstate), selector_(s) { statement_type(EXTEND); } Extension(const Extension* ptr) @@ -1073,7 +1073,7 @@ namespace Sass { is_bracketed_(ptr->is_bracketed_), from_selector_(ptr->from_selector_) { concrete_type(LIST); } - std::string type() { return is_arglist_ ? "arglist" : "list"; } + std::string type() const { return is_arglist_ ? "arglist" : "list"; } static std::string type_name() { return "list"; } const char* sep_string(bool compressed = false) const { return separator() == SASS_SPACE ? @@ -1122,7 +1122,7 @@ namespace Sass { : Value(ptr), Hashed(*ptr) { concrete_type(MAP); } - std::string type() { return "map"; } + std::string type() const { return "map"; } static std::string type_name() { return "map"; } bool is_invisible() const { return empty(); } List_Obj to_list(Context& ctx, ParserState& pstate); @@ -1190,7 +1190,7 @@ namespace Sass { hash_(ptr->hash_) { } const std::string type_name() { - switch (type()) { + switch (optype()) { case AND: return "and"; break; case OR: return "or"; break; case EQ: return "eq"; break; @@ -1210,7 +1210,7 @@ namespace Sass { } } const std::string separator() { - switch (type()) { + switch (optype()) { case AND: return "&&"; break; case OR: return "||"; break; case EQ: return "=="; break; @@ -1261,13 +1261,13 @@ namespace Sass { virtual size_t hash() { if (hash_ == 0) { - hash_ = std::hash()(type()); + hash_ = std::hash()(optype()); hash_combine(hash_, left()->hash()); hash_combine(hash_, right()->hash()); } return hash_; } - enum Sass_OP type() const { return op_.operand; } + enum Sass_OP optype() const { return op_.operand; } ATTACH_AST_OPERATIONS(Binary_Expression) ATTACH_OPERATIONS() }; @@ -1279,21 +1279,21 @@ namespace Sass { public: enum Type { PLUS, MINUS, NOT }; private: - HASH_PROPERTY(Type, type) + HASH_PROPERTY(Type, optype) HASH_PROPERTY(Expression_Obj, operand) size_t hash_; public: Unary_Expression(ParserState pstate, Type t, Expression_Obj o) - : Expression(pstate), type_(t), operand_(o), hash_(0) + : Expression(pstate), optype_(t), operand_(o), hash_(0) { } Unary_Expression(const Unary_Expression* ptr) : Expression(ptr), - type_(ptr->type_), + optype_(ptr->optype_), operand_(ptr->operand_), hash_(ptr->hash_) { } const std::string type_name() { - switch (type_) { + switch (optype_) { case PLUS: return "plus"; break; case MINUS: return "minus"; break; case NOT: return "not"; break; @@ -1318,7 +1318,7 @@ namespace Sass { virtual size_t hash() { if (hash_ == 0) { - hash_ = std::hash()(type_); + hash_ = std::hash()(optype_); hash_combine(hash_, operand()->hash()); }; return hash_; @@ -1541,17 +1541,17 @@ namespace Sass { public: enum Type { NUMBER, PERCENTAGE, DIMENSION, HEX }; private: - HASH_PROPERTY(Type, type) + HASH_PROPERTY(Type, valtype) HASH_CONSTREF(std::string, value) size_t hash_; public: Textual(ParserState pstate, Type t, std::string val) - : Expression(pstate, DELAYED), type_(t), value_(val), + : Expression(pstate, DELAYED), valtype_(t), value_(val), hash_(0) { } Textual(const Textual* ptr) : Expression(ptr), - type_(ptr->type_), + valtype_(ptr->valtype_), value_(ptr->value_), hash_(ptr->hash_) { } @@ -1574,7 +1574,7 @@ namespace Sass { { if (hash_ == 0) { hash_ = std::hash()(value_); - hash_combine(hash_, std::hash()(type_)); + hash_combine(hash_, std::hash()(valtype_)); } return hash_; } @@ -1609,7 +1609,7 @@ namespace Sass { std::vector& denominator_units() { return denominator_units_; } const std::vector& numerator_units() const { return numerator_units_; } const std::vector& denominator_units() const { return denominator_units_; } - std::string type() { return "number"; } + std::string type() const { return "number"; } static std::string type_name() { return "number"; } std::string unit() const; @@ -1662,7 +1662,7 @@ namespace Sass { disp_(ptr->disp_), hash_(ptr->hash_) { concrete_type(COLOR); } - std::string type() { return "color"; } + std::string type() const { return "color"; } static std::string type_name() { return "color"; } virtual size_t hash() @@ -1733,7 +1733,7 @@ namespace Sass { hash_(ptr->hash_) { concrete_type(BOOLEAN); } virtual operator bool() { return value_; } - std::string type() { return "bool"; } + std::string type() const { return "bool"; } static std::string type_name() { return "bool"; } virtual bool is_false() { return !value_; } @@ -1792,7 +1792,7 @@ namespace Sass { hash_(ptr->hash_) { concrete_type(STRING); } - std::string type() { return "string"; } + std::string type() const { return "string"; } static std::string type_name() { return "string"; } bool is_left_interpolant(void) const; @@ -1853,7 +1853,7 @@ namespace Sass { String_Constant(ParserState pstate, const Token& tok) : String(pstate), quote_mark_(0), can_compress_whitespace_(false), value_(read_css_string(std::string(tok.begin, tok.end))), hash_(0) { } - std::string type() { return "string"; } + std::string type() const { return "string"; } static std::string type_name() { return "string"; } virtual bool is_invisible() const; virtual void rtrim(); @@ -2142,7 +2142,7 @@ namespace Sass { public: Null(ParserState pstate) : Value(pstate) { concrete_type(NULL_VAL); } Null(const Null* ptr) : Value(ptr) { concrete_type(NULL_VAL); } - std::string type() { return "null"; } + std::string type() const { return "null"; } static std::string type_name() { return "null"; } bool is_invisible() const { return true; } operator bool() { return false; } @@ -2296,10 +2296,10 @@ namespace Sass { virtual void set_media_block(Media_Block_Ptr mb) { media_block(mb); } - virtual bool has_parent_ref() { + virtual bool has_parent_ref() const { return false; } - virtual bool has_real_parent_ref() { + virtual bool has_real_parent_ref() const { return false; } // dispatch to correct handlers @@ -2313,22 +2313,29 @@ namespace Sass { // Interpolated selectors -- the interpolated String will be expanded and // re-parsed into a normal selector class. ///////////////////////////////////////////////////////////////////////// - class Selector_Schema : public Selector { + class Selector_Schema : public AST_Node { ADD_PROPERTY(String_Obj, contents) ADD_PROPERTY(bool, connect_parent); + // must not be a reference counted object + // otherwise we create circular references + ADD_PROPERTY(Media_Block_Ptr, media_block) + // store computed hash + size_t hash_; public: Selector_Schema(ParserState pstate, String_Obj c) - : Selector(pstate), + : AST_Node(pstate), contents_(c), - connect_parent_(true) + connect_parent_(true), + media_block_(NULL) { } Selector_Schema(const Selector_Schema* ptr) - : Selector(ptr), + : AST_Node(ptr), contents_(ptr->contents_), - connect_parent_(ptr->connect_parent_) + connect_parent_(ptr->connect_parent_), + media_block_(ptr->media_block_) { } - virtual bool has_parent_ref(); - virtual bool has_real_parent_ref(); + virtual bool has_parent_ref() const; + virtual bool has_real_parent_ref() const; virtual bool operator<(const Selector& rhs) const; virtual bool operator==(const Selector& rhs) const; // selector schema is not yet a final selector, so we do not @@ -2422,8 +2429,8 @@ namespace Sass { virtual ~Simple_Selector() = 0; virtual Compound_Selector_Ptr unify_with(Compound_Selector_Ptr, Context&); - virtual bool has_parent_ref() { return false; }; - virtual bool has_real_parent_ref() { return false; }; + virtual bool has_parent_ref() const { return false; }; + virtual bool has_real_parent_ref() const { return false; }; virtual bool is_pseudo_element() const { return false; } virtual bool is_superselector_of(Compound_Selector_Obj sub) { return false; } @@ -2456,14 +2463,14 @@ namespace Sass { Parent_Selector(const Parent_Selector* ptr) : Simple_Selector(ptr), real_(ptr->real_) { /* has_reference(true); */ } - bool is_real_parent_ref() { return real(); }; - virtual bool has_parent_ref() { return true; }; - virtual bool has_real_parent_ref() { return is_real_parent_ref(); }; + bool is_real_parent_ref() const { return real(); }; + virtual bool has_parent_ref() const { return true; }; + virtual bool has_real_parent_ref() const { return is_real_parent_ref(); }; virtual unsigned long specificity() const { return 0; } - std::string type() { return "selector"; } + std::string type() const { return "selector"; } static std::string type_name() { return "selector"; } ATTACH_AST_OPERATIONS(Parent_Selector) ATTACH_OPERATIONS() @@ -2657,9 +2664,9 @@ namespace Sass { // Wrapped selector -- pseudo selector that takes a list of selectors as argument(s) e.g., :not(:first-of-type), :-moz-any(ol p.blah, ul, menu, dir) ///////////////////////////////////////////////// class Wrapped_Selector : public Simple_Selector { - ADD_PROPERTY(Selector_Obj, selector) + ADD_PROPERTY(Selector_List_Obj, selector) public: - Wrapped_Selector(ParserState pstate, std::string n, Selector_Obj sel) + Wrapped_Selector(ParserState pstate, std::string n, Selector_List_Obj sel) : Simple_Selector(pstate, n), selector_(sel) { simple_type(WRAPPED_SEL); } Wrapped_Selector(const Wrapped_Selector* ptr) @@ -2668,28 +2675,10 @@ namespace Sass { virtual bool is_superselector_of(Wrapped_Selector_Obj sub); // Selectors inside the negation pseudo-class are counted like any // other, but the negation itself does not count as a pseudo-class. - virtual size_t hash() - { - if (hash_ == 0) { - hash_combine(hash_, Simple_Selector::hash()); - if (selector_) hash_combine(hash_, selector_->hash()); - } - return hash_; - } - virtual bool has_parent_ref() { - // if (has_reference()) return true; - if (!selector()) return false; - return selector()->has_parent_ref(); - } - virtual bool has_real_parent_ref() { - // if (has_reference()) return true; - if (!selector()) return false; - return selector()->has_real_parent_ref(); - } - virtual unsigned long specificity() const - { - return selector_ ? selector_->specificity() : 0; - } + virtual size_t hash(); + virtual bool has_parent_ref() const; + virtual bool has_real_parent_ref() const; + virtual unsigned long specificity() const; virtual bool operator==(const Simple_Selector& rhs) const; virtual bool operator==(const Wrapped_Selector& rhs) const; virtual bool operator<(const Simple_Selector& rhs) const; @@ -2744,8 +2733,8 @@ namespace Sass { Complex_Selector_Obj to_complex(); Compound_Selector_Ptr unify_with(Compound_Selector_Ptr rhs, Context& ctx); // virtual Placeholder_Selector_Ptr find_placeholder(); - virtual bool has_parent_ref(); - virtual bool has_real_parent_ref(); + virtual bool has_parent_ref() const; + virtual bool has_real_parent_ref() const; Simple_Selector_Ptr base() const { if (length() == 0) return 0; // ToDo: why is this needed? @@ -2838,8 +2827,8 @@ namespace Sass { head_(ptr->head_), tail_(ptr->tail_), reference_(ptr->reference_) {}; - virtual bool has_parent_ref(); - virtual bool has_real_parent_ref(); + virtual bool has_parent_ref() const; + virtual bool has_real_parent_ref() const; Complex_Selector_Obj skip_empty_reference() { @@ -2971,23 +2960,28 @@ namespace Sass { // Comma-separated selector groups. /////////////////////////////////// class Selector_List : public Selector, public Vectorized { + ADD_PROPERTY(Selector_Schema_Obj, schema) ADD_CONSTREF(std::vector, wspace) protected: void adjust_after_pushing(Complex_Selector_Obj c); public: Selector_List(ParserState pstate, size_t s = 0) - : Selector(pstate), Vectorized(s), wspace_(0) + : Selector(pstate), + Vectorized(s), + schema_(NULL), + wspace_(0) { } Selector_List(const Selector_List* ptr) : Selector(ptr), Vectorized(*ptr), + schema_(ptr->schema_), wspace_(ptr->wspace_) { } - std::string type() { return "list"; } + std::string type() const { return "list"; } // remove parent selector references // basically unwraps parsed selectors - virtual bool has_parent_ref(); - virtual bool has_real_parent_ref(); + virtual bool has_parent_ref() const; + virtual bool has_real_parent_ref() const; void remove_parent_selectors(); Selector_List_Ptr resolve_parent_refs(Context& ctx, std::vector& pstack, bool implicit_parent = true); virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapping = ""); @@ -2995,6 +2989,7 @@ namespace Sass { virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapping = ""); Selector_List_Ptr unify_with(Selector_List_Ptr, Context&); void populate_extends(Selector_List_Obj, Context&, Subset_Map&); + Selector_List_Obj eval(Eval& eval); virtual size_t hash() { if (Selector::hash_ == 0) { diff --git a/src/debugger.hpp b/src/debugger.hpp index 4768c61a50..ea21ddbbc2 100644 --- a/src/debugger.hpp +++ b/src/debugger.hpp @@ -103,6 +103,7 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << std::endl; + debug_ast(selector->schema(), "#{} "); for(const Complex_Selector_Obj& i : selector->elements()) { debug_ast(i, ind + " ", env); } @@ -261,8 +262,6 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << " (" << pstate_source_position(node) << ")" << " [@media:" << selector->media_block() << "]" << (selector->connect_parent() ? " [connect-parent]": " -") - << (selector->has_line_break() ? " [line-break]": " -") - << (selector->has_line_feed() ? " [line-feed]": " -") << std::endl; debug_ast(selector->contents(), ind + " "); @@ -390,7 +389,7 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) Content_Ptr block = Cast(node); std::cerr << ind << "Content " << block; std::cerr << " (" << pstate_source_position(node) << ")"; - std::cerr << " [@media:" << block->media_block().ptr() << "]"; + std::cerr << " [@media:" << block->media_block() << "]"; std::cerr << " " << block->tabs() << std::endl; } else if (Cast(node)) { Import_Stub_Ptr block = Cast(node); @@ -611,7 +610,7 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) Content_Ptr expression = Cast(node); std::cerr << ind << "Content " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; - std::cerr << " [@media:" << expression->media_block().ptr() << "]"; + std::cerr << " [@media:" << expression->media_block() << "]"; std::cerr << " [Statement]" << std::endl; } else if (Cast(node)) { Boolean_Ptr expression = Cast(node); diff --git a/src/eval.cpp b/src/eval.cpp index d093523a1c..219d47e45d 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -475,8 +475,8 @@ namespace Sass { l->length() / 2); for (size_t i = 0, L = l->length(); i < L; i += 2) { - Expression_Ptr key = (*l)[i+0]->perform(this); - Expression_Ptr val = (*l)[i+1]->perform(this); + Expression_Obj key = (*l)[i+0]->perform(this); + Expression_Obj val = (*l)[i+1]->perform(this); // make sure the color key never displays its real name key->is_delayed(true); // verified *lm << std::make_pair(key, val); @@ -539,7 +539,7 @@ namespace Sass { String_Schema_Obj ret_schema; Binary_Expression_Obj b = b_in; - enum Sass_OP op_type = b->type(); + enum Sass_OP op_type = b->optype(); // only the last item will be used to eval the binary expression if (String_Schema_Ptr s_l = Cast(b->left())) { @@ -788,14 +788,14 @@ namespace Sass { Expression_Ptr Eval::operator()(Unary_Expression_Ptr u) { Expression_Obj operand = u->operand()->perform(this); - if (u->type() == Unary_Expression::NOT) { + if (u->optype() == Unary_Expression::NOT) { Boolean_Ptr result = SASS_MEMORY_NEW(Boolean, u->pstate(), (bool)*operand); result->value(!result->value()); return result; } else if (Number_Obj nr = Cast(operand)) { // negate value for minus unary expression - if (u->type() == Unary_Expression::MINUS) { + if (u->optype() == Unary_Expression::MINUS) { Number_Obj cpy = SASS_MEMORY_COPY(nr); cpy->value( - cpy->value() ); // negate value return cpy.detach(); // return the copy @@ -1047,7 +1047,7 @@ namespace Sass { if (unit_pos == std::string::npos) unit_pos = text.length(); const std::string& num = text.substr(num_pos, unit_pos - num_pos); - switch (t->type()) + switch (t->valtype()) { case Textual::NUMBER: result = SASS_MEMORY_NEW(Number, diff --git a/src/expand.cpp b/src/expand.cpp index baef6a0471..1057d980f9 100644 --- a/src/expand.cpp +++ b/src/expand.cpp @@ -94,9 +94,11 @@ namespace Sass { Block_Ptr bb = operator()(r->block()); Keyframe_Rule_Obj k = SASS_MEMORY_NEW(Keyframe_Rule, r->pstate(), bb); if (r->selector()) { - selector_stack.push_back(0); - k->name(Cast(r->selector()->perform(&eval))); - selector_stack.pop_back(); + if (Selector_List_Ptr s = r->selector()) { + selector_stack.push_back(0); + k->name(s->eval(eval)); + selector_stack.pop_back(); + } } return k.detach(); } @@ -111,10 +113,8 @@ namespace Sass { has_parent_selector = ll != 0 && ll->length() > 0; } - Expression_Obj ex = 0; - if (r->selector()) ex = r->selector()->perform(&eval); - Selector_List_Obj sel = Cast(ex); - if (sel == 0) throw std::runtime_error("Expanded null selector"); + Selector_List_Obj sel = r->selector(); + if (sel) sel = sel->eval(eval); // check for parent selectors in base level rules if (r->is_root()) { @@ -219,11 +219,11 @@ namespace Sass { { LOCAL_FLAG(in_keyframes, a->is_keyframes()); Block_Ptr ab = a->block(); - Selector_Ptr as = a->selector(); + Selector_List_Ptr as = a->selector(); Expression_Ptr av = a->value(); selector_stack.push_back(0); if (av) av = av->perform(&eval); - if (as) as = Cast(as->perform(&eval)); + if (as) as = eval(as); selector_stack.pop_back(); Block_Ptr bb = ab ? operator()(ab) : NULL; Directive_Ptr aa = SASS_MEMORY_NEW(Directive, @@ -626,28 +626,23 @@ namespace Sass { Statement* Expand::operator()(Extension_Ptr e) { - if (Selector_List_Obj extender = Cast(selector())) { - Selector_Obj s = e->selector(); - Selector_List_Obj sl = NULL; - // check if we already have a valid selector list - if ((sl = Cast(s))) {} - // convert selector schema to a selector list - else if (Selector_Schema_Obj schema = Cast(s)) { + if (Selector_List_Ptr extender = selector()) { + Selector_List_Ptr sl = e->selector(); + // abort on invalid selector + if (sl == NULL) return NULL; + if (Selector_Schema_Ptr schema = sl->schema()) { if (schema->has_real_parent_ref()) { // put root block on stack again (ignore parents) // selector schema must not connect in eval! block_stack.push_back(block_stack.at(1)); - sl = eval(schema); + sl = eval(sl->schema()); block_stack.pop_back(); } else { selector_stack.push_back(0); - sl = eval(schema); - sl->remove_parent_selectors(); + sl = eval(sl->schema()); selector_stack.pop_back(); } } - // abort on invalid selector - if (sl.isNull()) return NULL; for (Complex_Selector_Obj cs : sl->elements()) { if (!cs.isNull() && !cs->head().isNull()) { cs->head()->media_block(media_block_stack.back()); diff --git a/src/inspect.cpp b/src/inspect.cpp index 53f5038b90..4ace72484c 100644 --- a/src/inspect.cpp +++ b/src/inspect.cpp @@ -467,7 +467,7 @@ namespace Sass { expr->is_right_interpolant()) )) append_string(" "); - switch (expr->type()) { + switch (expr->optype()) { case Sass_OP::AND: append_string("&&"); break; case Sass_OP::OR: append_string("||"); break; case Sass_OP::EQ: append_string("=="); break; @@ -495,8 +495,8 @@ namespace Sass { void Inspect::operator()(Unary_Expression_Ptr expr) { - if (expr->type() == Unary_Expression::PLUS) append_string("+"); - else append_string("-"); + if (expr->optype() == Unary_Expression::PLUS) append_string("+"); + else append_string("-"); expr->operand()->perform(this); } diff --git a/src/parser.cpp b/src/parser.cpp index 17119ba565..d266484ced 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -248,9 +248,15 @@ namespace Sass { else if (lex < kwd_extend >(true)) { Lookahead lookahead = lookahead_for_include(position); if (!lookahead.found) css_error("Invalid CSS", " after ", ": expected selector, was "); - Selector_Obj target; - if (lookahead.has_interpolants) target = parse_selector_schema(lookahead.found, true); - else target = parse_selector_list(true); + Selector_List_Obj target; + if (!lookahead.has_interpolants) { + target = parse_selector_list(true); + } + else { + target = SASS_MEMORY_NEW(Selector_List, pstate); + target->schema(parse_selector_schema(lookahead.found, true)); + } + block->append(SASS_MEMORY_NEW(Extension, pstate, target)); } @@ -496,7 +502,11 @@ namespace Sass { Ruleset_Obj ruleset = SASS_MEMORY_NEW(Ruleset, pstate); // parse selector static or as schema to be evaluated later if (lookahead.parsable) ruleset->selector(parse_selector_list(false)); - else ruleset->selector(parse_selector_schema(lookahead.found, false)); + else { + Selector_List_Obj list = SASS_MEMORY_NEW(Selector_List, pstate); + list->schema(parse_selector_schema(lookahead.found, false)); + ruleset->selector(list); + } // then parse the inner block stack.push_back(Scope::Rules); ruleset->block(parse_block());