#ifndef SASS_OPERATION_H #define SASS_OPERATION_H // sass.hpp must go before all system headers to get the // __EXTENSIONS__ fix on Solaris. #include "sass.hpp" // base classes to implement curiously recurring template pattern (CRTP) // https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern #include #include #include "ast_fwd_decl.hpp" #include "ast_def_macros.hpp" namespace Sass { #define ATTACH_ABSTRACT_CRTP_PERFORM_METHODS()\ virtual void perform(Operation* op) = 0; \ virtual Value* perform(Operation* op) = 0; \ virtual sass::string perform(Operation* op) = 0; \ virtual AST_Node* perform(Operation* op) = 0; \ virtual Selector* perform(Operation* op) = 0; \ virtual Statement* perform(Operation* op) = 0; \ virtual Expression* perform(Operation* op) = 0; \ virtual union Sass_Value* perform(Operation* op) = 0; \ virtual SupportsCondition* perform(Operation* op) = 0; \ // you must add operators to every class // ensures `this` of actual instance type // we therefore call the specific operator // they are virtual so most specific is used #define ATTACH_CRTP_PERFORM_METHODS()\ virtual void perform(Operation* op) override { return (*op)(this); } \ virtual Value* perform(Operation* op) override { return (*op)(this); } \ virtual sass::string perform(Operation* op) override { return (*op)(this); } \ virtual AST_Node* perform(Operation* op) override { return (*op)(this); } \ virtual Selector* perform(Operation* op) override { return (*op)(this); } \ virtual Statement* perform(Operation* op) override { return (*op)(this); } \ virtual Expression* perform(Operation* op) override { return (*op)(this); } \ virtual union Sass_Value* perform(Operation* op) override { return (*op)(this); } \ virtual SupportsCondition* perform(Operation* op) override { return (*op)(this); } \ template class Operation { public: virtual T operator()(AST_Node* x) = 0; // statements virtual T operator()(Block* x) = 0; virtual T operator()(StyleRule* x) = 0; virtual T operator()(Bubble* x) = 0; virtual T operator()(Trace* x) = 0; virtual T operator()(SupportsRule* x) = 0; virtual T operator()(MediaRule* x) = 0; virtual T operator()(CssMediaRule* x) = 0; virtual T operator()(CssMediaQuery* x) = 0; virtual T operator()(AtRootRule* x) = 0; virtual T operator()(AtRule* x) = 0; virtual T operator()(Keyframe_Rule* x) = 0; virtual T operator()(Declaration* x) = 0; virtual T operator()(Assignment* x) = 0; virtual T operator()(Import* x) = 0; virtual T operator()(Import_Stub* x) = 0; virtual T operator()(WarningRule* x) = 0; virtual T operator()(ErrorRule* x) = 0; virtual T operator()(DebugRule* x) = 0; virtual T operator()(Comment* x) = 0; virtual T operator()(If* x) = 0; virtual T operator()(ForRule* x) = 0; virtual T operator()(EachRule* x) = 0; virtual T operator()(WhileRule* x) = 0; virtual T operator()(Return* x) = 0; virtual T operator()(Content* x) = 0; virtual T operator()(ExtendRule* x) = 0; virtual T operator()(Definition* x) = 0; virtual T operator()(Mixin_Call* x) = 0; // expressions virtual T operator()(Null* x) = 0; virtual T operator()(List* x) = 0; virtual T operator()(Map* x) = 0; virtual T operator()(Function* x) = 0; virtual T operator()(Binary_Expression* x) = 0; virtual T operator()(Unary_Expression* x) = 0; virtual T operator()(Function_Call* x) = 0; virtual T operator()(Custom_Warning* x) = 0; virtual T operator()(Custom_Error* x) = 0; virtual T operator()(Variable* x) = 0; virtual T operator()(Number* x) = 0; virtual T operator()(Color* x) = 0; virtual T operator()(Color_RGBA* x) = 0; virtual T operator()(Color_HSLA* x) = 0; virtual T operator()(Boolean* x) = 0; virtual T operator()(String_Schema* x) = 0; virtual T operator()(String_Quoted* x) = 0; virtual T operator()(String_Constant* x) = 0; virtual T operator()(SupportsCondition* x) = 0; virtual T operator()(SupportsOperation* x) = 0; virtual T operator()(SupportsNegation* x) = 0; virtual T operator()(SupportsDeclaration* x) = 0; virtual T operator()(Supports_Interpolation* x) = 0; virtual T operator()(Media_Query* x) = 0; virtual T operator()(Media_Query_Expression* x) = 0; virtual T operator()(At_Root_Query* x) = 0; virtual T operator()(Parent_Reference* x) = 0; // parameters and arguments virtual T operator()(Parameter* x) = 0; virtual T operator()(Parameters* x) = 0; virtual T operator()(Argument* x) = 0; virtual T operator()(Arguments* x) = 0; // selectors virtual T operator()(Selector_Schema* x) = 0; virtual T operator()(PlaceholderSelector* x) = 0; virtual T operator()(TypeSelector* x) = 0; virtual T operator()(ClassSelector* x) = 0; virtual T operator()(IDSelector* x) = 0; virtual T operator()(AttributeSelector* x) = 0; virtual T operator()(PseudoSelector* x) = 0; virtual T operator()(SelectorComponent* x) = 0; virtual T operator()(SelectorCombinator* x) = 0; virtual T operator()(CompoundSelector* x) = 0; virtual T operator()(ComplexSelector* x) = 0; virtual T operator()(SelectorList* x) = 0; }; // example: Operation_CRTP // T is the base return type of all visitors // D is the class derived visitor class // normally you want to implement all operators template class Operation_CRTP : public Operation { public: T operator()(AST_Node* x) { return static_cast(this)->fallback(x); } // statements T operator()(Block* x) { return static_cast(this)->fallback(x); } T operator()(StyleRule* x) { return static_cast(this)->fallback(x); } T operator()(Bubble* x) { return static_cast(this)->fallback(x); } T operator()(Trace* x) { return static_cast(this)->fallback(x); } T operator()(SupportsRule* x) { return static_cast(this)->fallback(x); } T operator()(MediaRule* x) { return static_cast(this)->fallback(x); } T operator()(CssMediaRule* x) { return static_cast(this)->fallback(x); } T operator()(CssMediaQuery* x) { return static_cast(this)->fallback(x); } T operator()(AtRootRule* x) { return static_cast(this)->fallback(x); } T operator()(AtRule* x) { return static_cast(this)->fallback(x); } T operator()(Keyframe_Rule* x) { return static_cast(this)->fallback(x); } T operator()(Declaration* x) { return static_cast(this)->fallback(x); } T operator()(Assignment* x) { return static_cast(this)->fallback(x); } T operator()(Import* x) { return static_cast(this)->fallback(x); } T operator()(Import_Stub* x) { return static_cast(this)->fallback(x); } T operator()(WarningRule* x) { return static_cast(this)->fallback(x); } T operator()(ErrorRule* x) { return static_cast(this)->fallback(x); } T operator()(DebugRule* x) { return static_cast(this)->fallback(x); } T operator()(Comment* x) { return static_cast(this)->fallback(x); } T operator()(If* x) { return static_cast(this)->fallback(x); } T operator()(ForRule* x) { return static_cast(this)->fallback(x); } T operator()(EachRule* x) { return static_cast(this)->fallback(x); } T operator()(WhileRule* x) { return static_cast(this)->fallback(x); } T operator()(Return* x) { return static_cast(this)->fallback(x); } T operator()(Content* x) { return static_cast(this)->fallback(x); } T operator()(ExtendRule* x) { return static_cast(this)->fallback(x); } T operator()(Definition* x) { return static_cast(this)->fallback(x); } T operator()(Mixin_Call* x) { return static_cast(this)->fallback(x); } // expressions T operator()(Null* x) { return static_cast(this)->fallback(x); } T operator()(List* x) { return static_cast(this)->fallback(x); } T operator()(Map* x) { return static_cast(this)->fallback(x); } T operator()(Function* x) { return static_cast(this)->fallback(x); } T operator()(Binary_Expression* x) { return static_cast(this)->fallback(x); } T operator()(Unary_Expression* x) { return static_cast(this)->fallback(x); } T operator()(Function_Call* x) { return static_cast(this)->fallback(x); } T operator()(Custom_Warning* x) { return static_cast(this)->fallback(x); } T operator()(Custom_Error* x) { return static_cast(this)->fallback(x); } T operator()(Variable* x) { return static_cast(this)->fallback(x); } T operator()(Number* x) { return static_cast(this)->fallback(x); } T operator()(Color* x) { return static_cast(this)->fallback(x); } T operator()(Color_RGBA* x) { return static_cast(this)->fallback(x); } T operator()(Color_HSLA* x) { return static_cast(this)->fallback(x); } T operator()(Boolean* x) { return static_cast(this)->fallback(x); } T operator()(String_Schema* x) { return static_cast(this)->fallback(x); } T operator()(String_Constant* x) { return static_cast(this)->fallback(x); } T operator()(String_Quoted* x) { return static_cast(this)->fallback(x); } T operator()(SupportsCondition* x) { return static_cast(this)->fallback(x); } T operator()(SupportsOperation* x) { return static_cast(this)->fallback(x); } T operator()(SupportsNegation* x) { return static_cast(this)->fallback(x); } T operator()(SupportsDeclaration* x) { return static_cast(this)->fallback(x); } T operator()(Supports_Interpolation* x) { return static_cast(this)->fallback(x); } T operator()(Media_Query* x) { return static_cast(this)->fallback(x); } T operator()(Media_Query_Expression* x) { return static_cast(this)->fallback(x); } T operator()(At_Root_Query* x) { return static_cast(this)->fallback(x); } T operator()(Parent_Reference* x) { return static_cast(this)->fallback(x); } // parameters and arguments T operator()(Parameter* x) { return static_cast(this)->fallback(x); } T operator()(Parameters* x) { return static_cast(this)->fallback(x); } T operator()(Argument* x) { return static_cast(this)->fallback(x); } T operator()(Arguments* x) { return static_cast(this)->fallback(x); } // selectors T operator()(Selector_Schema* x) { return static_cast(this)->fallback(x); } T operator()(PlaceholderSelector* x) { return static_cast(this)->fallback(x); } T operator()(TypeSelector* x) { return static_cast(this)->fallback(x); } T operator()(ClassSelector* x) { return static_cast(this)->fallback(x); } T operator()(IDSelector* x) { return static_cast(this)->fallback(x); } T operator()(AttributeSelector* x) { return static_cast(this)->fallback(x); } T operator()(PseudoSelector* x) { return static_cast(this)->fallback(x); } T operator()(SelectorComponent* x) { return static_cast(this)->fallback(x); } T operator()(SelectorCombinator* x) { return static_cast(this)->fallback(x); } T operator()(CompoundSelector* x) { return static_cast(this)->fallback(x); } T operator()(ComplexSelector* x) { return static_cast(this)->fallback(x); } T operator()(SelectorList* x) { return static_cast(this)->fallback(x); } // fallback with specific type U // will be called if not overloaded template inline T fallback(U x) { throw std::runtime_error( std::string(typeid(*this).name()) + ": CRTP not implemented for " + typeid(x).name()); } }; } #endif