Skip to content

Commit

Permalink
Move misc functions to own compile unit
Browse files Browse the repository at this point in the history
- clean up definitions of function macros
  • Loading branch information
mgreter committed Mar 17, 2018
1 parent 47354ad commit c1b3676
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 292 deletions.
1 change: 1 addition & 0 deletions Makefile.conf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ SOURCES = \
context.cpp \
constants.cpp \
fn_utils.cpp \
fn_miscs.cpp \
fn_maps.cpp \
fn_lists.cpp \
fn_colors.cpp \
Expand Down
1 change: 1 addition & 0 deletions src/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "prelexer.hpp"
#include "emitter.hpp"
#include "fn_utils.hpp"
#include "fn_miscs.hpp"
#include "fn_maps.hpp"
#include "fn_lists.hpp"
#include "fn_colors.hpp"
Expand Down
1 change: 1 addition & 0 deletions src/error_handling.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <string>
#include <sstream>
#include <stdexcept>
#include "units.hpp"
#include "position.hpp"
#include "backtrace.hpp"
#include "ast_fwd_decl.hpp"
Expand Down
1 change: 1 addition & 0 deletions src/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "prelexer.hpp"
#include "utf8_string.hpp"
#include "sass_functions.hpp"
#include "error_handling.hpp"
#include "sass2scss.h"

#ifdef _WIN32
Expand Down
252 changes: 252 additions & 0 deletions src/fn_miscs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
#include "ast.hpp"
#include "expand.hpp"
#include "fn_utils.hpp"
#include "fn_miscs.hpp"
#include "debugger.hpp"

namespace Sass {

namespace Functions {

// features
static std::set<std::string> features {
"global-variable-shadowing",
"extend-selector-pseudoclass",
"at-error",
"units-level-3",
"custom-property"
};

//////////////////////////
// INTROSPECTION FUNCTIONS
//////////////////////////

Signature type_of_sig = "type-of($value)";
BUILT_IN(type_of)
{
Expression_Ptr v = ARG("$value", Expression);
return SASS_MEMORY_NEW(String_Quoted, pstate, v->type());
}

Signature variable_exists_sig = "variable-exists($name)";
BUILT_IN(variable_exists)
{
std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));

if(d_env.has("$"+s)) {
return SASS_MEMORY_NEW(Boolean, pstate, true);
}
else {
return SASS_MEMORY_NEW(Boolean, pstate, false);
}
}

Signature global_variable_exists_sig = "global-variable-exists($name)";
BUILT_IN(global_variable_exists)
{
std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));

if(d_env.has_global("$"+s)) {
return SASS_MEMORY_NEW(Boolean, pstate, true);
}
else {
return SASS_MEMORY_NEW(Boolean, pstate, false);
}
}

Signature function_exists_sig = "function-exists($name)";
BUILT_IN(function_exists)
{
String_Constant_Ptr ss = Cast<String_Constant>(env["$name"]);
if (!ss) {
error("$name: " + (env["$name"]->to_string()) + " is not a string for `function-exists'", pstate, traces);
}

std::string name = Util::normalize_underscores(unquote(ss->value()));

if(d_env.has_global(name+"[f]")) {
return SASS_MEMORY_NEW(Boolean, pstate, true);
}
else {
return SASS_MEMORY_NEW(Boolean, pstate, false);
}
}

Signature mixin_exists_sig = "mixin-exists($name)";
BUILT_IN(mixin_exists)
{
std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));

if(d_env.has_global(s+"[m]")) {
return SASS_MEMORY_NEW(Boolean, pstate, true);
}
else {
return SASS_MEMORY_NEW(Boolean, pstate, false);
}
}

Signature feature_exists_sig = "feature-exists($name)";
BUILT_IN(feature_exists)
{
std::string s = unquote(ARG("$name", String_Constant)->value());

if(features.find(s) == features.end()) {
return SASS_MEMORY_NEW(Boolean, pstate, false);
}
else {
return SASS_MEMORY_NEW(Boolean, pstate, true);
}
}

Signature call_sig = "call($name, $args...)";
BUILT_IN(call)
{
std::string name;
Function_Ptr ff = Cast<Function>(env["$name"]);
String_Constant_Ptr ss = Cast<String_Constant>(env["$name"]);

if (ss) {
name = Util::normalize_underscores(unquote(ss->value()));
std::cerr << "DEPRECATION WARNING: ";
std::cerr << "Passing a string to call() is deprecated and will be illegal" << std::endl;
std::cerr << "in Sass 4.0. Use call(get-function(" + quote(name) + ")) instead." << std::endl;
std::cerr << std::endl;
} else if (ff) {
name = ff->name();
}

List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List));

Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
// std::string full_name(name + "[f]");
// Definition_Ptr def = d_env.has(full_name) ? Cast<Definition>((d_env)[full_name]) : 0;
// Parameters_Ptr params = def ? def->parameters() : 0;
// size_t param_size = params ? params->length() : 0;
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
Expression_Obj expr = arglist->value_at_index(i);
// if (params && params->has_rest_parameter()) {
// Parameter_Obj p = param_size > i ? (*params)[i] : 0;
// List_Ptr list = Cast<List>(expr);
// if (list && p && !p->is_rest_parameter()) expr = (*list)[0];
// }
if (arglist->is_arglist()) {
Expression_Obj obj = arglist->at(i);
Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX
args->append(SASS_MEMORY_NEW(Argument,
pstate,
expr,
arg ? arg->name() : "",
arg ? arg->is_rest_argument() : false,
arg ? arg->is_keyword_argument() : false));
} else {
args->append(SASS_MEMORY_NEW(Argument, pstate, expr));
}
}
Function_Call_Obj func = SASS_MEMORY_NEW(Function_Call, pstate, name, args);
Expand expand(ctx, &d_env, &selector_stack);
func->via_call(true); // calc invoke is allowed
if (ff) func->func(ff);
return func->perform(&expand.eval);
}

////////////////////
// BOOLEAN FUNCTIONS
////////////////////

Signature not_sig = "not($value)";
BUILT_IN(sass_not)
{
return SASS_MEMORY_NEW(Boolean, pstate, ARG("$value", Expression)->is_false());
}

Signature if_sig = "if($condition, $if-true, $if-false)";
// BUILT_IN(sass_if)
// { return ARG("$condition", Expression)->is_false() ? ARG("$if-false", Expression) : ARG("$if-true", Expression); }
BUILT_IN(sass_if)
{
Expand expand(ctx, &d_env, &selector_stack);
Expression_Obj cond = ARG("$condition", Expression)->perform(&expand.eval);
bool is_true = !cond->is_false();
Expression_Obj res = ARG(is_true ? "$if-true" : "$if-false", Expression);
Value_Obj qwe = Cast<Value>(res->perform(&expand.eval));
// if (qwe == 0) debug_ast(res);
// res = res->perform(&expand.eval.val_eval);
qwe->set_delayed(false); // clone?
return qwe.detach();
}

//////////////////////////
// MISCELLANEOUS FUNCTIONS
//////////////////////////

// value.check_deprecated_interp if value.is_a?(Sass::Script::Value::String)
// unquoted_string(value.to_sass)

Signature inspect_sig = "inspect($value)";
BUILT_IN(inspect)
{
Expression_Ptr v = ARG("$value", Expression);
if (v->concrete_type() == Expression::NULL_VAL) {
return SASS_MEMORY_NEW(String_Quoted, pstate, "null");
} else if (v->concrete_type() == Expression::BOOLEAN && v->is_false()) {
return SASS_MEMORY_NEW(String_Quoted, pstate, "false");
} else if (v->concrete_type() == Expression::STRING) {
return Cast<String>(v);
} else {
// ToDo: fix to_sass for nested parentheses
Sass_Output_Style old_style;
old_style = ctx.c_options.output_style;
ctx.c_options.output_style = TO_SASS;
Emitter emitter(ctx.c_options);
Inspect i(emitter);
i.in_declaration = false;
v->perform(&i);
ctx.c_options.output_style = old_style;
return SASS_MEMORY_NEW(String_Quoted, pstate, i.get_buffer());
}
// return v;
}

Signature content_exists_sig = "content-exists()";
BUILT_IN(content_exists)
{
if (!d_env.has_global("is_in_mixin")) {
error("Cannot call content-exists() except within a mixin.", pstate, traces);
}
return SASS_MEMORY_NEW(Boolean, pstate, d_env.has_lexical("@content[m]"));
}

Signature get_function_sig = "get-function($name, $css: false)";
BUILT_IN(get_function)
{
String_Constant_Ptr ss = Cast<String_Constant>(env["$name"]);
if (!ss) {
error("$name: " + (env["$name"]->to_string()) + " is not a string for `get-function'", pstate, traces);
}

std::string name = Util::normalize_underscores(unquote(ss->value()));
std::string full_name = name + "[f]";

Boolean_Obj css = ARG("$css", Boolean);
if (!css->is_false()) {
Definition_Ptr def = SASS_MEMORY_NEW(Definition,
pstate,
name,
SASS_MEMORY_NEW(Parameters, pstate),
SASS_MEMORY_NEW(Block, pstate, 0, false),
Definition::FUNCTION);
return SASS_MEMORY_NEW(Function, pstate, def, true);
}


if (!d_env.has_global(full_name)) {
error("Function not found: " + name, pstate, traces);
}

Definition_Ptr def = Cast<Definition>(d_env[full_name]);
return SASS_MEMORY_NEW(Function, pstate, def, false);
}

}

}
40 changes: 40 additions & 0 deletions src/fn_miscs.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef SASS_FN_MISCS_H
#define SASS_FN_MISCS_H

#include "fn_utils.hpp"

namespace Sass {

namespace Functions {

extern Signature type_of_sig;
extern Signature variable_exists_sig;
extern Signature global_variable_exists_sig;
extern Signature function_exists_sig;
extern Signature mixin_exists_sig;
extern Signature feature_exists_sig;
extern Signature call_sig;
extern Signature not_sig;
extern Signature if_sig;
extern Signature set_nth_sig;
extern Signature content_exists_sig;
extern Signature get_function_sig;

BUILT_IN(type_of);
BUILT_IN(variable_exists);
BUILT_IN(global_variable_exists);
BUILT_IN(function_exists);
BUILT_IN(mixin_exists);
BUILT_IN(feature_exists);
BUILT_IN(call);
BUILT_IN(sass_not);
BUILT_IN(sass_if);
BUILT_IN(set_nth);
BUILT_IN(content_exists);
BUILT_IN(get_function);

}

}

#endif
6 changes: 6 additions & 0 deletions src/fn_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ namespace Sass {

namespace Functions {

std::string function_name(Signature sig)
{
std::string str(sig);
return str.substr(0, str.find('('));
}

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!
Expand Down
13 changes: 0 additions & 13 deletions src/fn_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,10 @@ namespace Sass {
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)

// 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

typedef const char* Signature;

typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtraces, SelectorStack);
Expand Down
Loading

0 comments on commit c1b3676

Please sign in to comment.