Skip to content

Commit

Permalink
Move macros and helpers to fn_utils
Browse files Browse the repository at this point in the history
- Remove obsolete ctx parameter
- make ARGSEL(S) macro specific
  • Loading branch information
mgreter committed Mar 17, 2018
1 parent 0dad856 commit d828027
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 224 deletions.
1 change: 0 additions & 1 deletion src/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Selector_List_Obj>);
class Definition : public Has_Block {
public:
Expand Down
6 changes: 6 additions & 0 deletions src/ast_fwd_decl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,14 @@ namespace Sass {
typedef std::set<Compound_Selector_Obj, OrderNodes> CompoundSelectorSet;
typedef std::unordered_set<Simple_Selector_Obj, HashNodes, CompareNodes> SimpleSelectorDict;

typedef std::vector<Block_Ptr> BlockStack;
typedef std::vector<AST_Node_Obj> CallStack;
typedef std::vector<Media_Block_Ptr> MediaStack;
typedef std::vector<Selector_List_Obj> SelectorStack;
typedef std::vector<Sass_Import_Entry>* ImporterStack;

typedef const char* Signature;

// only to switch implementations for testing
#define environment_map std::map

Expand Down
1 change: 1 addition & 0 deletions src/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "sass2scss.h"
#include "prelexer.hpp"
#include "emitter.hpp"
#include "fn_utils.hpp"

namespace Sass {
using namespace Constants;
Expand Down
143 changes: 143 additions & 0 deletions src/fn_utils.cpp
Original file line number Diff line number Diff line change
@@ -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<Prelexer::identifier>();
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<Map>(env[argname]);
if (val) return val;

List_Ptr lval = Cast<List>(env[argname]);
if (lval && lval->length() == 0) return SASS_MEMORY_NEW(Map, pstate, 0);

// fallback on get_arg for error handling
val = get_arg<Map>(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<Number>(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<Number>(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<Number>(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<Number>(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<Number>(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<String_Constant>(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<String_Constant>(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();
}

}

}
63 changes: 63 additions & 0 deletions src/fn_utils.hpp
Original file line number Diff line number Diff line change
@@ -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_List_Obj> selector_stack)

#define ARG(argname, argtype) get_arg<argtype>(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 <typename T>
T* get_arg(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
{
T* val = Cast<T>(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

}

}
Expand Down
Loading

0 comments on commit d828027

Please sign in to comment.