// sass.hpp must go before all system headers to get the // __EXTENSIONS__ fix on Solaris. #include "sass.hpp" #include "ast.hpp" namespace Sass { static Null sass_null(SourceSpan("null")); const char* sass_op_to_name(enum Sass_OP op) { switch (op) { case AND: return "and"; case OR: return "or"; case EQ: return "eq"; case NEQ: return "neq"; case GT: return "gt"; case GTE: return "gte"; case LT: return "lt"; case LTE: return "lte"; case ADD: return "plus"; case SUB: return "minus"; case MUL: return "times"; case DIV: return "div"; case MOD: return "mod"; // this is only used internally! case NUM_OPS: return "[OPS]"; default: return "invalid"; } } const char* sass_op_separator(enum Sass_OP op) { switch (op) { case AND: return "&&"; case OR: return "||"; case EQ: return "=="; case NEQ: return "!="; case GT: return ">"; case GTE: return ">="; case LT: return "<"; case LTE: return "<="; case ADD: return "+"; case SUB: return "-"; case MUL: return "*"; case DIV: return "/"; case MOD: return "%"; // this is only used internally! case NUM_OPS: return "[OPS]"; default: return "invalid"; } } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void AST_Node::update_pstate(const SourceSpan& pstate) { pstate_.offset += pstate.position - pstate_.position + pstate.offset; } sass::string AST_Node::to_string(Sass_Inspect_Options opt) const { Sass_Output_Options out(opt); Emitter emitter(out); Inspect i(emitter); i.in_declaration = true; // ToDo: inspect should be const const_cast(this)->perform(&i); return i.get_buffer(); } sass::string AST_Node::to_css(Sass_Inspect_Options opt) const { opt.output_style = TO_CSS; Sass_Output_Options out(opt); Emitter emitter(out); Inspect i(emitter); i.in_declaration = true; // ToDo: inspect should be const const_cast(this)->perform(&i); return i.get_buffer(); } sass::string AST_Node::to_string() const { return to_string({ NESTED, 5 }); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Statement::Statement(SourceSpan pstate, Type st, size_t t) : AST_Node(pstate), statement_type_(st), tabs_(t), group_end_(false) { } Statement::Statement(const Statement* ptr) : AST_Node(ptr), statement_type_(ptr->statement_type_), tabs_(ptr->tabs_), group_end_(ptr->group_end_) { } bool Statement::bubbles() { return false; } bool Statement::has_content() { return statement_type_ == CONTENT; } bool Statement::is_invisible() const { return false; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Block::Block(SourceSpan pstate, size_t s, bool r) : Statement(pstate), Vectorized(s), is_root_(r) { } Block::Block(const Block* ptr) : Statement(ptr), Vectorized(*ptr), is_root_(ptr->is_root_) { } bool Block::isInvisible() const { for (auto& item : elements()) { if (!item->is_invisible()) return false; } return true; } bool Block::has_content() { for (size_t i = 0, L = elements().size(); i < L; ++i) { if (elements()[i]->has_content()) return true; } return Statement::has_content(); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ParentStatement::ParentStatement(SourceSpan pstate, Block_Obj b) : Statement(pstate), block_(b) { } ParentStatement::ParentStatement(const ParentStatement* ptr) : Statement(ptr), block_(ptr->block_) { } bool ParentStatement::has_content() { return (block_ && block_->has_content()) || Statement::has_content(); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// StyleRule::StyleRule(SourceSpan pstate, SelectorListObj s, Block_Obj b) : ParentStatement(pstate, b), selector_(s), schema_(), is_root_(false) { statement_type(RULESET); } StyleRule::StyleRule(const StyleRule* ptr) : ParentStatement(ptr), selector_(ptr->selector_), schema_(ptr->schema_), is_root_(ptr->is_root_) { statement_type(RULESET); } bool StyleRule::is_invisible() const { if (const SelectorList * sl = Cast(selector())) { for (size_t i = 0, L = sl->length(); i < L; i += 1) if (!(*sl)[i]->isInvisible()) return false; } return true; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Bubble::Bubble(SourceSpan pstate, Statement_Obj n, Statement_Obj g, size_t t) : Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == nullptr) { } Bubble::Bubble(const Bubble* ptr) : Statement(ptr), node_(ptr->node_), group_end_(ptr->group_end_) { } bool Bubble::bubbles() { return true; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Trace::Trace(SourceSpan pstate, sass::string n, Block_Obj b, char type) : ParentStatement(pstate, b), type_(type), name_(n) { } Trace::Trace(const Trace* ptr) : ParentStatement(ptr), type_(ptr->type_), name_(ptr->name_) { } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// AtRule::AtRule(SourceSpan pstate, sass::string kwd, SelectorListObj sel, Block_Obj b, ExpressionObj val) : ParentStatement(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed { statement_type(DIRECTIVE); } AtRule::AtRule(const AtRule* ptr) : ParentStatement(ptr), keyword_(ptr->keyword_), selector_(ptr->selector_), value_(ptr->value_) // set value manually if needed { statement_type(DIRECTIVE); } bool AtRule::bubbles() { return is_keyframes() || is_media(); } bool AtRule::is_media() { return keyword_.compare("@-webkit-media") == 0 || keyword_.compare("@-moz-media") == 0 || keyword_.compare("@-o-media") == 0 || keyword_.compare("@media") == 0; } bool AtRule::is_keyframes() { return keyword_.compare("@-webkit-keyframes") == 0 || keyword_.compare("@-moz-keyframes") == 0 || keyword_.compare("@-o-keyframes") == 0 || keyword_.compare("@keyframes") == 0; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Keyframe_Rule::Keyframe_Rule(SourceSpan pstate, Block_Obj b) : ParentStatement(pstate, b), name_() { statement_type(KEYFRAMERULE); } Keyframe_Rule::Keyframe_Rule(const Keyframe_Rule* ptr) : ParentStatement(ptr), name_(ptr->name_) { statement_type(KEYFRAMERULE); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Declaration::Declaration(SourceSpan pstate, String_Obj prop, ExpressionObj val, bool i, bool c, Block_Obj b) : ParentStatement(pstate, b), property_(prop), value_(val), is_important_(i), is_custom_property_(c), is_indented_(false) { statement_type(DECLARATION); } Declaration::Declaration(const Declaration* ptr) : ParentStatement(ptr), property_(ptr->property_), value_(ptr->value_), is_important_(ptr->is_important_), is_custom_property_(ptr->is_custom_property_), is_indented_(ptr->is_indented_) { statement_type(DECLARATION); } bool Declaration::is_invisible() const { if (is_custom_property()) return false; return !(value_ && !Cast(value_)); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Assignment::Assignment(SourceSpan pstate, sass::string var, ExpressionObj val, bool is_default, bool is_global) : Statement(pstate), variable_(var), value_(val), is_default_(is_default), is_global_(is_global) { statement_type(ASSIGNMENT); } Assignment::Assignment(const Assignment* ptr) : Statement(ptr), variable_(ptr->variable_), value_(ptr->value_), is_default_(ptr->is_default_), is_global_(ptr->is_global_) { statement_type(ASSIGNMENT); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Import::Import(SourceSpan pstate) : Statement(pstate), urls_(sass::vector()), incs_(sass::vector()), import_queries_() { statement_type(IMPORT); } Import::Import(const Import* ptr) : Statement(ptr), urls_(ptr->urls_), incs_(ptr->incs_), import_queries_(ptr->import_queries_) { statement_type(IMPORT); } sass::vector& Import::incs() { return incs_; } sass::vector& Import::urls() { return urls_; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Import_Stub::Import_Stub(SourceSpan pstate, Include res) : Statement(pstate), resource_(res) { statement_type(IMPORT_STUB); } Import_Stub::Import_Stub(const Import_Stub* ptr) : Statement(ptr), resource_(ptr->resource_) { statement_type(IMPORT_STUB); } Include Import_Stub::resource() { return resource_; }; sass::string Import_Stub::imp_path() { return resource_.imp_path; }; sass::string Import_Stub::abs_path() { return resource_.abs_path; }; ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// WarningRule::WarningRule(SourceSpan pstate, ExpressionObj msg) : Statement(pstate), message_(msg) { statement_type(WARNING); } WarningRule::WarningRule(const WarningRule* ptr) : Statement(ptr), message_(ptr->message_) { statement_type(WARNING); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ErrorRule::ErrorRule(SourceSpan pstate, ExpressionObj msg) : Statement(pstate), message_(msg) { statement_type(ERROR); } ErrorRule::ErrorRule(const ErrorRule* ptr) : Statement(ptr), message_(ptr->message_) { statement_type(ERROR); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// DebugRule::DebugRule(SourceSpan pstate, ExpressionObj val) : Statement(pstate), value_(val) { statement_type(DEBUGSTMT); } DebugRule::DebugRule(const DebugRule* ptr) : Statement(ptr), value_(ptr->value_) { statement_type(DEBUGSTMT); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Comment::Comment(SourceSpan pstate, String_Obj txt, bool is_important) : Statement(pstate), text_(txt), is_important_(is_important) { statement_type(COMMENT); } Comment::Comment(const Comment* ptr) : Statement(ptr), text_(ptr->text_), is_important_(ptr->is_important_) { statement_type(COMMENT); } bool Comment::is_invisible() const { return false; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// If::If(SourceSpan pstate, ExpressionObj pred, Block_Obj con, Block_Obj alt) : ParentStatement(pstate, con), predicate_(pred), alternative_(alt) { statement_type(IF); } If::If(const If* ptr) : ParentStatement(ptr), predicate_(ptr->predicate_), alternative_(ptr->alternative_) { statement_type(IF); } bool If::has_content() { return ParentStatement::has_content() || (alternative_ && alternative_->has_content()); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ForRule::ForRule(SourceSpan pstate, sass::string var, ExpressionObj lo, ExpressionObj hi, Block_Obj b, bool inc) : ParentStatement(pstate, b), variable_(var), lower_bound_(lo), upper_bound_(hi), is_inclusive_(inc) { statement_type(FOR); } ForRule::ForRule(const ForRule* ptr) : ParentStatement(ptr), variable_(ptr->variable_), lower_bound_(ptr->lower_bound_), upper_bound_(ptr->upper_bound_), is_inclusive_(ptr->is_inclusive_) { statement_type(FOR); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// EachRule::EachRule(SourceSpan pstate, sass::vector vars, ExpressionObj lst, Block_Obj b) : ParentStatement(pstate, b), variables_(vars), list_(lst) { statement_type(EACH); } EachRule::EachRule(const EachRule* ptr) : ParentStatement(ptr), variables_(ptr->variables_), list_(ptr->list_) { statement_type(EACH); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// WhileRule::WhileRule(SourceSpan pstate, ExpressionObj pred, Block_Obj b) : ParentStatement(pstate, b), predicate_(pred) { statement_type(WHILE); } WhileRule::WhileRule(const WhileRule* ptr) : ParentStatement(ptr), predicate_(ptr->predicate_) { statement_type(WHILE); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Return::Return(SourceSpan pstate, ExpressionObj val) : Statement(pstate), value_(val) { statement_type(RETURN); } Return::Return(const Return* ptr) : Statement(ptr), value_(ptr->value_) { statement_type(RETURN); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ExtendRule::ExtendRule(SourceSpan pstate, SelectorListObj s) : Statement(pstate), isOptional_(false), selector_(s), schema_() { statement_type(EXTEND); } ExtendRule::ExtendRule(SourceSpan pstate, Selector_Schema_Obj s) : Statement(pstate), isOptional_(false), selector_(), schema_(s) { statement_type(EXTEND); } ExtendRule::ExtendRule(const ExtendRule* ptr) : Statement(ptr), isOptional_(ptr->isOptional_), selector_(ptr->selector_), schema_(ptr->schema_) { statement_type(EXTEND); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Definition::Definition(const Definition* ptr) : ParentStatement(ptr), name_(ptr->name_), parameters_(ptr->parameters_), environment_(ptr->environment_), type_(ptr->type_), native_function_(ptr->native_function_), c_function_(ptr->c_function_), cookie_(ptr->cookie_), is_overload_stub_(ptr->is_overload_stub_), signature_(ptr->signature_) { } Definition::Definition(SourceSpan pstate, sass::string n, Parameters_Obj params, Block_Obj b, Type t) : ParentStatement(pstate, b), name_(n), parameters_(params), environment_(0), type_(t), native_function_(0), c_function_(0), cookie_(0), is_overload_stub_(false), signature_(0) { } Definition::Definition(SourceSpan pstate, Signature sig, sass::string n, Parameters_Obj params, Native_Function func_ptr, bool overload_stub) : ParentStatement(pstate, {}), name_(n), parameters_(params), environment_(0), type_(FUNCTION), native_function_(func_ptr), c_function_(0), cookie_(0), is_overload_stub_(overload_stub), signature_(sig) { } Definition::Definition(SourceSpan pstate, Signature sig, sass::string n, Parameters_Obj params, Sass_Function_Entry c_func) : ParentStatement(pstate, {}), name_(n), parameters_(params), environment_(0), type_(FUNCTION), native_function_(0), c_function_(c_func), cookie_(sass_function_get_cookie(c_func)), is_overload_stub_(false), signature_(sig) { } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Mixin_Call::Mixin_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, Parameters_Obj b_params, Block_Obj b) : ParentStatement(pstate, b), name_(n), arguments_(args), block_parameters_(b_params) { } Mixin_Call::Mixin_Call(const Mixin_Call* ptr) : ParentStatement(ptr), name_(ptr->name_), arguments_(ptr->arguments_), block_parameters_(ptr->block_parameters_) { } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Content::Content(SourceSpan pstate, Arguments_Obj args) : Statement(pstate), arguments_(args) { statement_type(CONTENT); } Content::Content(const Content* ptr) : Statement(ptr), arguments_(ptr->arguments_) { statement_type(CONTENT); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Expression::Expression(SourceSpan pstate, bool d, bool e, bool i, Type ct) : AST_Node(pstate), is_delayed_(d), is_expanded_(e), is_interpolant_(i), concrete_type_(ct) { } Expression::Expression(const Expression* ptr) : AST_Node(ptr), is_delayed_(ptr->is_delayed_), is_expanded_(ptr->is_expanded_), is_interpolant_(ptr->is_interpolant_), concrete_type_(ptr->concrete_type_) { } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Unary_Expression::Unary_Expression(SourceSpan pstate, Type t, ExpressionObj o) : Expression(pstate), optype_(t), operand_(o), hash_(0) { } Unary_Expression::Unary_Expression(const Unary_Expression* ptr) : Expression(ptr), optype_(ptr->optype_), operand_(ptr->operand_), hash_(ptr->hash_) { } const sass::string Unary_Expression::type_name() { switch (optype_) { case PLUS: return "plus"; case MINUS: return "minus"; case SLASH: return "slash"; case NOT: return "not"; default: return "invalid"; } } bool Unary_Expression::operator==(const Expression& rhs) const { try { const Unary_Expression* m = Cast(&rhs); if (m == 0) return false; return type() == m->type() && *operand() == *m->operand(); } catch (std::bad_cast&) { return false; } catch (...) { throw; } } size_t Unary_Expression::hash() const { if (hash_ == 0) { hash_ = std::hash()(optype_); hash_combine(hash_, operand()->hash()); }; return hash_; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Argument::Argument(SourceSpan pstate, ExpressionObj val, sass::string n, bool rest, bool keyword) : Expression(pstate), value_(val), name_(n), is_rest_argument_(rest), is_keyword_argument_(keyword), hash_(0) { if (!name_.empty() && is_rest_argument_) { coreError("variable-length argument may not be passed by name", pstate_); } } Argument::Argument(const Argument* ptr) : Expression(ptr), value_(ptr->value_), name_(ptr->name_), is_rest_argument_(ptr->is_rest_argument_), is_keyword_argument_(ptr->is_keyword_argument_), hash_(ptr->hash_) { if (!name_.empty() && is_rest_argument_) { coreError("variable-length argument may not be passed by name", pstate_); } } void Argument::set_delayed(bool delayed) { if (value_) value_->set_delayed(delayed); is_delayed(delayed); } bool Argument::operator==(const Expression& rhs) const { try { const Argument* m = Cast(&rhs); if (!(m && name() == m->name())) return false; return *value() == *m->value(); } catch (std::bad_cast&) { return false; } catch (...) { throw; } } size_t Argument::hash() const { if (hash_ == 0) { hash_ = std::hash()(name()); hash_combine(hash_, value()->hash()); } return hash_; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Arguments::Arguments(SourceSpan pstate) : Expression(pstate), Vectorized(), has_named_arguments_(false), has_rest_argument_(false), has_keyword_argument_(false) { } Arguments::Arguments(const Arguments* ptr) : Expression(ptr), Vectorized(*ptr), has_named_arguments_(ptr->has_named_arguments_), has_rest_argument_(ptr->has_rest_argument_), has_keyword_argument_(ptr->has_keyword_argument_) { } void Arguments::set_delayed(bool delayed) { for (Argument_Obj arg : elements()) { if (arg) arg->set_delayed(delayed); } is_delayed(delayed); } Argument_Obj Arguments::get_rest_argument() { if (this->has_rest_argument()) { for (Argument_Obj arg : this->elements()) { if (arg->is_rest_argument()) { return arg; } } } return {}; } Argument_Obj Arguments::get_keyword_argument() { if (this->has_keyword_argument()) { for (Argument_Obj arg : this->elements()) { if (arg->is_keyword_argument()) { return arg; } } } return {}; } void Arguments::adjust_after_pushing(Argument_Obj a) { if (!a->name().empty()) { if (has_keyword_argument()) { coreError("named arguments must precede variable-length argument", a->pstate()); } has_named_arguments(true); } else if (a->is_rest_argument()) { if (has_rest_argument()) { coreError("functions and mixins may only be called with one variable-length argument", a->pstate()); } if (has_keyword_argument_) { coreError("only keyword arguments may follow variable arguments", a->pstate()); } has_rest_argument(true); } else if (a->is_keyword_argument()) { if (has_keyword_argument()) { coreError("functions and mixins may only be called with one keyword argument", a->pstate()); } has_keyword_argument(true); } else { if (has_rest_argument()) { coreError("ordinal arguments must precede variable-length arguments", a->pstate()); } if (has_named_arguments()) { coreError("ordinal arguments must precede named arguments", a->pstate()); } } } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Media_Query::Media_Query(SourceSpan pstate, String_Obj t, size_t s, bool n, bool r) : Expression(pstate), Vectorized(s), media_type_(t), is_negated_(n), is_restricted_(r) { } Media_Query::Media_Query(const Media_Query* ptr) : Expression(ptr), Vectorized(*ptr), media_type_(ptr->media_type_), is_negated_(ptr->is_negated_), is_restricted_(ptr->is_restricted_) { } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Media_Query_Expression::Media_Query_Expression(SourceSpan pstate, ExpressionObj f, ExpressionObj v, bool i) : Expression(pstate), feature_(f), value_(v), is_interpolated_(i) { } Media_Query_Expression::Media_Query_Expression(const Media_Query_Expression* ptr) : Expression(ptr), feature_(ptr->feature_), value_(ptr->value_), is_interpolated_(ptr->is_interpolated_) { } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// At_Root_Query::At_Root_Query(SourceSpan pstate, ExpressionObj f, ExpressionObj v, bool i) : Expression(pstate), feature_(f), value_(v) { } At_Root_Query::At_Root_Query(const At_Root_Query* ptr) : Expression(ptr), feature_(ptr->feature_), value_(ptr->value_) { } bool At_Root_Query::exclude(sass::string str) { bool with = feature() && unquote(feature()->to_string()).compare("with") == 0; List* l = static_cast(value().ptr()); sass::string v; if (with) { if (!l || l->length() == 0) return str.compare("rule") != 0; for (size_t i = 0, L = l->length(); i < L; ++i) { v = unquote((*l)[i]->to_string()); if (v.compare("all") == 0 || v == str) return false; } return true; } else { if (!l || !l->length()) return str.compare("rule") == 0; for (size_t i = 0, L = l->length(); i < L; ++i) { v = unquote((*l)[i]->to_string()); if (v.compare("all") == 0 || v == str) return true; } return false; } } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// AtRootRule::AtRootRule(SourceSpan pstate, Block_Obj b, At_Root_Query_Obj e) : ParentStatement(pstate, b), expression_(e) { statement_type(ATROOT); } AtRootRule::AtRootRule(const AtRootRule* ptr) : ParentStatement(ptr), expression_(ptr->expression_) { statement_type(ATROOT); } bool AtRootRule::bubbles() { return true; } bool AtRootRule::exclude_node(Statement_Obj s) { if (expression() == nullptr) { return s->statement_type() == Statement::RULESET; } if (s->statement_type() == Statement::DIRECTIVE) { if (AtRuleObj dir = Cast(s)) { sass::string keyword(dir->keyword()); if (keyword.length() > 0) keyword.erase(0, 1); return expression()->exclude(keyword); } } if (s->statement_type() == Statement::MEDIA) { return expression()->exclude("media"); } if (s->statement_type() == Statement::RULESET) { return expression()->exclude("rule"); } if (s->statement_type() == Statement::SUPPORTS) { return expression()->exclude("supports"); } if (AtRuleObj dir = Cast(s)) { if (dir->is_keyframes()) return expression()->exclude("keyframes"); } return false; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Parameter::Parameter(SourceSpan pstate, sass::string n, ExpressionObj def, bool rest) : AST_Node(pstate), name_(n), default_value_(def), is_rest_parameter_(rest) { } Parameter::Parameter(const Parameter* ptr) : AST_Node(ptr), name_(ptr->name_), default_value_(ptr->default_value_), is_rest_parameter_(ptr->is_rest_parameter_) { } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// Parameters::Parameters(SourceSpan pstate) : AST_Node(pstate), Vectorized(), has_optional_parameters_(false), has_rest_parameter_(false) { } Parameters::Parameters(const Parameters* ptr) : AST_Node(ptr), Vectorized(*ptr), has_optional_parameters_(ptr->has_optional_parameters_), has_rest_parameter_(ptr->has_rest_parameter_) { } void Parameters::adjust_after_pushing(Parameter_Obj p) { if (p->default_value()) { if (has_rest_parameter()) { coreError("optional parameters may not be combined with variable-length parameters", p->pstate()); } has_optional_parameters(true); } else if (p->is_rest_parameter()) { if (has_rest_parameter()) { coreError("functions and mixins cannot have more than one variable-length parameter", p->pstate()); } has_rest_parameter(true); } else { if (has_rest_parameter()) { coreError("required parameters must precede variable-length parameters", p->pstate()); } if (has_optional_parameters()) { coreError("required parameters must precede optional parameters", p->pstate()); } } } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // If you forget to add a class here you will get // undefined reference to `vtable for Sass::Class' IMPLEMENT_AST_OPERATORS(StyleRule); IMPLEMENT_AST_OPERATORS(MediaRule); IMPLEMENT_AST_OPERATORS(CssMediaRule); IMPLEMENT_AST_OPERATORS(CssMediaQuery); IMPLEMENT_AST_OPERATORS(Import); IMPLEMENT_AST_OPERATORS(Import_Stub); IMPLEMENT_AST_OPERATORS(AtRule); IMPLEMENT_AST_OPERATORS(AtRootRule); IMPLEMENT_AST_OPERATORS(WhileRule); IMPLEMENT_AST_OPERATORS(EachRule); IMPLEMENT_AST_OPERATORS(ForRule); IMPLEMENT_AST_OPERATORS(If); IMPLEMENT_AST_OPERATORS(Mixin_Call); IMPLEMENT_AST_OPERATORS(ExtendRule); IMPLEMENT_AST_OPERATORS(Media_Query); IMPLEMENT_AST_OPERATORS(Media_Query_Expression); IMPLEMENT_AST_OPERATORS(DebugRule); IMPLEMENT_AST_OPERATORS(ErrorRule); IMPLEMENT_AST_OPERATORS(WarningRule); IMPLEMENT_AST_OPERATORS(Assignment); IMPLEMENT_AST_OPERATORS(Return); IMPLEMENT_AST_OPERATORS(At_Root_Query); IMPLEMENT_AST_OPERATORS(Comment); IMPLEMENT_AST_OPERATORS(Parameters); IMPLEMENT_AST_OPERATORS(Parameter); IMPLEMENT_AST_OPERATORS(Arguments); IMPLEMENT_AST_OPERATORS(Argument); IMPLEMENT_AST_OPERATORS(Unary_Expression); IMPLEMENT_AST_OPERATORS(Block); IMPLEMENT_AST_OPERATORS(Content); IMPLEMENT_AST_OPERATORS(Trace); IMPLEMENT_AST_OPERATORS(Keyframe_Rule); IMPLEMENT_AST_OPERATORS(Bubble); IMPLEMENT_AST_OPERATORS(Definition); IMPLEMENT_AST_OPERATORS(Declaration); ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// }