diff --git a/src/ast.hpp b/src/ast.hpp index a2be8685c..07728103e 100644 --- a/src/ast.hpp +++ b/src/ast.hpp @@ -944,7 +944,6 @@ namespace Sass { // by a type tag. ///////////////////////////////////////////////////////////////////////////// struct Backtrace; - typedef const char* Signature; typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtraces, std::vector); class Definition : public Has_Block { public: diff --git a/src/ast_fwd_decl.hpp b/src/ast_fwd_decl.hpp index 5145a092b..4a3ff69b1 100644 --- a/src/ast_fwd_decl.hpp +++ b/src/ast_fwd_decl.hpp @@ -419,8 +419,14 @@ namespace Sass { typedef std::set CompoundSelectorSet; typedef std::unordered_set SimpleSelectorDict; + typedef std::vector BlockStack; + typedef std::vector CallStack; + typedef std::vector MediaStack; + typedef std::vector SelectorStack; typedef std::vector* ImporterStack; + typedef const char* Signature; + // only to switch implementations for testing #define environment_map std::map diff --git a/src/context.cpp b/src/context.cpp index dae2cbd75..272b99cb1 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -29,6 +29,7 @@ #include "sass2scss.h" #include "prelexer.hpp" #include "emitter.hpp" +#include "fn_utils.hpp" namespace Sass { using namespace Constants; diff --git a/src/fn_utils.cpp b/src/fn_utils.cpp index e069240d1..47ec759a4 100644 --- a/src/fn_utils.cpp +++ b/src/fn_utils.cpp @@ -1,10 +1,153 @@ #include "sass.hpp" +#include "parser.hpp" #include "fn_utils.hpp" +#include "functions.hpp" +#include "error_handling.hpp" namespace Sass { + Definition_Ptr make_native_function(Signature sig, Native_Function func, Context& ctx) + { + Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[built-in function]")); + sig_parser.lex(); + std::string name(Util::normalize_underscores(sig_parser.lexed)); + Parameters_Obj params = sig_parser.parse_parameters(); + return SASS_MEMORY_NEW(Definition, + ParserState("[built-in function]"), + sig, + name, + params, + func, + false); + } + + Definition_Ptr make_c_function(Sass_Function_Entry c_func, Context& ctx) + { + using namespace Prelexer; + + const char* sig = sass_function_get_signature(c_func); + Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[c function]")); + // allow to overload generic callback plus @warn, @error and @debug with custom functions + sig_parser.lex < alternatives < identifier, exactly <'*'>, + exactly < Constants::warn_kwd >, + exactly < Constants::error_kwd >, + exactly < Constants::debug_kwd > + > >(); + std::string name(Util::normalize_underscores(sig_parser.lexed)); + Parameters_Obj params = sig_parser.parse_parameters(); + return SASS_MEMORY_NEW(Definition, + ParserState("[c function]"), + sig, + name, + params, + c_func, + false, true); + } + namespace Functions { + Map_Ptr get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) + { + // Minimal error handling -- the expectation is that built-ins will be written correctly! + Map_Ptr val = Cast(env[argname]); + if (val) return val; + + List_Ptr lval = Cast(env[argname]); + if (lval && lval->length() == 0) return SASS_MEMORY_NEW(Map, pstate, 0); + + // fallback on get_arg for error handling + val = get_arg(argname, env, sig, pstate, traces); + return val; + } + + double get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, double lo, double hi) + { + // Minimal error handling -- the expectation is that built-ins will be written correctly! + Number_Ptr val = get_arg(argname, env, sig, pstate, traces); + Number tmpnr(val); + tmpnr.reduce(); + double v = tmpnr.value(); + if (!(lo <= v && v <= hi)) { + std::stringstream msg; + msg << "argument `" << argname << "` of `" << sig << "` must be between "; + msg << lo << " and " << hi; + error(msg.str(), pstate, traces); + } + return v; + } + + Number_Ptr get_arg_n(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) + { + Number_Ptr val = get_arg(argname, env, sig, pstate, traces); + val = SASS_MEMORY_COPY(val); + val->reduce(); + return val; + } + + double get_arg_val(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) + { + Number_Ptr val = get_arg(argname, env, sig, pstate, traces); + Number tmpnr(val); + tmpnr.reduce(); + return tmpnr.value(); + } + + double color_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) + { + Number_Ptr val = get_arg(argname, env, sig, pstate, traces); + Number tmpnr(val); + tmpnr.reduce(); + if (tmpnr.unit() == "%") { + return std::min(std::max(tmpnr.value() * 255 / 100.0, 0.0), 255.0); + } else { + return std::min(std::max(tmpnr.value(), 0.0), 255.0); + } + } + + double alpha_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) { + Number_Ptr val = get_arg(argname, env, sig, pstate, traces); + Number tmpnr(val); + tmpnr.reduce(); + if (tmpnr.unit() == "%") { + return std::min(std::max(tmpnr.value(), 0.0), 100.0); + } else { + return std::min(std::max(tmpnr.value(), 0.0), 1.0); + } + } + + Selector_List_Obj get_arg_sels(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) { + Expression_Obj exp = ARG(argname, Expression); + if (exp->concrete_type() == Expression::NULL_VAL) { + std::stringstream msg; + msg << argname << ": null is not a valid selector: it must be a string,\n"; + msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'"; + error(msg.str(), pstate, traces); + } + if (String_Constant_Ptr str = Cast(exp)) { + str->quote_mark(0); + } + std::string exp_src = exp->to_string(ctx.c_options); + return Parser::parse_selector(exp_src.c_str(), ctx, traces); + } + + Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) { + Expression_Obj exp = ARG(argname, Expression); + if (exp->concrete_type() == Expression::NULL_VAL) { + std::stringstream msg; + msg << argname << ": null is not a string for `" << function_name(sig) << "'"; + error(msg.str(), pstate, traces); + } + if (String_Constant_Ptr str = Cast(exp)) { + str->quote_mark(0); + } + std::string exp_src = exp->to_string(ctx.c_options); + Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx, traces); + if (sel_list->length() == 0) return NULL; + Complex_Selector_Obj first = sel_list->first(); + if (!first->tail()) return first->head(); + return first->tail()->head(); + } + } } diff --git a/src/fn_utils.hpp b/src/fn_utils.hpp index 8363240eb..eaeac0228 100644 --- a/src/fn_utils.hpp +++ b/src/fn_utils.hpp @@ -1,10 +1,73 @@ #ifndef SASS_FN_UTILS_H #define SASS_FN_UTILS_H +#include "backtrace.hpp" +#include "environment.hpp" +#include "ast_fwd_decl.hpp" + namespace Sass { + #define BUILT_IN(name) Expression_Ptr \ + name(Env& env, Env& d_env, Context& ctx, Signature sig, ParserState pstate, Backtraces traces, std::vector selector_stack) + + #define ARG(argname, argtype) get_arg(argname, env, sig, pstate, traces) + #define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, traces) + + // return a number object (copied since we want to have reduced units) + #define ARGN(argname) get_arg_n(argname, env, sig, pstate, traces) // Number copy + + // special function for weird hsla percent (10px == 10% == 10 != 0.1) + #define ARGVAL(argname) get_arg_val(argname, env, sig, pstate, traces) // double + + // macros for common ranges (u mean unsigned or upper, r for full range) + #define DARG_U_FACT(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 1.0) // double + #define DARG_R_FACT(argname) get_arg_r(argname, env, sig, pstate, traces, - 1.0, 1.0) // double + #define DARG_U_BYTE(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 255.0) // double + #define DARG_R_BYTE(argname) get_arg_r(argname, env, sig, pstate, traces, - 255.0, 255.0) // double + #define DARG_U_PRCT(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 100.0) // double + #define DARG_R_PRCT(argname) get_arg_r(argname, env, sig, pstate, traces, - 100.0, 100.0) // double + + // macros for color related inputs (rbg and alpha/opacity values) + #define COLOR_NUM(argname) color_num(argname, env, sig, pstate, traces) // double + #define ALPHA_NUM(argname) alpha_num(argname, env, sig, pstate, traces) // double + + #define ARGSEL(argname) get_arg_sel(argname, env, sig, pstate, traces, ctx) + #define ARGSELS(argname) get_arg_sels(argname, env, sig, pstate, traces, ctx) + + typedef const char* Signature; + + typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtraces, SelectorStack); + + Definition_Ptr make_native_function(Signature, Native_Function, Context& ctx); + Definition_Ptr make_c_function(Sass_Function_Entry c_func, Context& ctx); + namespace Functions { + template + T* get_arg(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) + { + T* val = Cast(env[argname]); + if (!val) { + std::string msg("argument `"); + msg += argname; + msg += "` of `"; + msg += sig; + msg += "` must be a "; + msg += T::type_name(); + error(msg, pstate, traces); + } + return val; + } + + Map_Ptr get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // maps only + Number_Ptr get_arg_n(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // numbers only + double alpha_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // colors only + double color_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // colors only + double get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, double lo, double hi); // colors only + double get_arg_val(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces); // shared + Selector_List_Obj get_arg_sels(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx); // selectors only + Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx); // selectors only + } } diff --git a/src/functions.cpp b/src/functions.cpp index 9b118d53a..b3fdf44f7 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -31,69 +31,12 @@ #include "wincrypt.h" #endif -#define ARG(argname, argtype) get_arg(argname, env, sig, pstate, traces) -#define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, traces, ctx) - -// return a number object (copied since we want to have reduced units) -#define ARGN(argname) get_arg_n(argname, env, sig, pstate, traces) // Number copy - -// special function for weird hsla percent (10px == 10% == 10 != 0.1) -#define ARGVAL(argname) get_arg_val(argname, env, sig, pstate, traces) // double - -// macros for common ranges (u mean unsigned or upper, r for full range) -#define DARG_U_FACT(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 1.0) // double -#define DARG_R_FACT(argname) get_arg_r(argname, env, sig, pstate, traces, - 1.0, 1.0) // double -#define DARG_U_BYTE(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 255.0) // double -#define DARG_R_BYTE(argname) get_arg_r(argname, env, sig, pstate, traces, - 255.0, 255.0) // double -#define DARG_U_PRCT(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 100.0) // double -#define DARG_R_PRCT(argname) get_arg_r(argname, env, sig, pstate, traces, - 100.0, 100.0) // double - -// macros for color related inputs (rbg and alpha/opacity values) -#define COLOR_NUM(argname) color_num(argname, env, sig, pstate, traces) // double -#define ALPHA_NUM(argname) alpha_num(argname, env, sig, pstate, traces) // double +#include "fn_utils.hpp" namespace Sass { using std::stringstream; using std::endl; - Definition_Ptr make_native_function(Signature sig, Native_Function func, Context& ctx) - { - Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[built-in function]")); - sig_parser.lex(); - std::string name(Util::normalize_underscores(sig_parser.lexed)); - Parameters_Obj params = sig_parser.parse_parameters(); - return SASS_MEMORY_NEW(Definition, - ParserState("[built-in function]"), - sig, - name, - params, - func, - false); - } - - Definition_Ptr make_c_function(Sass_Function_Entry c_func, Context& ctx) - { - using namespace Prelexer; - - const char* sig = sass_function_get_signature(c_func); - Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[c function]")); - // allow to overload generic callback plus @warn, @error and @debug with custom functions - sig_parser.lex < alternatives < identifier, exactly <'*'>, - exactly < Constants::warn_kwd >, - exactly < Constants::error_kwd >, - exactly < Constants::debug_kwd > - > >(); - std::string name(Util::normalize_underscores(sig_parser.lexed)); - Parameters_Obj params = sig_parser.parse_parameters(); - return SASS_MEMORY_NEW(Definition, - ParserState("[c function]"), - sig, - name, - params, - c_func, - false, true); - } - std::string function_name(Signature sig) { std::string str(sig); @@ -122,152 +65,6 @@ namespace Sass { catch (...) { throw; } } - template - T* get_arg(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) - { - // Minimal error handling -- the expectation is that built-ins will be written correctly! - T* val = Cast(env[argname]); - if (!val) { - std::string msg("argument `"); - msg += argname; - msg += "` of `"; - msg += sig; - msg += "` must be a "; - msg += T::type_name(); - error(msg, pstate, traces); - } - return val; - } - - Map_Ptr get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) - { - // Minimal error handling -- the expectation is that built-ins will be written correctly! - Map_Ptr val = Cast(env[argname]); - if (val) return val; - - List_Ptr lval = Cast(env[argname]); - if (lval && lval->length() == 0) return SASS_MEMORY_NEW(Map, pstate, 0); - - // fallback on get_arg for error handling - val = get_arg(argname, env, sig, pstate, traces); - return val; - } - - double get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, double lo, double hi) - { - // Minimal error handling -- the expectation is that built-ins will be written correctly! - Number_Ptr val = get_arg(argname, env, sig, pstate, traces); - Number tmpnr(val); - tmpnr.reduce(); - double v = tmpnr.value(); - if (!(lo <= v && v <= hi)) { - std::stringstream msg; - msg << "argument `" << argname << "` of `" << sig << "` must be between "; - msg << lo << " and " << hi; - error(msg.str(), pstate, traces); - } - return v; - } - - Number_Ptr get_arg_n(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) - { - // Minimal error handling -- the expectation is that built-ins will be written correctly! - Number_Ptr val = get_arg(argname, env, sig, pstate, traces); - val = SASS_MEMORY_COPY(val); - val->reduce(); - return val; - } - - double get_arg_v(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) - { - // Minimal error handling -- the expectation is that built-ins will be written correctly! - Number_Ptr val = get_arg(argname, env, sig, pstate, traces); - Number tmpnr(val); - tmpnr.reduce(); - /* - if (tmpnr.unit() == "%") { - tmpnr.value(tmpnr.value() / 100); - tmpnr.numerators.clear(); - } else { - if (!tmpnr.is_unitless()) error("argument " + argname + " of `" + std::string(sig) + "` must be unitless", pstate); - } - */ - return tmpnr.value(); - } - - double get_arg_val(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) - { - // Minimal error handling -- the expectation is that built-ins will be written correctly! - Number_Ptr val = get_arg(argname, env, sig, pstate, traces); - Number tmpnr(val); - tmpnr.reduce(); - return tmpnr.value(); - } - - double color_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) - { - Number_Ptr val = get_arg(argname, env, sig, pstate, traces); - Number tmpnr(val); - tmpnr.reduce(); - if (tmpnr.unit() == "%") { - return std::min(std::max(tmpnr.value() * 255 / 100.0, 0.0), 255.0); - } else { - return std::min(std::max(tmpnr.value(), 0.0), 255.0); - } - } - - - inline double alpha_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) { - Number_Ptr val = get_arg(argname, env, sig, pstate, traces); - Number tmpnr(val); - tmpnr.reduce(); - if (tmpnr.unit() == "%") { - return std::min(std::max(tmpnr.value(), 0.0), 100.0); - } else { - return std::min(std::max(tmpnr.value(), 0.0), 1.0); - } - } - - #define ARGSEL(argname, seltype, contextualize) get_arg_sel(argname, env, sig, pstate, traces, ctx) - - template - T get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx); - - template <> - Selector_List_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) { - Expression_Obj exp = ARG(argname, Expression); - if (exp->concrete_type() == Expression::NULL_VAL) { - std::stringstream msg; - msg << argname << ": null is not a valid selector: it must be a string,\n"; - msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'"; - error(msg.str(), pstate, traces); - } - if (String_Constant_Ptr str = Cast(exp)) { - str->quote_mark(0); - } - std::string exp_src = exp->to_string(ctx.c_options); - return Parser::parse_selector(exp_src.c_str(), ctx, traces); - } - - template <> - Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) { - Expression_Obj exp = ARG(argname, Expression); - if (exp->concrete_type() == Expression::NULL_VAL) { - std::stringstream msg; - msg << argname << ": null is not a string for `" << function_name(sig) << "'"; - error(msg.str(), pstate, traces); - } - if (String_Constant_Ptr str = Cast(exp)) { - str->quote_mark(0); - } - std::string exp_src = exp->to_string(ctx.c_options); - Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx, traces); - if (sel_list->length() == 0) return NULL; - Complex_Selector_Obj first = sel_list->first(); - if (!first->tail()) return first->head(); - return first->tail()->head(); - } - #ifdef __MINGW32__ uint64_t GetSeed() { @@ -2097,8 +1894,8 @@ namespace Sass { Signature selector_unify_sig = "selector-unify($selector1, $selector2)"; BUILT_IN(selector_unify) { - Selector_List_Obj selector1 = ARGSEL("$selector1", Selector_List_Obj, p_contextualize); - Selector_List_Obj selector2 = ARGSEL("$selector2", Selector_List_Obj, p_contextualize); + Selector_List_Obj selector1 = ARGSELS("$selector1"); + Selector_List_Obj selector2 = ARGSELS("$selector2"); Selector_List_Obj result = selector1->unify_with(selector2); Listize listize; @@ -2108,7 +1905,7 @@ namespace Sass { Signature simple_selectors_sig = "simple-selectors($selector)"; BUILT_IN(simple_selectors) { - Compound_Selector_Obj sel = ARGSEL("$selector", Compound_Selector_Obj, p_contextualize); + Compound_Selector_Obj sel = ARGSEL("$selector"); List_Ptr l = SASS_MEMORY_NEW(List, sel->pstate(), sel->length(), SASS_COMMA); @@ -2125,9 +1922,9 @@ namespace Sass { Signature selector_extend_sig = "selector-extend($selector, $extendee, $extender)"; BUILT_IN(selector_extend) { - Selector_List_Obj selector = ARGSEL("$selector", Selector_List_Obj, p_contextualize); - Selector_List_Obj extendee = ARGSEL("$extendee", Selector_List_Obj, p_contextualize); - Selector_List_Obj extender = ARGSEL("$extender", Selector_List_Obj, p_contextualize); + Selector_List_Obj selector = ARGSELS("$selector"); + Selector_List_Obj extendee = ARGSELS("$extendee"); + Selector_List_Obj extender = ARGSELS("$extender"); Subset_Map subset_map; extender->populate_extends(extendee, subset_map); @@ -2142,9 +1939,9 @@ namespace Sass { Signature selector_replace_sig = "selector-replace($selector, $original, $replacement)"; BUILT_IN(selector_replace) { - Selector_List_Obj selector = ARGSEL("$selector", Selector_List_Obj, p_contextualize); - Selector_List_Obj original = ARGSEL("$original", Selector_List_Obj, p_contextualize); - Selector_List_Obj replacement = ARGSEL("$replacement", Selector_List_Obj, p_contextualize); + Selector_List_Obj selector = ARGSELS("$selector"); + Selector_List_Obj original = ARGSELS("$original"); + Selector_List_Obj replacement = ARGSELS("$replacement"); Subset_Map subset_map; replacement->populate_extends(original, subset_map); Extend extend(subset_map); @@ -2158,7 +1955,7 @@ namespace Sass { Signature selector_parse_sig = "selector-parse($selector)"; BUILT_IN(selector_parse) { - Selector_List_Obj sel = ARGSEL("$selector", Selector_List_Obj, p_contextualize); + Selector_List_Obj sel = ARGSELS("$selector"); Listize listize; return sel->perform(&listize); @@ -2167,8 +1964,8 @@ namespace Sass { Signature is_superselector_sig = "is-superselector($super, $sub)"; BUILT_IN(is_superselector) { - Selector_List_Obj sel_sup = ARGSEL("$super", Selector_List_Obj, p_contextualize); - Selector_List_Obj sel_sub = ARGSEL("$sub", Selector_List_Obj, p_contextualize); + Selector_List_Obj sel_sup = ARGSELS("$super"); + Selector_List_Obj sel_sub = ARGSELS("$sub"); bool result = sel_sup->is_superselector_of(sel_sub); return SASS_MEMORY_NEW(Boolean, pstate, result); } diff --git a/src/functions.hpp b/src/functions.hpp index 7019be934..fa6d5d7f0 100644 --- a/src/functions.hpp +++ b/src/functions.hpp @@ -6,18 +6,13 @@ #include "environment.hpp" #include "ast_fwd_decl.hpp" #include "sass/functions.h" - -#define BUILT_IN(name) Expression_Ptr \ -name(Env& env, Env& d_env, Context& ctx, Signature sig, ParserState pstate, Backtraces traces, std::vector selector_stack) +#include "fn_utils.hpp" namespace Sass { struct Backtrace; typedef const char* Signature; typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtraces, std::vector); - Definition_Ptr make_native_function(Signature, Native_Function, Context& ctx); - Definition_Ptr make_c_function(Sass_Function_Entry c_func, Context& ctx); - std::string function_name(Signature); namespace Functions { diff --git a/src/sass_functions.hpp b/src/sass_functions.hpp index 3b646d67e..482ed641b 100644 --- a/src/sass_functions.hpp +++ b/src/sass_functions.hpp @@ -3,7 +3,7 @@ #include "sass.h" #include "environment.hpp" -#include "functions.hpp" +#include "fn_utils.hpp" // Struct to hold custom function callback struct Sass_Function {