Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

Commit

Permalink
Cleanup CRTP implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed Mar 17, 2018
1 parent 7cb696a commit aa7386f
Show file tree
Hide file tree
Showing 19 changed files with 133 additions and 172 deletions.
140 changes: 70 additions & 70 deletions src/ast.hpp

Large diffs are not rendered by default.

10 changes: 0 additions & 10 deletions src/ast_def_macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,6 @@ class LocalOption {
LocalOption<size_t> cnt_##name(name, name + 1); \
if (name > MAX_NESTING) throw Exception::NestingLimitError(pstate, traces); \

#define ATTACH_OPERATIONS()\
virtual void perform(Operation<void>* op) { (*op)(this); }\
virtual AST_Node_Ptr perform(Operation<AST_Node_Ptr>* op) { return (*op)(this); }\
virtual Statement_Ptr perform(Operation<Statement_Ptr>* op) { return (*op)(this); }\
virtual Expression_Ptr perform(Operation<Expression_Ptr>* op) { return (*op)(this); }\
virtual Selector_Ptr perform(Operation<Selector_Ptr>* op) { return (*op)(this); }\
virtual std::string perform(Operation<std::string>* op) { return (*op)(this); }\
virtual union Sass_Value* perform(Operation<union Sass_Value*>* op) { return (*op)(this); }\
virtual Value_Ptr perform(Operation<Value_Ptr>* op) { return (*op)(this); }

#define ADD_PROPERTY(type, name)\
protected:\
type name##_;\
Expand Down
7 changes: 0 additions & 7 deletions src/check_nesting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,6 @@ namespace Sass {
return i;
}

Statement_Ptr CheckNesting::fallback_impl(Statement_Ptr s)
{
Block_Ptr b1 = Cast<Block>(s);
Has_Block_Ptr b2 = Cast<Has_Block>(s);
return b1 || b2 ? visit_children(s) : s;
}

bool CheckNesting::should_visit(Statement_Ptr node)
{
if (!this->parent) return true;
Expand Down
11 changes: 6 additions & 5 deletions src/check_nesting.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ namespace Sass {
Statement_Ptr parent;
Definition_Ptr current_mixin_definition;

Statement_Ptr fallback_impl(Statement_Ptr);
Statement_Ptr before(Statement_Ptr);
Statement_Ptr visit_children(Statement_Ptr);

Expand All @@ -27,11 +26,13 @@ namespace Sass {

template <typename U>
Statement_Ptr fallback(U x) {
Statement_Ptr n = Cast<Statement>(x);
if (this->should_visit(n)) {
return fallback_impl(n);
Statement_Ptr s = Cast<Statement>(x);
if (s && this->should_visit(s)) {
Block_Ptr b1 = Cast<Block>(s);
Has_Block_Ptr b2 = Cast<Has_Block>(s);
if (b1 || b2) return visit_children(s);
}
return NULL;
return s;
}

private:
Expand Down
5 changes: 0 additions & 5 deletions src/cssize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,11 +509,6 @@ namespace Sass {
return flatten(result);
}

Statement_Ptr Cssize::fallback_impl(AST_Node_Ptr n)
{
return static_cast<Statement_Ptr>(n);
}

void Cssize::append_block(Block_Ptr b, Block_Ptr cur)
{
for (size_t i = 0, L = b->length(); i < L; ++i) {
Expand Down
6 changes: 3 additions & 3 deletions src/cssize.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ namespace Sass {
BlockStack block_stack;
std::vector<Statement_Ptr> p_stack;

Statement_Ptr fallback_impl(AST_Node_Ptr n);

public:
Cssize(Context&);
~Cssize() { }
Expand Down Expand Up @@ -66,8 +64,10 @@ namespace Sass {
List_Ptr merge_media_queries(Media_Block_Ptr, Media_Block_Ptr);
Media_Query_Ptr merge_media_query(Media_Query_Ptr, Media_Query_Ptr);

// generic fallback
template <typename U>
Statement_Ptr fallback(U x) { return fallback_impl(x); }
Statement_Ptr fallback(U x)
{ return Cast<Statement>(x); }

void append_block(Block_Ptr, Block_Ptr);
};
Expand Down
5 changes: 0 additions & 5 deletions src/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1467,11 +1467,6 @@ namespace Sass {
return 0;
}

inline Expression_Ptr Eval::fallback_impl(AST_Node_Ptr n)
{
return static_cast<Expression_Ptr>(n);
}

// All the binary helpers.

Expression_Ptr cval_to_astnode(union Sass_Value* v, Backtraces traces, ParserState pstate)
Expand Down
20 changes: 11 additions & 9 deletions src/eval.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ namespace Sass {

class Eval : public Operation_CRTP<Expression_Ptr, Eval> {

private:
Expression_Ptr fallback_impl(AST_Node_Ptr n);

public:
Expand& exp;
Context& ctx;
Expand Down Expand Up @@ -78,18 +75,23 @@ namespace Sass {
Compound_Selector_Ptr operator()(Compound_Selector_Ptr);
Simple_Selector_Ptr operator()(Simple_Selector_Ptr s);
Wrapped_Selector_Ptr operator()(Wrapped_Selector_Ptr s);

// they don't have any specific implementation (yet)
// Element_Selector_Ptr operator()(Element_Selector_Ptr s) { return s; };
// Pseudo_Selector_Ptr operator()(Pseudo_Selector_Ptr s) { return s; };
// Class_Selector_Ptr operator()(Class_Selector_Ptr s) { return s; };
// Id_Selector_Ptr operator()(Id_Selector_Ptr s) { return s; };
// Placeholder_Selector_Ptr operator()(Placeholder_Selector_Ptr s) { return s; };
Id_Selector_Ptr operator()(Id_Selector_Ptr s) { return s; };
Class_Selector_Ptr operator()(Class_Selector_Ptr s) { return s; };
Pseudo_Selector_Ptr operator()(Pseudo_Selector_Ptr s) { return s; };
Element_Selector_Ptr operator()(Element_Selector_Ptr s) { return s; };
Attribute_Selector_Ptr operator()(Attribute_Selector_Ptr s) { return s; };
Placeholder_Selector_Ptr operator()(Placeholder_Selector_Ptr s) { return s; };

// actual evaluated selectors
Selector_List_Ptr operator()(Selector_Schema_Ptr);
Expression_Ptr operator()(Parent_Selector_Ptr);

// generic fallback
template <typename U>
Expression_Ptr fallback(U x) { return fallback_impl(x); }
Expression_Ptr fallback(U x)
{ return Cast<Expression>(x); }

private:
void interpolation(Context& ctx, std::string& res, Expression_Obj ex, bool into_quotes, bool was_itpl = false);
Expand Down
9 changes: 0 additions & 9 deletions src/expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,15 +792,6 @@ namespace Sass {
return trace.detach();
}

// produce an error if something is not implemented
inline Statement_Ptr Expand::fallback_impl(AST_Node_Ptr n)
{
std::string err =std:: string("`Expand` doesn't handle ") + typeid(*n).name();
String_Quoted_Obj msg = SASS_MEMORY_NEW(String_Quoted, ParserState("[WARN]"), err);
error("unknown internal error; please contact the LibSass maintainers", n->pstate(), traces);
return SASS_MEMORY_NEW(Warning, ParserState("[WARN]"), msg);
}

// process and add to last block on stack
inline void Expand::append_block(Block_Ptr b)
{
Expand Down
6 changes: 1 addition & 5 deletions src/expand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ namespace Sass {

Boolean_Obj bool_true;

Statement_Ptr fallback_impl(AST_Node_Ptr n);

private:
void expand_selector_list(Selector_Obj, Selector_List_Obj extender);

Expand Down Expand Up @@ -71,10 +69,8 @@ namespace Sass {
Statement_Ptr operator()(Mixin_Call_Ptr);
Statement_Ptr operator()(Content_Ptr);

template <typename U>
Statement_Ptr fallback(U x) { return fallback_impl(x); }

void append_block(Block_Ptr);

};

}
Expand Down
6 changes: 3 additions & 3 deletions src/extend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ namespace Sass {
Subset_Map& subset_map;
Eval* eval;

void fallback_impl(AST_Node_Ptr n) { }

private:

std::unordered_map<
Expand Down Expand Up @@ -77,8 +75,10 @@ namespace Sass {
void operator()(Media_Block_Ptr);
void operator()(Directive_Ptr);

// ignore missed types
template <typename U>
void fallback(U x) { return fallback_impl(x); }
void fallback(U x) {}

};

}
Expand Down
4 changes: 0 additions & 4 deletions src/inspect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1131,8 +1131,4 @@ namespace Sass {

}

void Inspect::fallback_impl(AST_Node_Ptr n)
{
}

}
4 changes: 0 additions & 4 deletions src/inspect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ namespace Sass {
// import all the class-specific methods and override as desired
using Operation_CRTP<void, Inspect>::operator();

void fallback_impl(AST_Node_Ptr n);

public:

Inspect(const Emitter& emi);
Expand Down Expand Up @@ -95,8 +93,6 @@ namespace Sass {
virtual std::string lbracket(List_Ptr);
virtual std::string rbracket(List_Ptr);

// template <typename U>
// void fallback(U x) { fallback_impl(reinterpret_cast<AST_Node_Ptr>(x)); }
};

}
Expand Down
5 changes: 0 additions & 5 deletions src/listize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,4 @@ namespace Sass {
return l.detach();
}

Expression_Ptr Listize::fallback_impl(AST_Node_Ptr n)
{
return Cast<Expression>(n);
}

}
6 changes: 3 additions & 3 deletions src/listize.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ namespace Sass {

class Listize : public Operation_CRTP<Expression_Ptr, Listize> {

Expression_Ptr fallback_impl(AST_Node_Ptr n);

public:
Listize();
~Listize() { }
Expand All @@ -25,8 +23,10 @@ namespace Sass {
Expression_Ptr operator()(Complex_Selector_Ptr);
Expression_Ptr operator()(Compound_Selector_Ptr);

// generic fallback
template <typename U>
Expression_Ptr fallback(U x) { return fallback_impl(x); }
Expression_Ptr fallback(U x)
{ return Cast<Expression>(x); }
};

}
Expand Down
44 changes: 34 additions & 10 deletions src/operation.hpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
#ifndef SASS_OPERATION_H
#define SASS_OPERATION_H

// base classes to implement curiously recurring template pattern (CRTP)
// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

#include "ast_fwd_decl.hpp"
#include "ast_def_macros.hpp"

namespace Sass {

// 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<void>* op) { return (*op)(this); } \
virtual Value_Ptr perform(Operation<Value_Ptr>* op) { return (*op)(this); } \
virtual std::string perform(Operation<std::string>* op) { return (*op)(this); } \
virtual AST_Node_Ptr perform(Operation<AST_Node_Ptr>* op) { return (*op)(this); } \
virtual Selector_Ptr perform(Operation<Selector_Ptr>* op) { return (*op)(this); } \
virtual Statement_Ptr perform(Operation<Statement_Ptr>* op) { return (*op)(this); } \
virtual Expression_Ptr perform(Operation<Expression_Ptr>* op) { return (*op)(this); } \
virtual union Sass_Value* perform(Operation<union Sass_Value*>* op) { return (*op)(this); } \
virtual Supports_Condition_Ptr perform(Operation<Supports_Condition_Ptr>* op) { return (*op)(this); } \

template<typename T>
class Operation {
public:
virtual T operator()(AST_Node_Ptr x) = 0;
virtual ~Operation() { }
// statements
virtual T operator()(Block_Ptr x) = 0;
virtual T operator()(Ruleset_Ptr x) = 0;
Expand Down Expand Up @@ -38,6 +56,7 @@ namespace Sass {
virtual T operator()(Definition_Ptr x) = 0;
virtual T operator()(Mixin_Call_Ptr x) = 0;
// expressions
virtual T operator()(Null_Ptr x) = 0;
virtual T operator()(List_Ptr x) = 0;
virtual T operator()(Map_Ptr x) = 0;
virtual T operator()(Function_Ptr x) = 0;
Expand All @@ -62,7 +81,6 @@ namespace Sass {
virtual T operator()(Media_Query_Ptr x) = 0;
virtual T operator()(Media_Query_Expression_Ptr x) = 0;
virtual T operator()(At_Root_Query_Ptr x) = 0;
virtual T operator()(Null_Ptr x) = 0;
virtual T operator()(Parent_Selector_Ptr x) = 0;
// parameters and arguments
virtual T operator()(Parameter_Ptr x) = 0;
Expand All @@ -81,15 +99,14 @@ namespace Sass {
virtual T operator()(Compound_Selector_Ptr x)= 0;
virtual T operator()(Complex_Selector_Ptr x) = 0;
virtual T operator()(Selector_List_Ptr x) = 0;

template <typename U>
T fallback(U x) { return T(); }
};

// example: Operation_CRTP<Expression_Ptr, Eval>
// T is the base return type of all visitors
// D is the class derived visitor class
// normaly you want to implement all operators
template <typename T, typename D>
class Operation_CRTP : public Operation<T> {
public:
D& impl() { return static_cast<D&>(*this); }
public:
T operator()(AST_Node_Ptr x) { return static_cast<D*>(this)->fallback(x); }
// statements
Expand Down Expand Up @@ -120,6 +137,7 @@ namespace Sass {
T operator()(Definition_Ptr x) { return static_cast<D*>(this)->fallback(x); }
T operator()(Mixin_Call_Ptr x) { return static_cast<D*>(this)->fallback(x); }
// expressions
T operator()(Null_Ptr x) { return static_cast<D*>(this)->fallback(x); }
T operator()(List_Ptr x) { return static_cast<D*>(this)->fallback(x); }
T operator()(Map_Ptr x) { return static_cast<D*>(this)->fallback(x); }
T operator()(Function_Ptr x) { return static_cast<D*>(this)->fallback(x); }
Expand All @@ -144,7 +162,6 @@ namespace Sass {
T operator()(Media_Query_Ptr x) { return static_cast<D*>(this)->fallback(x); }
T operator()(Media_Query_Expression_Ptr x) { return static_cast<D*>(this)->fallback(x); }
T operator()(At_Root_Query_Ptr x) { return static_cast<D*>(this)->fallback(x); }
T operator()(Null_Ptr x) { return static_cast<D*>(this)->fallback(x); }
T operator()(Parent_Selector_Ptr x) { return static_cast<D*>(this)->fallback(x); }
// parameters and arguments
T operator()(Parameter_Ptr x) { return static_cast<D*>(this)->fallback(x); }
Expand All @@ -164,8 +181,15 @@ namespace Sass {
T operator()(Complex_Selector_Ptr x) { return static_cast<D*>(this)->fallback(x); }
T operator()(Selector_List_Ptr x) { return static_cast<D*>(this)->fallback(x); }

template <typename U>
T fallback(U x) { return T(); }
// fallback with specific type U
// will be called if not overloaded
template <typename U> T fallback(U x)
{
std::string msg(typeid(*this).name());
msg += ": CRTP not implemented for ";
throw std::runtime_error(msg + typeid(*x).name());
}

};

}
Expand Down
5 changes: 2 additions & 3 deletions src/remove_placeholders.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ namespace Sass {

class Remove_Placeholders : public Operation_CRTP<void, Remove_Placeholders> {

void fallback_impl(AST_Node_Ptr n) {}

public:
Selector_List_Ptr remove_placeholders(Selector_List_Ptr);

Expand All @@ -26,8 +24,9 @@ namespace Sass {
void operator()(Supports_Block_Ptr);
void operator()(Directive_Ptr);

// ignore missed types
template <typename U>
void fallback(U x) { return fallback_impl(x); }
void fallback(U x) {}
};

}
Expand Down
7 changes: 0 additions & 7 deletions src/to_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@

namespace Sass {

Value_Ptr To_Value::fallback_impl(AST_Node_Ptr n)
{
// throw a runtime error if this happens
// we want a well defined set of possible nodes
throw std::runtime_error("invalid node for to_value");
}

// Custom_Error is a valid value
Value_Ptr To_Value::operator()(Custom_Error_Ptr e)
{
Expand Down
Loading

0 comments on commit aa7386f

Please sign in to comment.