Commit de3aadc3 by Aaron Leung

Oy, converted all existing built-in functions to use the new-and-improved infrastructure.

parent 863cddce
#include "context.hpp" #include "context.hpp"
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <sstream>
#include <unistd.h> #include <unistd.h>
#include "prelexer.hpp" #include "prelexer.hpp"
#include "color_names.hpp" #include "color_names.hpp"
...@@ -73,27 +74,20 @@ namespace Sass { ...@@ -73,27 +74,20 @@ namespace Sass {
} }
delete[] image_path; delete[] image_path;
new_Node.free(); new_Node.free();
// cerr << "Deallocated " << i << " source string(s)." << endl;
} }
inline void Context::register_function(Function_Descriptor d, Primitive ip) inline void Context::register_function(Signature sig, Primitive ip)
{ {
Function f(d, ip, new_Node); Function f(const_cast<char*>(sig), ip, *this);
// function_env[pair<string, size_t>(f.name, f.parameters.size())] = f;
function_env[f.name] = f; function_env[f.name] = f;
} }
inline void Context::register_function(Function_Descriptor d, Primitive ip, size_t arity) inline void Context::register_function(Signature sig, Primitive ip, size_t arity)
{
Function f(d, ip, new_Node);
// function_env[pair<string, size_t>(f.name, arity)] = f;
function_env[f.name] = f;
}
inline void Context::register_function_2(const char* sig, Primitive_2 ip)
{ {
Function f(const_cast<char*>(sig), ip, *this); Function f(const_cast<char*>(sig), ip, *this);
function_env[f.name] = f; std::stringstream stub;
stub << f.name << " " << arity;
function_env[stub.str()] = f;
} }
inline void Context::register_overload_stub(string name) inline void Context::register_overload_stub(string name)
...@@ -105,69 +99,50 @@ namespace Sass { ...@@ -105,69 +99,50 @@ namespace Sass {
{ {
using namespace Functions; using namespace Functions;
register_function_2(foo_sig, foo);
// RGB Functions // RGB Functions
register_function(rgb_descriptor, rgb); register_function(rgb_sig, rgb);
register_overload_stub("rgba"); register_overload_stub("rgba");
register_function(rgba_4_descriptor, rgba_4); register_function(rgba_4_sig, rgba_4, 4);
register_function(rgba_2_descriptor, rgba_2); register_function(rgba_2_sig, rgba_2, 2);
register_function(red_descriptor, red); register_function(red_sig, red);
register_function(green_descriptor, green); register_function(green_sig, green);
register_function(blue_descriptor, blue); register_function(blue_sig, blue);
register_overload_stub("mix"); register_function(mix_sig, mix);
register_function(mix_2_descriptor, mix_2);
register_function(mix_3_descriptor, mix_3);
// HSL Functions // HSL Functions
register_function(hsla_descriptor, hsla); register_function(hsla_sig, hsla);
register_function(hsl_descriptor, hsl); register_function(hsl_sig, hsl);
register_function(adjust_hue_descriptor, adjust_hue); register_function(adjust_hue_sig, adjust_hue);
register_function(invert_descriptor, invert); register_function(invert_sig, invert);
// Opacity Functions // Opacity Functions
register_function(alpha_descriptor, alpha); register_function(alpha_sig, alpha);
register_function(opacity_descriptor, alpha); register_function(opacity_sig, alpha);
register_function(opacify_descriptor, opacify); register_function(opacify_sig, opacify);
register_function(fade_in_descriptor, opacify); register_function(fade_in_sig, opacify);
register_function(transparentize_descriptor, transparentize); register_function(transparentize_sig, transparentize);
register_function(fade_out_descriptor, transparentize); register_function(fade_out_sig, transparentize);
// String Functions // String Functions
register_function(unquote_descriptor, unquote); register_function(unquote_sig, unquote);
register_function(quote_descriptor, quote); register_function(quote_sig, quote);
// Number Functions // Number Functions
register_function(percentage_descriptor, percentage); register_function(percentage_sig, percentage);
register_function(round_descriptor, round); register_function(round_sig, round);
register_function(ceil_descriptor, ceil); register_function(ceil_sig, ceil);
register_function(floor_descriptor, floor); register_function(floor_sig, floor);
register_function(abs_descriptor, abs); register_function(abs_sig, abs);
// List Functions // List Functions
register_function(length_descriptor, length); register_function(length_sig, length);
register_function(nth_descriptor, nth); register_function(nth_sig, nth);
register_overload_stub("join"); register_function(join_sig, join);
register_function(join_2_descriptor, join_2); register_function(append_sig, append);
register_function(join_3_descriptor, join_3); register_function(compact_sig, compact);
register_overload_stub("append");
register_function(append_2_descriptor, append_2);
register_function(append_3_descriptor, append_3);
register_overload_stub("compact");
register_function(compact_1_descriptor, compact);
register_function(compact_2_descriptor, compact);
register_function(compact_3_descriptor, compact);
register_function(compact_4_descriptor, compact);
register_function(compact_5_descriptor, compact);
register_function(compact_6_descriptor, compact);
register_function(compact_7_descriptor, compact);
register_function(compact_8_descriptor, compact);
register_function(compact_9_descriptor, compact);
register_function(compact_10_descriptor, compact);
register_function(compact_11_descriptor, compact);
register_function(compact_12_descriptor, compact);
// Introspection Functions // Introspection Functions
register_function(type_of_descriptor, type_of); register_function(type_of_sig, type_of);
register_function(unit_descriptor, unit); register_function(unit_sig, unit);
register_function(unitless_descriptor, unitless); register_function(unitless_sig, unitless);
register_function(comparable_descriptor, comparable); register_function(comparable_sig, comparable);
// Boolean Functions // Boolean Functions
register_function(not_descriptor, not_impl); register_function(not_sig, not_impl);
register_function(if_descriptor, if_impl); register_function(if_sig, if_impl);
} }
void Context::setup_color_map() void Context::setup_color_map()
......
...@@ -38,9 +38,8 @@ namespace Sass { ...@@ -38,9 +38,8 @@ namespace Sass {
Context(const char* paths_str = 0, const char* img_path_str = 0); Context(const char* paths_str = 0, const char* img_path_str = 0);
~Context(); ~Context();
void register_function_2(const char* sig, Primitive_2 ip); void register_function(Signature sig, Primitive ip);
void register_function(Function_Descriptor d, Primitive ip); void register_function(Signature sig, Primitive ip, size_t arity);
void register_function(Function_Descriptor d, Primitive ip, size_t arity);
void register_overload_stub(string name); void register_overload_stub(string name);
void register_functions(); void register_functions();
void setup_color_map(); void setup_color_map();
......
...@@ -706,7 +706,7 @@ namespace Sass { ...@@ -706,7 +706,7 @@ namespace Sass {
// primitive function implementation, then return its value. // primitive function implementation, then return its value.
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx) Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx)
{ {
if (f.primitive_2) { if (f.primitive) {
// evaluate arguments in the current environment // evaluate arguments in the current environment
for (size_t i = 0, S = args.size(); i < S; ++i) { for (size_t i = 0, S = args.size(); i < S; ++i) {
if (args[i].type() != Node::assignment) { if (args[i].type() != Node::assignment) {
...@@ -720,25 +720,25 @@ namespace Sass { ...@@ -720,25 +720,25 @@ namespace Sass {
Environment bindings; Environment bindings;
bindings.link(env.global ? *env.global : env); bindings.link(env.global ? *env.global : env);
bind_arguments("function " + f.name, f.parameters, args, prefix, bindings, f_env, new_Node, ctx); bind_arguments("function " + f.name, f.parameters, args, prefix, bindings, f_env, new_Node, ctx);
return f.primitive_2(f.parameter_names, bindings, new_Node); return f.primitive(f.parameter_names, bindings, new_Node);
}
else if (f.primitive) {
map<Token, Node> bindings;
// bind arguments
for (size_t i = 0, j = 0, S = args.size(); i < S; ++i) {
if (args[i].type() == Node::assignment) {
Node arg(args[i]);
Token name(arg[0].token());
bindings[name] = eval(arg[1], prefix, env, f_env, new_Node, ctx);
}
else {
// TO DO: ensure (j < f.parameters.size())
bindings[f.parameters[j].token()] = eval(args[i], prefix, env, f_env, new_Node, ctx);
++j;
}
}
return f(bindings, new_Node);
} }
// else if (f.primitive) {
// map<Token, Node> bindings;
// // bind arguments
// for (size_t i = 0, j = 0, S = args.size(); i < S; ++i) {
// if (args[i].type() == Node::assignment) {
// Node arg(args[i]);
// Token name(arg[0].token());
// bindings[name] = eval(arg[1], prefix, env, f_env, new_Node, ctx);
// }
// else {
// // TO DO: ensure (j < f.parameters.size())
// bindings[f.parameters[j].token()] = eval(args[i], prefix, env, f_env, new_Node, ctx);
// ++j;
// }
// }
// return f(bindings, new_Node);
// }
else { else {
Node params(f.definition[1]); Node params(f.definition[1]);
Node body(new_Node(f.definition[2])); Node body(new_Node(f.definition[2]));
......
...@@ -17,8 +17,9 @@ using std::cerr; using std::endl; ...@@ -17,8 +17,9 @@ using std::cerr; using std::endl;
namespace Sass { namespace Sass {
// this constructor needs context.hpp, so it can't be defined in functions.hpp // this constructor needs context.hpp, so it can't be defined in functions.hpp
Function::Function(char* signature, Primitive_2 ip, Context& ctx) Function::Function(char* signature, Primitive ip, Context& ctx)
: primitive_2(ip), : definition(Node()),
primitive(ip),
overloaded(false) overloaded(false)
{ {
Document sig_doc(Document::make_from_source_chars(ctx, signature)); Document sig_doc(Document::make_from_source_chars(ctx, signature));
...@@ -33,7 +34,7 @@ namespace Sass { ...@@ -33,7 +34,7 @@ namespace Sass {
} }
else { else {
parameter_names << param[0]; parameter_names << param[0];
// assuming default args for primitives can be evaluated only once at init // assume it's safe to evaluate default args just once at initialization
param[1] = eval(param[1], Node(), ctx.global_env, ctx.function_env, ctx.new_Node, ctx); param[1] = eval(param[1], Node(), ctx.global_env, ctx.function_env, ctx.new_Node, ctx);
} }
} }
...@@ -50,7 +51,7 @@ namespace Sass { ...@@ -50,7 +51,7 @@ namespace Sass {
throw Error(Error::evaluation, path, line, message); throw Error(Error::evaluation, path, line, message);
} }
extern const char foo_sig[] = "foo($x, $y, $z: \"hey\")"; extern Signature foo_sig = "foo($x, $y, $z: \"hey\")";
Node foo(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) { Node foo(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node arg1(bindings[parameter_names[0].token()]); Node arg1(bindings[parameter_names[0].token()]);
Node arg2(bindings[parameter_names[1].token()]); Node arg2(bindings[parameter_names[1].token()]);
...@@ -63,107 +64,88 @@ namespace Sass { ...@@ -63,107 +64,88 @@ namespace Sass {
// RGB Functions /////////////////////////////////////////////////////// // RGB Functions ///////////////////////////////////////////////////////
Function_Descriptor rgb_descriptor = extern Signature rgb_sig = "rgb($red, $green, $blue)";
{ "rgb", "$red", "$green", "$blue", 0 }; Node rgb(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node rgb(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node r(bindings[parameter_names[0].token()]);
Node r(bindings[parameters[0].token()]); Node g(bindings[parameter_names[1].token()]);
Node g(bindings[parameters[1].token()]); Node b(bindings[parameter_names[2].token()]);
Node b(bindings[parameters[2].token()]);
if (!(r.type() == Node::number && g.type() == Node::number && b.type() == Node::number)) { if (!(r.type() == Node::number && g.type() == Node::number && b.type() == Node::number)) {
throw_eval_error("arguments for rgb must be numbers", r.path(), r.line()); throw_eval_error("arguments for rgb must be numbers", r.path(), r.line());
} }
return new_Node(r.path(), r.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), 1.0); return new_Node(r.path(), r.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), 1.0);
} }
Function_Descriptor rgba_4_descriptor = // TODO: SOMETHING SPECIAL FOR OVERLOADED FUNCTIONS
{ "rgba 4", "$red", "$green", "$blue", "$alpha", 0 }; extern Signature rgba_4_sig = "rgba($red, $green, $blue, $alpha)";
Node rgba_4(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node rgba_4(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0].token()]); Node r(bindings[parameter_names[0].token()]);
Node g(bindings[parameters[1].token()]); Node g(bindings[parameter_names[1].token()]);
Node b(bindings[parameters[2].token()]); Node b(bindings[parameter_names[2].token()]);
Node a(bindings[parameters[3].token()]); Node a(bindings[parameter_names[3].token()]);
if (!(r.type() == Node::number && g.type() == Node::number && b.type() == Node::number && a.type() == Node::number)) { if (!(r.type() == Node::number && g.type() == Node::number && b.type() == Node::number && a.type() == Node::number)) {
throw_eval_error("arguments for rgba must be numbers", r.path(), r.line()); throw_eval_error("arguments for rgba must be numbers", r.path(), r.line());
} }
return new_Node(r.path(), r.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), a.numeric_value()); return new_Node(r.path(), r.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), a.numeric_value());
} }
Function_Descriptor rgba_2_descriptor = extern Signature rgba_2_sig = "rgba($color, $alpha)";
{ "rgba 2", "$color", "$alpha", 0 }; Node rgba_2(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node rgba_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node color(bindings[parameter_names[0].token()]);
Node color(bindings[parameters[0].token()]);
Node r(color[0]); Node r(color[0]);
Node g(color[1]); Node g(color[1]);
Node b(color[2]); Node b(color[2]);
Node a(bindings[parameters[1].token()]); Node a(bindings[parameter_names[1].token()]);
if (color.type() != Node::numeric_color || a.type() != Node::number) throw_eval_error("arguments to rgba must be a color and a number", color.path(), color.line()); if (color.type() != Node::numeric_color || a.type() != Node::number) throw_eval_error("arguments to rgba must be a color and a number", color.path(), color.line());
return new_Node(color.path(), color.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), a.numeric_value()); return new_Node(color.path(), color.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), a.numeric_value());
} }
Function_Descriptor red_descriptor = extern Signature red_sig = "red($color)";
{ "red", "$color", 0 }; Node red(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node red(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node color(bindings[parameter_names[0].token()]);
Node color(bindings[parameters[0].token()]);
if (color.type() != Node::numeric_color) throw_eval_error("argument to red must be a color", color.path(), color.line()); if (color.type() != Node::numeric_color) throw_eval_error("argument to red must be a color", color.path(), color.line());
return color[0]; return color[0];
} }
Function_Descriptor green_descriptor = extern Signature green_sig = "green($color)";
{ "green", "$color", 0 }; Node green(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node green(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node color(bindings[parameter_names[0].token()]);
Node color(bindings[parameters[0].token()]);
if (color.type() != Node::numeric_color) throw_eval_error("argument to green must be a color", color.path(), color.line()); if (color.type() != Node::numeric_color) throw_eval_error("argument to green must be a color", color.path(), color.line());
return color[1]; return color[1];
} }
Function_Descriptor blue_descriptor = extern Signature blue_sig = "blue($color)";
{ "blue", "$color", 0 }; Node blue(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node blue(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node color(bindings[parameter_names[0].token()]);
Node color(bindings[parameters[0].token()]);
if (color.type() != Node::numeric_color) throw_eval_error("argument to blue must be a color", color.path(), color.line()); if (color.type() != Node::numeric_color) throw_eval_error("argument to blue must be a color", color.path(), color.line());
return color[2]; return color[2];
} }
Node mix_impl(Node color1, Node color2, double weight, Node_Factory& new_Node) { extern Signature mix_sig = "mix($color-1, $color-2, $weight: 50%)";
if (!(color1.type() == Node::numeric_color && color2.type() == Node::numeric_color)) { Node mix(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
throw_eval_error("first two arguments to mix must be colors", color1.path(), color1.line()); Node color1(bindings[parameter_names[0].token()]);
} Node color2(bindings[parameter_names[1].token()]);
double p = weight/100; Node weight(bindings[parameter_names[2].token()]);
if (color1.type() != Node::numeric_color) throw_eval_error("first argument to mix must be a color", color1.path(), color1.line());
if (color2.type() != Node::numeric_color) throw_eval_error("second argument to mix must be a color", color2.path(), color2.line());
if (!weight.is_numeric()) throw_eval_error("third argument to mix must be numeric", weight.path(), weight.line());
double p = weight.numeric_value()/100;
double w = 2*p - 1; double w = 2*p - 1;
double a = color1[3].numeric_value() - color2[3].numeric_value(); double a = color1[3].numeric_value() - color2[3].numeric_value();
double w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0; double w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0;
double w2 = 1 - w1; double w2 = 1 - w1;
Node mixed(new_Node(Node::numeric_color, color1.path(), color1.line(), 4)); Node mixed(new_Node(Node::numeric_color, color1.path(), color1.line(), 4));
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
mixed << new_Node(mixed.path(), mixed.line(), mixed << new_Node(mixed.path(), mixed.line(), w1*color1[i].numeric_value() + w2*color2[i].numeric_value());
w1*color1[i].numeric_value() + w2*color2[i].numeric_value());
} }
double alpha = color1[3].numeric_value()*p + color2[3].numeric_value()*(1-p); double alpha = color1[3].numeric_value()*p + color2[3].numeric_value()*(1-p);
mixed << new_Node(mixed.path(), mixed.line(), alpha); mixed << new_Node(mixed.path(), mixed.line(), alpha);
return mixed; return mixed;
} }
Function_Descriptor mix_2_descriptor =
{ "mix 2", "$color1", "$color2", 0 };
Node mix_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return mix_impl(bindings[parameters[0].token()], bindings[parameters[1].token()], 50, new_Node);
}
Function_Descriptor mix_3_descriptor =
{ "mix 3", "$color1", "$color2", "$weight", 0 };
Node mix_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node percentage(bindings[parameters[2].token()]);
if (!(percentage.type() == Node::number || percentage.type() == Node::numeric_percentage || percentage.type() == Node::numeric_dimension)) {
throw_eval_error("third argument to mix must be numeric", percentage.path(), percentage.line());
}
return mix_impl(bindings[parameters[0].token()],
bindings[parameters[1].token()],
percentage.numeric_value(),
new_Node);
}
// HSL Functions /////////////////////////////////////////////////////// // HSL Functions ///////////////////////////////////////////////////////
// Utility rgb to hsl function so we can do hsl operations // Utility rgb to hsl function so we can do hsl operations
...@@ -200,14 +182,6 @@ namespace Sass { ...@@ -200,14 +182,6 @@ namespace Sass {
return new_Node("", 0, static_cast<int>(h*360)%360, s*100, l*100); return new_Node("", 0, static_cast<int>(h*360)%360, s*100, l*100);
} }
// Function_Descriptor adjust_color_descriptor =
// { "adjust_color 1", "$color", 0 }
// Function_Descriptor adjust_color_2_descriptor =
// { "adjust_color 2", "$color", "2")
// Node adjust_color_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
// blah;
// }
double h_to_rgb(double m1, double m2, double h) { double h_to_rgb(double m1, double m2, double h) {
if (h < 0) ++h; if (h < 0) ++h;
if (h > 1) --h; if (h > 1) --h;
...@@ -233,45 +207,40 @@ namespace Sass { ...@@ -233,45 +207,40 @@ namespace Sass {
return new_Node("", 0, r, g, b, a); return new_Node("", 0, r, g, b, a);
} }
Function_Descriptor hsla_descriptor = extern Signature hsla_sig = "hsla($hue, $saturation, $lightness, $alpha)";
{ "hsla", "$hue", "$saturation", "$lightness", "$alpha", 0 }; Node hsla(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node hsla(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { if (!(bindings[parameter_names[0].token()].is_numeric() &&
if (!(bindings[parameters[0].token()].is_numeric() && bindings[parameter_names[1].token()].is_numeric() &&
bindings[parameters[1].token()].is_numeric() && bindings[parameter_names[2].token()].is_numeric() &&
bindings[parameters[2].token()].is_numeric() && bindings[parameter_names[3].token()].is_numeric())) {
bindings[parameters[3].token()].is_numeric())) { throw_eval_error("arguments to hsla must be numeric", bindings[parameter_names[0].token()].path(), bindings[parameter_names[0].token()].line());
throw_eval_error("arguments to hsla must be numeric", bindings[parameters[0].token()].path(), bindings[parameters[0].token()].line());
} }
double h = bindings[parameters[0].token()].numeric_value(); double h = bindings[parameter_names[0].token()].numeric_value();
double s = bindings[parameters[1].token()].numeric_value(); double s = bindings[parameter_names[1].token()].numeric_value();
double l = bindings[parameters[2].token()].numeric_value(); double l = bindings[parameter_names[2].token()].numeric_value();
double a = bindings[parameters[3].token()].numeric_value(); double a = bindings[parameter_names[3].token()].numeric_value();
Node color(hsla_impl(h, s, l, a, new_Node)); Node color(hsla_impl(h, s, l, a, new_Node));
// color.line() = bindings[parameters[0].token()].line();
return color; return color;
} }
Function_Descriptor hsl_descriptor = extern Signature hsl_sig = "hsl($hue, $saturation, $lightness)";
{ "hsl", "$hue", "$saturation", "$lightness", 0 }; Node hsl(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node hsl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { if (!(bindings[parameter_names[0].token()].is_numeric() &&
if (!(bindings[parameters[0].token()].is_numeric() && bindings[parameter_names[1].token()].is_numeric() &&
bindings[parameters[1].token()].is_numeric() && bindings[parameter_names[2].token()].is_numeric())) {
bindings[parameters[2].token()].is_numeric())) { throw_eval_error("arguments to hsl must be numeric", bindings[parameter_names[0].token()].path(), bindings[parameter_names[0].token()].line());
throw_eval_error("arguments to hsl must be numeric", bindings[parameters[0].token()].path(), bindings[parameters[0].token()].line());
} }
double h = bindings[parameters[0].token()].numeric_value(); double h = bindings[parameter_names[0].token()].numeric_value();
double s = bindings[parameters[1].token()].numeric_value(); double s = bindings[parameter_names[1].token()].numeric_value();
double l = bindings[parameters[2].token()].numeric_value(); double l = bindings[parameter_names[2].token()].numeric_value();
Node color(hsla_impl(h, s, l, 1, new_Node)); Node color(hsla_impl(h, s, l, 1, new_Node));
// color.line() = bindings[parameters[0].token()].line();
return color; return color;
} }
Function_Descriptor adjust_hue_descriptor = extern Signature adjust_hue_sig = "adjust-hue($color, $degrees)";
{ "adjust-hue", "$color", "$degrees", 0 }; Node adjust_hue(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node adjust_hue(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node rgb_col(bindings[parameter_names[0].token()]);
Node rgb_col(bindings[parameters[0].token()]); Node degrees(bindings[parameter_names[1].token()]);
Node degrees(bindings[parameters[1].token()]);
if (rgb_col.type() != Node::numeric_color) throw_eval_error("first argument to adjust-hue must be a color", rgb_col.path(), rgb_col.line()); if (rgb_col.type() != Node::numeric_color) throw_eval_error("first argument to adjust-hue must be a color", rgb_col.path(), rgb_col.line());
if (!degrees.is_numeric()) throw_eval_error("second argument to adjust-hue must be numeric", degrees.path(), degrees.line()); if (!degrees.is_numeric()) throw_eval_error("second argument to adjust-hue must be numeric", degrees.path(), degrees.line());
Node hsl_col(rgb_to_hsl(rgb_col[0].numeric_value(), Node hsl_col(rgb_to_hsl(rgb_col[0].numeric_value(),
...@@ -285,10 +254,9 @@ namespace Sass { ...@@ -285,10 +254,9 @@ namespace Sass {
new_Node); new_Node);
} }
Function_Descriptor invert_descriptor = extern Signature invert_sig = "invert($color)";
{ "invert", "$color", 0 }; Node invert(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node invert(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node orig(bindings[parameter_names[0].token()]);
Node orig(bindings[parameters[0].token()]);
if (orig.type() != Node::numeric_color) throw_eval_error("argument to invert must be a color", orig.path(), orig.line()); if (orig.type() != Node::numeric_color) throw_eval_error("argument to invert must be a color", orig.path(), orig.line());
return new_Node(orig.path(), orig.line(), return new_Node(orig.path(), orig.line(),
255 - orig[0].numeric_value(), 255 - orig[0].numeric_value(),
...@@ -299,23 +267,19 @@ namespace Sass { ...@@ -299,23 +267,19 @@ namespace Sass {
// Opacity Functions /////////////////////////////////////////////////// // Opacity Functions ///////////////////////////////////////////////////
Function_Descriptor alpha_descriptor = extern Signature alpha_sig = "alpha($color)";
{ "alpha", "$color", 0 }; extern Signature opacity_sig = "opacity($color)";
Function_Descriptor opacity_descriptor = Node alpha(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
{ "opacity", "$color", 0 }; Node color(bindings[parameter_names[0].token()]);
Node alpha(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { if (color.type() != Node::numeric_color) throw_eval_error("argument to alpha/opacity must be a color", color.path(), color.line());
Node color(bindings[parameters[0].token()]);
if (color.type() != Node::numeric_color) throw_eval_error("argument to alpha must be a color", color.path(), color.line());
return color[3]; return color[3];
} }
Function_Descriptor opacify_descriptor = extern Signature opacify_sig = "opacify($color, $amount)";
{ "opacify", "$color", "$amount", 0 }; extern Signature fade_in_sig = "fade-in($color, $amount)";
Function_Descriptor fade_in_descriptor = Node opacify(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
{ "fade_in", "$color", "$amount", 0 }; Node color(bindings[parameter_names[0].token()]);
Node opacify(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node delta(bindings[parameter_names[1].token()]);
Node color(bindings[parameters[0].token()]);
Node delta(bindings[parameters[1].token()]);
if (color.type() != Node::numeric_color || !delta.is_numeric()) { if (color.type() != Node::numeric_color || !delta.is_numeric()) {
throw_eval_error("arguments to opacify/fade_in must be a color and a numeric value", color.path(), color.line()); throw_eval_error("arguments to opacify/fade_in must be a color and a numeric value", color.path(), color.line());
} }
...@@ -329,13 +293,11 @@ namespace Sass { ...@@ -329,13 +293,11 @@ namespace Sass {
color[0].numeric_value(), color[1].numeric_value(), color[2].numeric_value(), alpha); color[0].numeric_value(), color[1].numeric_value(), color[2].numeric_value(), alpha);
} }
Function_Descriptor transparentize_descriptor = extern Signature transparentize_sig = "transparentize($color, $amount)";
{ "transparentize", "$color", "$amount", 0 }; extern Signature fade_out_sig = "fade-out($color, $amount)";
Function_Descriptor fade_out_descriptor = Node transparentize(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
{ "fade_out", "$color", "$amount", 0 }; Node color(bindings[parameter_names[0].token()]);
Node transparentize(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node delta(bindings[parameter_names[1].token()]);
Node color(bindings[parameters[0].token()]);
Node delta(bindings[parameters[1].token()]);
if (color.type() != Node::numeric_color || !delta.is_numeric()) { if (color.type() != Node::numeric_color || !delta.is_numeric()) {
throw_eval_error("arguments to transparentize/fade_out must be a color and a numeric value", color.path(), color.line()); throw_eval_error("arguments to transparentize/fade_out must be a color and a numeric value", color.path(), color.line());
} }
...@@ -351,10 +313,9 @@ namespace Sass { ...@@ -351,10 +313,9 @@ namespace Sass {
// String Functions //////////////////////////////////////////////////// // String Functions ////////////////////////////////////////////////////
Function_Descriptor unquote_descriptor = extern Signature unquote_sig = "unquote($string)";
{ "unquote", "$string", 0 }; Node unquote(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node unquote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node cpy(new_Node(bindings[parameter_names[0].token()]));
Node cpy(new_Node(bindings[parameters[0].token()]));
// if (cpy.type() != Node::string_constant /* && cpy.type() != Node::concatenation */) { // if (cpy.type() != Node::string_constant /* && cpy.type() != Node::concatenation */) {
// throw_eval_error("argument to unquote must be a string", cpy.path(), cpy.line()); // throw_eval_error("argument to unquote must be a string", cpy.path(), cpy.line());
// } // }
...@@ -363,10 +324,9 @@ namespace Sass { ...@@ -363,10 +324,9 @@ namespace Sass {
return cpy; return cpy;
} }
Function_Descriptor quote_descriptor = extern Signature quote_sig = "quote($string)";
{ "quote", "$string", 0 }; Node quote(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node quote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node orig(bindings[parameter_names[0].token()]);
Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
default: { default: {
...@@ -389,20 +349,18 @@ namespace Sass { ...@@ -389,20 +349,18 @@ namespace Sass {
// Number Functions //////////////////////////////////////////////////// // Number Functions ////////////////////////////////////////////////////
Function_Descriptor percentage_descriptor = extern Signature percentage_sig = "percentage($value)";
{ "percentage", "$value", 0 }; Node percentage(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node percentage(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node orig(bindings[parameter_names[0].token()]);
Node orig(bindings[parameters[0].token()]);
if (orig.type() != Node::number) { if (orig.type() != Node::number) {
throw_eval_error("argument to percentage must be a unitless number", orig.path(), orig.line()); throw_eval_error("argument to percentage must be a unitless number", orig.path(), orig.line());
} }
return new_Node(orig.path(), orig.line(), orig.numeric_value() * 100, Node::numeric_percentage); return new_Node(orig.path(), orig.line(), orig.numeric_value() * 100, Node::numeric_percentage);
} }
Function_Descriptor round_descriptor = extern Signature round_sig = "round($value)";
{ "round", "$value", 0 }; Node round(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node round(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node orig(bindings[parameter_names[0].token()]);
Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
case Node::numeric_dimension: { case Node::numeric_dimension: {
...@@ -429,10 +387,9 @@ namespace Sass { ...@@ -429,10 +387,9 @@ namespace Sass {
return Node(); return Node();
} }
Function_Descriptor ceil_descriptor = extern Signature ceil_sig = "ceil($value)";
{ "ceil", "$value", 0 }; Node ceil(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node ceil(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node orig(bindings[parameter_names[0].token()]);
Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
case Node::numeric_dimension: { case Node::numeric_dimension: {
...@@ -459,10 +416,9 @@ namespace Sass { ...@@ -459,10 +416,9 @@ namespace Sass {
return Node(); return Node();
} }
Function_Descriptor floor_descriptor = extern Signature floor_sig = "floor($value)";
{ "floor", "$value", 0 }; Node floor(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node floor(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node orig(bindings[parameter_names[0].token()]);
Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
case Node::numeric_dimension: { case Node::numeric_dimension: {
...@@ -489,10 +445,9 @@ namespace Sass { ...@@ -489,10 +445,9 @@ namespace Sass {
return Node(); return Node();
} }
Function_Descriptor abs_descriptor = extern Signature abs_sig = "abs($value)";
{ "abs", "$value", 0 }; Node abs(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node abs(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node orig(bindings[parameter_names[0].token()]);
Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
case Node::numeric_dimension: { case Node::numeric_dimension: {
...@@ -521,10 +476,9 @@ namespace Sass { ...@@ -521,10 +476,9 @@ namespace Sass {
// List Functions ////////////////////////////////////////////////////// // List Functions //////////////////////////////////////////////////////
Function_Descriptor length_descriptor = extern Signature length_sig = "length($list)";
{ "length", "$list", 0 }; Node length(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node length(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node arg(bindings[parameter_names[0].token()]);
Node arg(bindings[parameters[0].token()]);
switch (arg.type()) switch (arg.type())
{ {
case Node::space_list: case Node::space_list:
...@@ -545,11 +499,10 @@ namespace Sass { ...@@ -545,11 +499,10 @@ namespace Sass {
return Node(); return Node();
} }
Function_Descriptor nth_descriptor = extern Signature nth_sig = "nth($list, $n)";
{ "nth", "$list", "$n", 0 }; Node nth(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node nth(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node l(bindings[parameter_names[0].token()]);
Node l(bindings[parameters[0].token()]); Node n(bindings[parameter_names[1].token()]);
Node n(bindings[parameters[1].token()]);
if (n.type() != Node::number) { if (n.type() != Node::number) {
throw_eval_error("second argument to nth must be a number", n.path(), n.line()); throw_eval_error("second argument to nth must be a number", n.path(), n.line());
} }
...@@ -566,15 +519,15 @@ namespace Sass { ...@@ -566,15 +519,15 @@ namespace Sass {
} }
return l[n_prim - 1]; return l[n_prim - 1];
} }
extern const char separator_kwd[] = "$separator"; extern Signature join_sig = "join($list1, $list2, $separator: auto)";
Node join_impl(const Node parameters, map<Token, Node>& bindings, bool has_sep, Node_Factory& new_Node) { Node join(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
// if the args aren't lists, turn them into singleton lists // if the args aren't lists, turn them into singleton lists
Node l1(bindings[parameters[0].token()]); Node l1(bindings[parameter_names[0].token()]);
if (l1.type() != Node::space_list && l1.type() != Node::comma_list && l1.type() != Node::nil) { if (l1.type() != Node::space_list && l1.type() != Node::comma_list && l1.type() != Node::nil) {
l1 = new_Node(Node::space_list, l1.path(), l1.line(), 1) << l1; l1 = new_Node(Node::space_list, l1.path(), l1.line(), 1) << l1;
} }
Node l2(bindings[parameters[1].token()]); Node l2(bindings[parameter_names[1].token()]);
if (l2.type() != Node::space_list && l2.type() != Node::comma_list && l2.type() != Node::nil) { if (l2.type() != Node::space_list && l2.type() != Node::comma_list && l2.type() != Node::nil) {
l2 = new_Node(Node::space_list, l2.path(), l2.line(), 1) << l2; l2 = new_Node(Node::space_list, l2.path(), l2.line(), 1) << l2;
} }
...@@ -588,38 +541,25 @@ namespace Sass { ...@@ -588,38 +541,25 @@ namespace Sass {
if (l2.type() != Node::nil) size += l2.size(); if (l2.type() != Node::nil) size += l2.size();
// figure out the result type in advance // figure out the result type in advance
Node::Type rtype = Node::space_list; Node::Type rtype = Node::space_list;
if (has_sep) {
string sep(bindings[parameters[2].token()].token().unquote()); string sep(bindings[parameter_names[2].token()].token().unquote());
if (sep == "comma") rtype = Node::comma_list; if (sep == "comma") rtype = Node::comma_list;
else if (sep == "space") rtype = Node::space_list; else if (sep == "space") rtype = Node::space_list;
else if (sep == "auto") rtype = l1.type(); else if (sep == "auto") rtype = l1.type();
else { else {
throw_eval_error("third argument to join must be 'space', 'comma', or 'auto'", l2.path(), l2.line()); throw_eval_error("third argument to join must be 'space', 'comma', or 'auto'", l2.path(), l2.line());
}
} }
else if (l1.type() != Node::nil) rtype = l1.type(); if (rtype == Node::nil) rtype = l2.type();
else if (l2.type() != Node::nil) rtype = l2.type();
// accumulate the result // accumulate the result
Node lr(new_Node(rtype, l1.path(), l1.line(), size)); Node lr(new_Node(rtype, l1.path(), l1.line(), size));
if (l1.type() != Node::nil) lr += l1; if (l1.type() != Node::nil) lr += l1;
if (l2.type() != Node::nil) lr += l2; if (l2.type() != Node::nil) lr += l2;
return lr; return lr;
} }
Function_Descriptor join_2_descriptor =
{ "join 2", "$list1", "$list2", 0 };
Node join_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, false, new_Node);
}
Function_Descriptor join_3_descriptor =
{ "join 3", "$list1", "$list2", "$separator", 0 };
Node join_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, true, new_Node);
}
Node append_impl(const Node parameters, map<Token, Node>& bindings, bool has_sep, Node_Factory& new_Node) { extern Signature append_sig = "append($list1, $list2, $separator: auto)";
Node list(bindings[parameters[0].token()]); Node append(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node list(bindings[parameter_names[0].token()]);
switch (list.type()) switch (list.type())
{ {
case Node::space_list: case Node::space_list:
...@@ -632,37 +572,26 @@ namespace Sass { ...@@ -632,37 +572,26 @@ namespace Sass {
list = (new_Node(Node::space_list, list.path(), list.line(), 1) << list); list = (new_Node(Node::space_list, list.path(), list.line(), 1) << list);
} break; } break;
} }
Node::Type sep_type = list.type();
if (has_sep) { Node::Type sep_type;
string sep_string = bindings[parameters[2].token()].token().unquote(); string sep_string = bindings[parameter_names[2].token()].token().unquote();
if (sep_string == "comma") sep_type = Node::comma_list; if (sep_string == "comma") sep_type = Node::comma_list;
else if (sep_string == "space") sep_type = Node::space_list; else if (sep_string == "space") sep_type = Node::space_list;
else if (sep_string == "auto") sep_type = list.type(); else if (sep_string == "auto") sep_type = list.type();
else throw_eval_error("third argument to append must be 'space', 'comma', or 'auto'", list.path(), list.line()); else throw_eval_error("third argument to append must be 'space', 'comma', or 'auto'", list.path(), list.line());
}
Node new_list(new_Node(sep_type, list.path(), list.line(), list.size() + 1)); Node new_list(new_Node(sep_type, list.path(), list.line(), list.size() + 1));
new_list += list; new_list += list;
new_list << bindings[parameters[1].token()]; new_list << bindings[parameter_names[1].token()];
return new_list; return new_list;
} }
Function_Descriptor append_2_descriptor = extern Signature compact_sig = "compact($arg1: false, $arg2: false, $arg3: false, $arg4: false, $arg5: false, $arg6: false, $arg7: false, $arg8: false, $arg9: false, $arg10: false, $arg11: false, $arg12: false)";
{ "append 2", "$list", "$val", 0 }; Node compact(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node append_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { size_t num_args = bindings.current_frame.size();
return append_impl(parameters, bindings, false, new_Node);
}
Function_Descriptor append_3_descriptor =
{ "append 3", "$list", "$val", "$separator", 0 };
Node append_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return append_impl(parameters, bindings, true, new_Node);
}
Node compact(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
size_t num_args = bindings.size();
Node::Type sep_type = Node::comma_list; Node::Type sep_type = Node::comma_list;
Node list; Node list;
Node arg1(bindings[parameters[0].token()]); Node arg1(bindings[parameter_names[0].token()]);
if (num_args == 1 && (arg1.type() == Node::space_list || if (num_args == 1 && (arg1.type() == Node::space_list ||
arg1.type() == Node::comma_list || arg1.type() == Node::comma_list ||
arg1.type() == Node::nil)) { arg1.type() == Node::nil)) {
...@@ -672,7 +601,7 @@ namespace Sass { ...@@ -672,7 +601,7 @@ namespace Sass {
else { else {
list = new_Node(sep_type, arg1.path(), arg1.line(), num_args); list = new_Node(sep_type, arg1.path(), arg1.line(), num_args);
for (size_t i = 0; i < num_args; ++i) { for (size_t i = 0; i < num_args; ++i) {
list << bindings[parameters[i].token()]; list << bindings[parameter_names[i].token()];
} }
} }
Node new_list(new_Node(list.type(), list.path(), list.line(), 0)); Node new_list(new_Node(list.type(), list.path(), list.line(), 0));
...@@ -684,40 +613,6 @@ namespace Sass { ...@@ -684,40 +613,6 @@ namespace Sass {
return new_list.size() ? new_list : new_Node(Node::nil, list.path(), list.line(), 0); return new_list.size() ? new_list : new_Node(Node::nil, list.path(), list.line(), 0);
} }
Function_Descriptor compact_1_descriptor =
{ "compact 1", "$arg1", 0 };
Function_Descriptor compact_2_descriptor =
{ "compact 2", "$arg1", "$arg2", 0 };
Function_Descriptor compact_3_descriptor =
{ "compact 3", "$arg1", "$arg2", "$arg3", 0 };
Function_Descriptor compact_4_descriptor =
{ "compact 4", "$arg1", "$arg2", "$arg3", "$arg4", 0 };
Function_Descriptor compact_5_descriptor =
{ "compact 5", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", 0 };
Function_Descriptor compact_6_descriptor =
{ "compact 6", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", 0 };
Function_Descriptor compact_7_descriptor =
{ "compact 7", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", 0 };
Function_Descriptor compact_8_descriptor =
{ "compact 8", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", "$arg8", 0 };
Function_Descriptor compact_9_descriptor =
{ "compact 9", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", "$arg8", "$arg9", 0 };
Function_Descriptor compact_10_descriptor =
{ "compact 10", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", "$arg8", "$arg9", "$arg10", 0 };
Function_Descriptor compact_11_descriptor =
{ "compact 11", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", "$arg6",
"$arg7", "$arg8", "$arg9", "$arg10", "$arg11", 0 };
Function_Descriptor compact_12_descriptor =
{ "compact 12", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", "arg6",
"$arg7", "$arg8", "$arg9", "$arg10", "$arg11", "$arg12", 0 };
// Introspection Functions ///////////////////////////////////////////// // Introspection Functions /////////////////////////////////////////////
extern const char number_name[] = "number"; extern const char number_name[] = "number";
...@@ -726,10 +621,9 @@ namespace Sass { ...@@ -726,10 +621,9 @@ namespace Sass {
extern const char color_name[] = "color"; extern const char color_name[] = "color";
extern const char list_name[] = "list"; extern const char list_name[] = "list";
Function_Descriptor type_of_descriptor = extern Signature type_of_sig = "type-of($value)";
{ "type-of", "$value", 0 }; Node type_of(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node type_of(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node val(bindings[parameter_names[0].token()]);
Node val(bindings[parameters[0].token()]);
Token type_name; Token type_name;
switch (val.type()) switch (val.type())
{ {
...@@ -765,10 +659,9 @@ namespace Sass { ...@@ -765,10 +659,9 @@ namespace Sass {
extern const char empty_str[] = ""; extern const char empty_str[] = "";
extern const char percent_str[] = "%"; extern const char percent_str[] = "%";
Function_Descriptor unit_descriptor = extern Signature unit_sig = "unit($number)";
{ "unit", "$number", 0 }; Node unit(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node unit(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node val(bindings[parameter_names[0].token()]);
Node val(bindings[parameters[0].token()]);
switch (val.type()) switch (val.type())
{ {
case Node::number: { case Node::number: {
...@@ -791,10 +684,9 @@ namespace Sass { ...@@ -791,10 +684,9 @@ namespace Sass {
extern const char true_str[] = "true"; extern const char true_str[] = "true";
extern const char false_str[] = "false"; extern const char false_str[] = "false";
Function_Descriptor unitless_descriptor = extern Signature unitless_sig = "unitless($number)";
{ "unitless", "$number", 0 }; Node unitless(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node unitless(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node val(bindings[parameter_names[0].token()]);
Node val(bindings[parameters[0].token()]);
switch (val.type()) switch (val.type())
{ {
case Node::number: { case Node::number: {
...@@ -814,11 +706,10 @@ namespace Sass { ...@@ -814,11 +706,10 @@ namespace Sass {
return Node(); return Node();
} }
Function_Descriptor comparable_descriptor = extern Signature comparable_sig = "comparable($number-1, $number-2)";
{ "comparable", "$number_1", "$number_2", 0 }; Node comparable(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node comparable(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node n1(bindings[parameter_names[0].token()]);
Node n1(bindings[parameters[0].token()]); Node n2(bindings[parameter_names[1].token()]);
Node n2(bindings[parameters[1].token()]);
Node::Type t1 = n1.type(); Node::Type t1 = n1.type();
Node::Type t2 = n2.type(); Node::Type t2 = n2.type();
if ((t1 == Node::number && n2.is_numeric()) || if ((t1 == Node::number && n2.is_numeric()) ||
...@@ -849,10 +740,9 @@ namespace Sass { ...@@ -849,10 +740,9 @@ namespace Sass {
} }
// Boolean Functions /////////////////////////////////////////////////// // Boolean Functions ///////////////////////////////////////////////////
Function_Descriptor not_descriptor = extern Signature not_sig = "not($value)";
{ "not", "$value", 0 }; Node not_impl(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node not_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node val(bindings[parameter_names[0].token()]);
Node val(bindings[parameters[0].token()]);
if (val.type() == Node::boolean && val.boolean_value() == false) { if (val.type() == Node::boolean && val.boolean_value() == false) {
return new_Node(Node::boolean, val.path(), val.line(), true); return new_Node(Node::boolean, val.path(), val.line(), true);
} }
...@@ -861,12 +751,11 @@ namespace Sass { ...@@ -861,12 +751,11 @@ namespace Sass {
} }
} }
Function_Descriptor if_descriptor = extern Signature if_sig = "if($condition, $if-true, $if-false)";
{ "if", "$predicate", "$consequent", "$alternative", 0 }; Node if_impl(const Node parameter_names, Environment& bindings, Node_Factory& new_Node) {
Node if_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node predicate(bindings[parameter_names[0].token()]);
Node predicate(bindings[parameters[0].token()]); Node consequent(bindings[parameter_names[1].token()]);
Node consequent(bindings[parameters[1].token()]); Node alternative(bindings[parameter_names[2].token()]);
Node alternative(bindings[parameters[2].token()]);
if (predicate.type() == Node::boolean && predicate.boolean_value() == false) return alternative; if (predicate.type() == Node::boolean && predicate.boolean_value() == false) return alternative;
return consequent; return consequent;
......
...@@ -13,10 +13,10 @@ namespace Sass { ...@@ -13,10 +13,10 @@ namespace Sass {
using std::map; using std::map;
typedef Node (*Primitive)(const Node, map<Token, Node>&, Node_Factory& new_Node); // typedef Node (*Primitive)(const Node, map<Token, Node>&, Node_Factory& new_Node);
typedef Node (*Primitive_2)(const Node, Environment&, Node_Factory&); typedef Node (*Primitive)(const Node, Environment&, Node_Factory&);
typedef const char* str; typedef const char* str;
typedef str Function_Descriptor[]; typedef const char Signature[];
struct Function { struct Function {
...@@ -26,7 +26,7 @@ namespace Sass { ...@@ -26,7 +26,7 @@ namespace Sass {
Node parameter_names; Node parameter_names;
Node definition; Node definition;
Primitive primitive; Primitive primitive;
Primitive_2 primitive_2; // Primitive_2 primitive_2;
bool overloaded; bool overloaded;
Function() Function()
...@@ -38,7 +38,6 @@ namespace Sass { ...@@ -38,7 +38,6 @@ namespace Sass {
parameters(def[1]), parameters(def[1]),
definition(def), definition(def),
primitive(0), primitive(0),
primitive_2(0),
overloaded(false) overloaded(false)
{ } { }
...@@ -48,30 +47,28 @@ namespace Sass { ...@@ -48,30 +47,28 @@ namespace Sass {
parameters(Node()), parameters(Node()),
definition(Node()), definition(Node()),
primitive(0), primitive(0),
primitive_2(0),
overloaded(overloaded) overloaded(overloaded)
{ } { }
Function(char* signature, Primitive_2 ip, Context& ctx); Function(char* signature, Primitive ip, Context& ctx);
Function(Function_Descriptor d, Primitive ip, Node_Factory& new_Node) // Function(Function_Descriptor d, Primitive ip, Node_Factory& new_Node)
: name(d[0]), // : name(d[0]),
parameters(new_Node(Node::parameters, "[PRIMITIVE FUNCTIONS]", 0, 0)), // parameters(new_Node(Node::parameters, "[PRIMITIVE FUNCTIONS]", 0, 0)),
definition(Node()), // definition(Node()),
primitive(ip), // primitive(ip),
primitive_2(0), // overloaded(false)
overloaded(false) // {
{ // size_t len = 0;
size_t len = 0; // while (d[len+1]) ++len;
while (d[len+1]) ++len;
for (size_t i = 0; i < len; ++i) { // for (size_t i = 0; i < len; ++i) {
const char* p = d[i+1]; // const char* p = d[i+1];
parameters.push_back(new_Node(Node::variable, "[PRIMITIVE FUNCTIONS]", 0, Token::make(p, p + std::strlen(p)))); // parameters.push_back(new_Node(Node::variable, "[PRIMITIVE FUNCTIONS]", 0, Token::make(p, p + std::strlen(p))));
} // }
} // }
Node operator()(map<Token, Node>& bindings, Node_Factory& new_Node) const Node operator()(Environment& bindings, Node_Factory& new_Node) const
{ {
if (primitive) return primitive(parameters, bindings, new_Node); if (primitive) return primitive(parameters, bindings, new_Node);
else return Node(); else return Node();
...@@ -86,138 +83,118 @@ namespace Sass { ...@@ -86,138 +83,118 @@ namespace Sass {
// RGB Functions /////////////////////////////////////////////////////// // RGB Functions ///////////////////////////////////////////////////////
extern Function_Descriptor rgb_descriptor; extern Signature rgb_sig;
Node rgb(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node rgb(const Node, Environment&, Node_Factory&);
extern Function_Descriptor rgba_4_descriptor; extern Signature rgba_4_sig;
Node rgba_4(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node rgba_4(const Node, Environment&, Node_Factory&);
extern Function_Descriptor rgba_2_descriptor;
Node rgba_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor red_descriptor; extern Signature rgba_2_sig;
Node red(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node rgba_2(const Node, Environment&, Node_Factory&);
extern Function_Descriptor green_descriptor; extern Signature red_sig;
Node green(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node red(const Node, Environment&, Node_Factory&);
extern Function_Descriptor blue_descriptor; extern Signature green_sig;
Node blue(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node green(const Node, Environment&, Node_Factory&);
extern Function_Descriptor mix_2_descriptor; extern Signature blue_sig;
Node mix_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node blue(const Node, Environment&, Node_Factory&);
extern Function_Descriptor mix_3_descriptor; extern Signature mix_sig;
Node mix_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node mix(const Node, Environment&, Node_Factory&);
// HSL Functions /////////////////////////////////////////////////////// // HSL Functions ///////////////////////////////////////////////////////
extern Function_Descriptor hsla_descriptor; extern Signature hsla_sig;
Node hsla(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node hsla(const Node, Environment&, Node_Factory&);
extern Function_Descriptor hsl_descriptor; extern Signature hsl_sig;
Node hsl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node hsl(const Node, Environment&, Node_Factory&);
extern Function_Descriptor adjust_hue_descriptor; extern Signature adjust_hue_sig;
Node adjust_hue(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node adjust_hue(const Node, Environment&, Node_Factory&);
extern Function_Descriptor invert_descriptor; extern Signature invert_sig;
Node invert(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node invert(const Node, Environment&, Node_Factory&);
// Opacity Functions /////////////////////////////////////////////////// // Opacity Functions ///////////////////////////////////////////////////
extern Function_Descriptor alpha_descriptor; extern Signature alpha_sig;
extern Function_Descriptor opacity_descriptor; extern Signature opacity_sig;
Node alpha(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node alpha(const Node, Environment&, Node_Factory&);
extern Function_Descriptor opacify_descriptor; extern Signature opacify_sig;
extern Function_Descriptor fade_in_descriptor; extern Signature fade_in_sig;
Node opacify(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node opacify(const Node, Environment&, Node_Factory&);
extern Function_Descriptor transparentize_descriptor; extern Signature transparentize_sig;
extern Function_Descriptor fade_out_descriptor; extern Signature fade_out_sig;
Node transparentize(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node transparentize(const Node, Environment&, Node_Factory&);
// String Functions //////////////////////////////////////////////////// // String Functions ////////////////////////////////////////////////////
extern Function_Descriptor unquote_descriptor; extern Signature unquote_sig;
Node unquote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node unquote(const Node, Environment&, Node_Factory&);
extern Function_Descriptor quote_descriptor; extern Signature quote_sig;
Node quote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node quote(const Node, Environment&, Node_Factory&);
// Number Functions //////////////////////////////////////////////////// // Number Functions ////////////////////////////////////////////////////
extern Function_Descriptor percentage_descriptor; extern Signature percentage_sig;
Node percentage(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node percentage(const Node, Environment&, Node_Factory&);
extern Function_Descriptor round_descriptor; extern Signature round_sig;
Node round(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node round(const Node, Environment&, Node_Factory&);
extern Function_Descriptor ceil_descriptor; extern Signature ceil_sig;
Node ceil(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node ceil(const Node, Environment&, Node_Factory&);
extern Function_Descriptor floor_descriptor; extern Signature floor_sig;
Node floor(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node floor(const Node, Environment&, Node_Factory&);
extern Function_Descriptor abs_descriptor; extern Signature abs_sig;
Node abs(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node abs(const Node, Environment&, Node_Factory&);
// List Functions ////////////////////////////////////////////////////// // List Functions //////////////////////////////////////////////////////
extern Function_Descriptor length_descriptor; extern Signature length_sig;
Node length(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node length(const Node, Environment&, Node_Factory&);
extern Function_Descriptor nth_descriptor; extern Signature nth_sig;
Node nth(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node nth(const Node, Environment&, Node_Factory&);
extern Function_Descriptor join_2_descriptor;
Node join_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_3_descriptor;
Node join_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor append_2_descriptor; extern Signature join_sig;
Node append_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node join(const Node, Environment&, Node_Factory&);
extern Function_Descriptor append_3_descriptor; extern Signature append_sig;
Node append_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node append(const Node, Environment&, Node_Factory&);
extern Function_Descriptor compact_1_descriptor; extern Signature compact_sig;
extern Function_Descriptor compact_2_descriptor; Node compact(const Node, Environment&, Node_Factory&);
extern Function_Descriptor compact_3_descriptor;
extern Function_Descriptor compact_4_descriptor;
extern Function_Descriptor compact_5_descriptor;
extern Function_Descriptor compact_6_descriptor;
extern Function_Descriptor compact_7_descriptor;
extern Function_Descriptor compact_8_descriptor;
extern Function_Descriptor compact_9_descriptor;
extern Function_Descriptor compact_10_descriptor;
extern Function_Descriptor compact_11_descriptor;
extern Function_Descriptor compact_12_descriptor;
Node compact(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Introspection Functions ///////////////////////////////////////////// // Introspection Functions /////////////////////////////////////////////
extern Function_Descriptor type_of_descriptor; extern Signature type_of_sig;
Node type_of(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node type_of(const Node, Environment&, Node_Factory&);
extern Function_Descriptor unit_descriptor; extern Signature unit_sig;
Node unit(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node unit(const Node, Environment&, Node_Factory&);
extern Function_Descriptor unitless_descriptor; extern Signature unitless_sig;
Node unitless(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node unitless(const Node, Environment&, Node_Factory&);
extern Function_Descriptor comparable_descriptor; extern Signature comparable_sig;
Node comparable(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node comparable(const Node, Environment&, Node_Factory&);
// Boolean Functions /////////////////////////////////////////////////// // Boolean Functions ///////////////////////////////////////////////////
extern Function_Descriptor not_descriptor; extern Signature not_sig;
Node not_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node not_impl(const Node, Environment&, Node_Factory&);
extern Function_Descriptor if_descriptor; extern Signature if_sig;
Node if_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node if_impl(const Node, Environment&, Node_Factory&);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment