diff --git a/src/ast.cpp b/src/ast.cpp index e38a5e5cb..f03eb9ccc 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -2108,6 +2108,44 @@ namespace Sass { } } + Function_Call::Function_Call(ParserState pstate, std::string n, Arguments_Obj args, void* cookie) + : PreValue(pstate), sname_(SASS_MEMORY_NEW(String_Constant, pstate, n)), arguments_(args), func_(0), via_call_(false), cookie_(cookie), hash_(0) + { concrete_type(FUNCTION); } + Function_Call::Function_Call(ParserState pstate, std::string n, Arguments_Obj args, Function_Obj func) + : PreValue(pstate), sname_(SASS_MEMORY_NEW(String_Constant, pstate, n)), arguments_(args), func_(func), via_call_(false), cookie_(0), hash_(0) + { concrete_type(FUNCTION); } + Function_Call::Function_Call(ParserState pstate, std::string n, Arguments_Obj args) + : PreValue(pstate), sname_(SASS_MEMORY_NEW(String_Constant, pstate, n)), arguments_(args), via_call_(false), cookie_(0), hash_(0) + { concrete_type(FUNCTION); } + + bool Function_Call::operator==(const Expression& rhs) const + { + try + { + Function_Call_Ptr_Const m = Cast(&rhs); + if (!(m && *sname() == *m->sname())) return false; + if (!(m && arguments()->length() == m->arguments()->length())) return false; + for (size_t i =0, L = arguments()->length(); i < L; ++i) + if (!(*(*arguments())[i] == *(*m->arguments())[i])) return false; + return true; + } + catch (std::bad_cast&) + { + return false; + } + catch (...) { throw; } + } + + size_t Function_Call::hash() + { + if (hash_ == 0) { + hash_ = std::hash()(name()); + for (auto argument : arguments()->elements()) + hash_combine(hash_, argument->hash()); + } + return hash_; + } + ////////////////////////////////////////////////////////////////////////////////////////// // Convert map to (key, value) list. ////////////////////////////////////////////////////////////////////////////////////////// @@ -2181,7 +2219,6 @@ namespace Sass { IMPLEMENT_AST_OPERATORS(Arguments); IMPLEMENT_AST_OPERATORS(Argument); IMPLEMENT_AST_OPERATORS(Unary_Expression); - IMPLEMENT_AST_OPERATORS(Function_Call_Schema); IMPLEMENT_AST_OPERATORS(Block); IMPLEMENT_AST_OPERATORS(Content); IMPLEMENT_AST_OPERATORS(Trace); diff --git a/src/ast.hpp b/src/ast.hpp index ae79d785d..f7874b36e 100644 --- a/src/ast.hpp +++ b/src/ast.hpp @@ -81,6 +81,12 @@ namespace Sass { : pstate_(ptr->pstate_) { } + // allow implicit conversion to string + // needed for by SharedPtr implementation + operator std::string() { + return to_string(); + } + // AST_Node(AST_Node& ptr) = delete; virtual ~AST_Node() = 0; @@ -1429,25 +1435,34 @@ namespace Sass { // Function calls. ////////////////// class Function_Call : public PreValue { - HASH_CONSTREF(std::string, name) + HASH_CONSTREF(String_Obj, sname) HASH_PROPERTY(Arguments_Obj, arguments) HASH_PROPERTY(Function_Obj, func) ADD_PROPERTY(bool, via_call) ADD_PROPERTY(void*, cookie) size_t hash_; public: - Function_Call(ParserState pstate, std::string n, Arguments_Obj args, void* cookie) - : PreValue(pstate), name_(n), arguments_(args), func_(0), via_call_(false), cookie_(cookie), hash_(0) + Function_Call(ParserState pstate, std::string n, Arguments_Obj args, void* cookie); + Function_Call(ParserState pstate, std::string n, Arguments_Obj args, Function_Obj func); + Function_Call(ParserState pstate, std::string n, Arguments_Obj args); + + Function_Call(ParserState pstate, String_Obj n, Arguments_Obj args, void* cookie) + : PreValue(pstate), sname_(n), arguments_(args), func_(0), via_call_(false), cookie_(cookie), hash_(0) { concrete_type(FUNCTION); } - Function_Call(ParserState pstate, std::string n, Arguments_Obj args, Function_Obj func) - : PreValue(pstate), name_(n), arguments_(args), func_(func), via_call_(false), cookie_(0), hash_(0) + Function_Call(ParserState pstate, String_Obj n, Arguments_Obj args, Function_Obj func) + : PreValue(pstate), sname_(n), arguments_(args), func_(func), via_call_(false), cookie_(0), hash_(0) { concrete_type(FUNCTION); } - Function_Call(ParserState pstate, std::string n, Arguments_Obj args) - : PreValue(pstate), name_(n), arguments_(args), via_call_(false), cookie_(0), hash_(0) + Function_Call(ParserState pstate, String_Obj n, Arguments_Obj args) + : PreValue(pstate), sname_(n), arguments_(args), via_call_(false), cookie_(0), hash_(0) { concrete_type(FUNCTION); } + + std::string name() { + return sname(); + } + Function_Call(const Function_Call* ptr) : PreValue(ptr), - name_(ptr->name_), + sname_(ptr->sname_), arguments_(ptr->arguments_), func_(ptr->func_), via_call_(ptr->via_call_), @@ -1460,53 +1475,11 @@ namespace Sass { return false; } - virtual bool operator==(const Expression& rhs) const - { - try - { - Function_Call_Ptr_Const m = Cast(&rhs); - if (!(m && name() == m->name())) return false; - if (!(m && arguments()->length() == m->arguments()->length())) return false; - for (size_t i =0, L = arguments()->length(); i < L; ++i) - if (!(*(*arguments())[i] == *(*m->arguments())[i])) return false; - return true; - } - catch (std::bad_cast&) - { - return false; - } - catch (...) { throw; } - } + virtual bool operator==(const Expression& rhs) const; - virtual size_t hash() - { - if (hash_ == 0) { - hash_ = std::hash()(name()); - for (auto argument : arguments()->elements()) - hash_combine(hash_, argument->hash()); - } - return hash_; - } - ATTACH_AST_OPERATIONS(Function_Call) - ATTACH_CRTP_PERFORM_METHODS() - }; + virtual size_t hash(); - ///////////////////////// - // Function call schemas. - ///////////////////////// - class Function_Call_Schema : public Expression { - ADD_PROPERTY(String_Obj, name) - ADD_PROPERTY(Arguments_Obj, arguments) - public: - Function_Call_Schema(ParserState pstate, String_Obj n, Arguments_Obj args) - : Expression(pstate), name_(n), arguments_(args) - { concrete_type(STRING); } - Function_Call_Schema(const Function_Call_Schema* ptr) - : Expression(ptr), - name_(ptr->name_), - arguments_(ptr->arguments_) - { concrete_type(STRING); } - ATTACH_AST_OPERATIONS(Function_Call_Schema) + ATTACH_AST_OPERATIONS(Function_Call) ATTACH_CRTP_PERFORM_METHODS() }; diff --git a/src/ast_fwd_decl.hpp b/src/ast_fwd_decl.hpp index e4037865f..6176233b9 100644 --- a/src/ast_fwd_decl.hpp +++ b/src/ast_fwd_decl.hpp @@ -149,9 +149,6 @@ namespace Sass { class Function_Call; typedef Function_Call* Function_Call_Ptr; typedef Function_Call const* Function_Call_Ptr_Const; - class Function_Call_Schema; - typedef Function_Call_Schema* Function_Call_Schema_Ptr; - typedef Function_Call_Schema const* Function_Call_Schema_Ptr_Const; class Custom_Warning; typedef Custom_Warning* Custom_Warning_Ptr; typedef Custom_Warning const* Custom_Warning_Ptr_Const; @@ -319,7 +316,6 @@ namespace Sass { IMPL_MEM_OBJ(Binary_Expression); IMPL_MEM_OBJ(Unary_Expression); IMPL_MEM_OBJ(Function_Call); - IMPL_MEM_OBJ(Function_Call_Schema); IMPL_MEM_OBJ(Custom_Warning); IMPL_MEM_OBJ(Custom_Error); IMPL_MEM_OBJ(Variable); diff --git a/src/debugger.hpp b/src/debugger.hpp index ee0d6eba7..40186140e 100644 --- a/src/debugger.hpp +++ b/src/debugger.hpp @@ -497,14 +497,6 @@ inline void debug_ast(AST_Node_Ptr node, std::string ind, Env* env) std::cerr << " [" << expression->name() << "]" << std::endl; std::string name(expression->name()); if (env && env->has(name)) debug_ast(Cast((*env)[name]), ind + " -> ", env); - } else if (Cast(node)) { - Function_Call_Schema_Ptr expression = Cast(node); - std::cerr << ind << "Function_Call_Schema " << expression; - std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; - std::cerr << " (" << pstate_source_position(node) << ")"; - std::cerr << "" << std::endl; - debug_ast(expression->name(), ind + "name: ", env); - debug_ast(expression->arguments(), ind + " args: ", env); } else if (Cast(node)) { Function_Call_Ptr expression = Cast(node); std::cerr << ind << "Function_Call " << expression; diff --git a/src/eval.cpp b/src/eval.cpp index 585b56d6a..c5f514fd9 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -931,8 +931,18 @@ namespace Sass { stm << "Stack depth exceeded max of " << Constants::MaxCallStack; error(stm.str(), c->pstate(), traces); } + + if (Cast(c->sname())) { + Expression_Ptr evaluated_name = c->sname()->perform(this); + Expression_Ptr evaluated_args = c->arguments()->perform(this); + std::string str(evaluated_name->to_string()); + str += evaluated_args->to_string(); + return SASS_MEMORY_NEW(String_Constant, c->pstate(), str); + } + std::string name(Util::normalize_underscores(c->name())); std::string full_name(name + "[f]"); + // we make a clone here, need to implement that further Arguments_Obj args = c->arguments(); @@ -1090,16 +1100,6 @@ namespace Sass { return result.detach(); } - Expression_Ptr Eval::operator()(Function_Call_Schema_Ptr s) - { - Expression_Ptr evaluated_name = s->name()->perform(this); - Expression_Ptr evaluated_args = s->arguments()->perform(this); - String_Schema_Obj ss = SASS_MEMORY_NEW(String_Schema, s->pstate(), 2); - ss->append(evaluated_name); - ss->append(evaluated_args); - return ss->perform(this); - } - Expression_Ptr Eval::operator()(Variable_Ptr v) { Expression_Obj value = 0; diff --git a/src/eval.hpp b/src/eval.hpp index a0cb97aae..76bbb91e9 100644 --- a/src/eval.hpp +++ b/src/eval.hpp @@ -48,7 +48,6 @@ namespace Sass { Expression_Ptr operator()(Binary_Expression_Ptr); Expression_Ptr operator()(Unary_Expression_Ptr); Expression_Ptr operator()(Function_Call_Ptr); - Expression_Ptr operator()(Function_Call_Schema_Ptr); Expression_Ptr operator()(Variable_Ptr); Expression_Ptr operator()(Number_Ptr); Expression_Ptr operator()(Color_Ptr); diff --git a/src/inspect.cpp b/src/inspect.cpp index c82ae0757..a83ed25a6 100644 --- a/src/inspect.cpp +++ b/src/inspect.cpp @@ -513,12 +513,6 @@ namespace Sass { call->arguments()->perform(this); } - void Inspect::operator()(Function_Call_Schema_Ptr call) - { - call->name()->perform(this); - call->arguments()->perform(this); - } - void Inspect::operator()(Variable_Ptr var) { append_token(var->name(), var); diff --git a/src/inspect.hpp b/src/inspect.hpp index 8f5e8af76..774290d3f 100644 --- a/src/inspect.hpp +++ b/src/inspect.hpp @@ -51,7 +51,6 @@ namespace Sass { virtual void operator()(Binary_Expression_Ptr); virtual void operator()(Unary_Expression_Ptr); virtual void operator()(Function_Call_Ptr); - virtual void operator()(Function_Call_Schema_Ptr); // virtual void operator()(Custom_Warning_Ptr); // virtual void operator()(Custom_Error_Ptr); virtual void operator()(Variable_Ptr); diff --git a/src/memory/SharedPtr.hpp b/src/memory/SharedPtr.hpp index f20dfa39b..7e13bf06c 100644 --- a/src/memory/SharedPtr.hpp +++ b/src/memory/SharedPtr.hpp @@ -78,6 +78,9 @@ namespace Sass { static void setTaint(bool val) { taint = val; } + + virtual const std::string to_string() const = 0; + virtual ~SharedObj(); long getRefCount() { return refcounter; @@ -169,6 +172,14 @@ namespace Sass { } return *this; } + + // allow implicit conversion to string + // relies on base class implementation + operator const std::string() const { + if (node) return node->to_string(); + else return std::string("[NULLPTR]"); + } + ~SharedImpl() {}; public: operator T*() const { diff --git a/src/operation.hpp b/src/operation.hpp index 02e604ac6..92bb44680 100644 --- a/src/operation.hpp +++ b/src/operation.hpp @@ -63,7 +63,6 @@ namespace Sass { virtual T operator()(Binary_Expression_Ptr x) = 0; virtual T operator()(Unary_Expression_Ptr x) = 0; virtual T operator()(Function_Call_Ptr x) = 0; - virtual T operator()(Function_Call_Schema_Ptr x) = 0; virtual T operator()(Custom_Warning_Ptr x) = 0; virtual T operator()(Custom_Error_Ptr x) = 0; virtual T operator()(Variable_Ptr x) = 0; @@ -144,7 +143,6 @@ namespace Sass { T operator()(Binary_Expression_Ptr x) { return static_cast(this)->fallback(x); } T operator()(Unary_Expression_Ptr x) { return static_cast(this)->fallback(x); } T operator()(Function_Call_Ptr x) { return static_cast(this)->fallback(x); } - T operator()(Function_Call_Schema_Ptr x) { return static_cast(this)->fallback(x); } T operator()(Custom_Warning_Ptr x) { return static_cast(this)->fallback(x); } T operator()(Custom_Error_Ptr x) { return static_cast(this)->fallback(x); } T operator()(Variable_Ptr x) { return static_cast(this)->fallback(x); } diff --git a/src/parser.cpp b/src/parser.cpp index 525f199d1..5b1fd81ed 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2179,13 +2179,13 @@ namespace Sass { return SASS_MEMORY_NEW(Function_Call, call_pos, name, args); } - Function_Call_Schema_Obj Parser::parse_function_call_schema() + Function_Call_Obj Parser::parse_function_call_schema() { String_Obj name = parse_identifier_schema(); ParserState source_position_of_call = pstate; Arguments_Obj args = parse_arguments(); - return SASS_MEMORY_NEW(Function_Call_Schema, source_position_of_call, name, args); + return SASS_MEMORY_NEW(Function_Call, source_position_of_call, name, args); } Content_Obj Parser::parse_content_directive() diff --git a/src/parser.hpp b/src/parser.hpp index 83c7f34ba..31bac8dd7 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -285,7 +285,7 @@ namespace Sass { Expression_Obj parse_value(); Function_Call_Obj parse_calc_function(); Function_Call_Obj parse_function_call(); - Function_Call_Schema_Obj parse_function_call_schema(); + Function_Call_Obj parse_function_call_schema(); String_Obj parse_url_function_string(); String_Obj parse_url_function_argument(); String_Obj parse_interpolated_chunk(Token, bool constant = false, bool css = true);