Skip to content

Commit

Permalink
Refactor custom function/importer signatures
Browse files Browse the repository at this point in the history
Pass `Sass_Option` pointer to custom functions.
Allows implementer to access the context options.
  • Loading branch information
mgreter committed Mar 29, 2015
1 parent 8942168 commit e159403
Show file tree
Hide file tree
Showing 17 changed files with 269 additions and 191 deletions.
20 changes: 13 additions & 7 deletions ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,24 +644,27 @@ namespace Sass {
ADD_PROPERTY(Env*, environment);
ADD_PROPERTY(Type, type);
ADD_PROPERTY(Native_Function, native_function);
ADD_PROPERTY(Sass_C_Function, c_function);
ADD_PROPERTY(Sass_Function_Entry, c_cb);
ADD_PROPERTY(void*, cookie);
ADD_PROPERTY(Context*, ctx);
ADD_PROPERTY(bool, is_overload_stub);
ADD_PROPERTY(Signature, signature);
public:
Definition(ParserState pstate,
string n,
Parameters* params,
Block* b,
Context* ctx,
Type t)
: Has_Block(pstate, b),
name_(n),
parameters_(params),
environment_(0),
type_(t),
native_function_(0),
c_function_(0),
c_cb_(0),
cookie_(0),
ctx_(ctx),
is_overload_stub_(false),
signature_(0)
{ }
Expand All @@ -670,24 +673,26 @@ namespace Sass {
string n,
Parameters* params,
Native_Function func_ptr,
Context* ctx,
bool overload_stub = false)
: Has_Block(pstate, 0),
name_(n),
parameters_(params),
environment_(0),
type_(FUNCTION),
native_function_(func_ptr),
c_function_(0),
c_cb_(0),
cookie_(0),
ctx_(ctx),
is_overload_stub_(overload_stub),
signature_(sig)
{ }
Definition(ParserState pstate,
Signature sig,
string n,
Parameters* params,
Sass_C_Function func_ptr,
void* cookie,
Sass_Function_Entry c_func,
Context* ctx,
bool whatever,
bool whatever2)
: Has_Block(pstate, 0),
Expand All @@ -696,8 +701,9 @@ namespace Sass {
environment_(0),
type_(FUNCTION),
native_function_(0),
c_function_(func_ptr),
cookie_(cookie),
c_cb_(c_func),
cookie_(sass_function_get_cookie(c_func)),
ctx_(ctx),
is_overload_stub_(false),
signature_(sig)
{ }
Expand Down
30 changes: 14 additions & 16 deletions context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,23 @@ namespace Sass {
this->source = source;
}

inline bool sort_importers (const Sass_C_Importer_Call& i, const Sass_C_Importer_Call& j)
inline bool sort_importers (const Sass_Importer_Entry& i, const Sass_Importer_Entry& j)
{ return sass_importer_get_priority(i) < sass_importer_get_priority(j); }

Context::Context(Context::Data initializers)
: // Output(this),
mem(Memory_Manager<AST_Node>()),
c_options (initializers.c_options()),
c_compiler (initializers.c_compiler()),
source_c_str (initializers.source_c_str()),
sources (vector<const char*>()),
plugin_paths (initializers.plugin_paths()),
include_paths (initializers.include_paths()),
queue (vector<Sass_Queued>()),
style_sheets (map<string, Block*>()),
emitter (this),
c_functions (vector<Sass_C_Function_Call>()),
c_importers (vector<Sass_C_Importer_Call>()),
c_functions (vector<Sass_Function_Entry>()),
c_importers (vector<Sass_Importer_Entry>()),
indent (initializers.indent()),
linefeed (initializers.linefeed()),
input_path (make_canonical_path(initializers.input_path())),
Expand Down Expand Up @@ -123,11 +125,11 @@ namespace Sass {

}

void Context::add_c_function(Sass_C_Function_Call function)
void Context::add_c_function(Sass_Function_Entry function)
{
c_functions.push_back(function);
}
void Context::add_c_importer(Sass_C_Importer_Call importer)
void Context::add_c_importer(Sass_Importer_Entry importer)
{
c_importers.push_back(importer);
// need to sort the array afterwards (no big deal)
Expand Down Expand Up @@ -279,8 +281,8 @@ namespace Sass {
void register_function(Context&, Signature sig, Native_Function f, size_t arity, Env* env);
void register_overload_stub(Context&, string name, Env* env);
void register_built_in_functions(Context&, Env* env);
void register_c_functions(Context&, Env* env, Sass_C_Function_List);
void register_c_function(Context&, Env* env, Sass_C_Function_Call);
void register_c_functions(Context&, Env* env, Sass_Function_List);
void register_c_function(Context&, Env* env, Sass_Function_Entry);

char* Context::compile_block(Block* root)
{
Expand All @@ -299,7 +301,7 @@ namespace Sass {
{
Block* root = 0;
for (size_t i = 0; i < queue.size(); ++i) {
struct Sass_Import* import = sass_make_import(
Sass_Import_Entry import = sass_make_import(
queue[i].load_path.c_str(),
queue[i].abs_path.c_str(),
0, 0
Expand Down Expand Up @@ -427,6 +429,7 @@ namespace Sass {
name,
0,
0,
&ctx,
true);
(*env)[name + "[f]"] = stub;
}
Expand Down Expand Up @@ -525,21 +528,16 @@ namespace Sass {
register_function(ctx, unique_id_sig, unique_id, env);
}

void register_c_functions(Context& ctx, Env* env, Sass_C_Function_List descrs)
void register_c_functions(Context& ctx, Env* env, Sass_Function_List descrs)
{
while (descrs && *descrs) {
register_c_function(ctx, env, *descrs);
++descrs;
}
}
void register_c_function(Context& ctx, Env* env, Sass_C_Function_Call descr)
void register_c_function(Context& ctx, Env* env, Sass_Function_Entry descr)
{
Definition* def = make_c_function(
sass_function_get_signature(descr),
sass_function_get_function(descr),
sass_function_get_cookie(descr),
ctx
);
Definition* def = make_c_function(descr, ctx);
def->environment(env);
(*env)[def->name() + "[f]"] = def;
}
Expand Down
16 changes: 10 additions & 6 deletions context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "plugins.hpp"
#include "sass_functions.h"

struct Sass_C_Function_Descriptor;
struct Sass_Function;

namespace Sass {
using namespace std;
Expand All @@ -34,6 +34,8 @@ namespace Sass {
public:
Memory_Manager<AST_Node> mem;

struct Sass_Options* c_options;
struct Sass_Compiler* c_compiler;
const char* source_c_str;

// c-strs containing Sass file contents
Expand All @@ -52,11 +54,11 @@ namespace Sass {
// SourceMap source_map;
Output emitter;

vector<Sass_C_Function_Call> c_functions;
vector<Sass_C_Importer_Call> c_importers;
vector<Sass_Function_Entry> c_functions;
vector<Sass_Importer_Entry> c_importers;

void add_c_function(Sass_C_Function_Call function);
void add_c_importer(Sass_C_Importer_Call importer);
void add_c_function(Sass_Function_Entry function);
void add_c_importer(Sass_Importer_Entry importer);

string indent; // String to be used for indentation
string linefeed; // String to be used for line feeds
Expand All @@ -72,14 +74,16 @@ namespace Sass {
bool is_indented_syntax_src; // treat source string as sass

// overload import calls
vector<struct Sass_Import*> import_stack;
vector<Sass_Import_Entry> import_stack;

map<string, Color*> names_to_colors;
map<int, string> colors_to_names;

size_t precision; // precision for outputting fractional numbers

KWD_ARG_SET(Data) {
KWD_ARG(Data, struct Sass_Options*, c_options);
KWD_ARG(Data, struct Sass_Compiler*, c_compiler);
KWD_ARG(Data, const char*, source_c_str);
KWD_ARG(Data, string, entry_point);
KWD_ARG(Data, string, input_path);
Expand Down
45 changes: 36 additions & 9 deletions contrib/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,52 @@
// gcc: g++ -shared plugin.cpp -o plugin.so -fPIC -Llib -lsass
// mingw: g++ -shared plugin.cpp -o plugin.dll -Llib -lsass

union Sass_Value* call_fn_foo(const union Sass_Value* s_args, void* cookie)
extern "C" const char* ADDCALL libsass_get_version() {
return libsass_version();
}

union Sass_Value* custom_function(const union Sass_Value* s_args, Sass_Function_Entry cb, struct Sass_Options* opts)
{
// get the cookie from function descriptor
void* cookie = sass_function_get_cookie(cb);
// we actually abuse the void* to store an "int"
return sass_make_number((intptr_t)cookie, "px");
}

extern "C" const char* ADDCALL libsass_get_version() {
return libsass_version();
extern "C" Sass_Function_List ADDCALL libsass_load_functions()
{
// allocate a custom function caller
Sass_Function_Entry c_func =
sass_make_function("foo()", custom_function, (void*)42);
// create list of all custom functions
Sass_Function_List fn_list = sass_make_function_list(1);
// put the only function in this plugin to the list
sass_function_set_list_entry(fn_list, 0, c_func);
// return the list
return fn_list;
}

extern "C" Sass_C_Function_List ADDCALL libsass_load_functions()
Sass_Import_List custom_importer(const char* cur_path, Sass_Importer_Entry cb, struct Sass_Compiler* comp)
{
// get the cookie from importer descriptor
void* cookie = sass_importer_get_cookie(cb);
// create a list to hold our import entries
Sass_Import_List incs = sass_make_import_list(1);
// create our only import entry (route path back)
incs[0] = sass_make_import_entry(cur_path, 0, 0);
// return imports
return incs;
}

extern "C" Sass_Importer_List ADDCALL libsass_load_importers()
{
// allocate a custom function caller
Sass_C_Function_Call fn_foo =
sass_make_function("foo()", call_fn_foo, (void*)42);
Sass_Importer_Entry c_imp =
sass_make_importer(custom_importer, - 99, (void*)42);
// create list of all custom functions
Sass_C_Function_List fn_list = sass_make_function_list(1);
Sass_Importer_List imp_list = sass_make_importer_list(1);
// put the only function in this plugin to the list
sass_function_set_list_entry(fn_list, 0, fn_foo);
sass_importer_set_list_entry(imp_list, 0, c_imp);
// return the list
return fn_list;
return imp_list;
}
22 changes: 13 additions & 9 deletions eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,13 @@ namespace Sass {
Definition* def = static_cast<Definition*>((*env)["@warn[f]"]);
// Block* body = def->block();
// Native_Function func = def->native_function();
Sass_C_Function c_func = def->c_function();
Sass_Function_Entry c_cb = def->c_cb();
Sass_Function_Fn c_func = sass_function_get_function(c_cb);

To_C to_c;
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
sass_list_set_value(c_args, 0, message->perform(&to_c));
Sass_Value* c_val = c_func(c_args, def->cookie());
Sass_Value* c_val = c_func(c_args, c_cb, ctx.c_options);
sass_delete_value(c_args);
sass_delete_value(c_val);
return 0;
Expand All @@ -287,12 +288,13 @@ namespace Sass {
Definition* def = static_cast<Definition*>((*env)["@error[f]"]);
// Block* body = def->block();
// Native_Function func = def->native_function();
Sass_C_Function c_func = def->c_function();
Sass_Function_Entry c_cb = def->c_cb();
Sass_Function_Fn c_func = sass_function_get_function(c_cb);

To_C to_c;
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
sass_list_set_value(c_args, 0, message->perform(&to_c));
Sass_Value* c_val = c_func(c_args, def->cookie());
Sass_Value* c_val = c_func(c_args, c_cb, ctx.c_options);
sass_delete_value(c_args);
sass_delete_value(c_val);
return 0;
Expand All @@ -315,12 +317,13 @@ namespace Sass {
Definition* def = static_cast<Definition*>((*env)["@debug[f]"]);
// Block* body = def->block();
// Native_Function func = def->native_function();
Sass_C_Function c_func = def->c_function();
Sass_Function_Entry c_cb = def->c_cb();
Sass_Function_Fn c_func = sass_function_get_function(c_cb);

To_C to_c;
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
sass_list_set_value(c_args, 0, message->perform(&to_c));
Sass_Value* c_val = c_func(c_args, def->cookie());
Sass_Value* c_val = c_func(c_args, c_cb, ctx.c_options);
sass_delete_value(c_args);
sass_delete_value(c_val);
return 0;
Expand Down Expand Up @@ -500,7 +503,7 @@ namespace Sass {
Definition* def = static_cast<Definition*>((*env)[full_name]);
Block* body = def->block();
Native_Function func = def->native_function();
Sass_C_Function c_func = def->c_function();
Sass_Function_Entry c_cb = def->c_cb();

if (full_name != "if[f]") {
for (size_t i = 0, L = args->length(); i < L; ++i) {
Expand Down Expand Up @@ -551,8 +554,9 @@ namespace Sass {
env = old_env;
}
// else if it's a user-defined c function
else if (c_func) {
else if (c_cb) {

Sass_Function_Fn c_func = sass_function_get_function(c_cb);
if (full_name == "*[f]") {
String_Constant *str = new (ctx.mem) String_Constant(c->pstate(), c->name());
Arguments* new_args = new (ctx.mem) Arguments(c->pstate());
Expand All @@ -577,7 +581,7 @@ namespace Sass {
Expression* arg = static_cast<Expression*>(node);
sass_list_set_value(c_args, i, arg->perform(&to_c));
}
Sass_Value* c_val = c_func(c_args, def->cookie());
Sass_Value* c_val = c_func(c_args, c_cb, ctx.c_options);
if (sass_value_get_tag(c_val) == SASS_ERROR) {
error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), backtrace);
} else if (sass_value_get_tag(c_val) == SASS_WARNING) {
Expand Down
1 change: 1 addition & 0 deletions expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ namespace Sass {
"@content",
new (ctx.mem) Parameters(c->pstate()),
c->block(),
&ctx,
Definition::MIXIN);
thunk->environment(env);
new_env.local_frame()["@content[m]"] = thunk;
Expand Down
Loading

0 comments on commit e159403

Please sign in to comment.