Commit c83420f6 by Aaron Leung

Pushing the refactor through the builtin functions.

parent 6ff683eb
...@@ -10,118 +10,115 @@ using std::cerr; using std::endl; ...@@ -10,118 +10,115 @@ using std::cerr; using std::endl;
namespace Sass { namespace Sass {
namespace Functions { namespace Functions {
static void eval_error(string message, size_t line_number, const char* file_name) static void throw_eval_error(string message, string path, size_t line)
{ {
string fn; if (!path.empty() && Prelexer::string_constant(file_name))
if (file_name) { path = path.substr(1, path.length() - 1);
const char* end = Prelexer::string_constant(file_name);
if (end) fn = string(file_name, end - file_name); throw Error(Error::evaluation, path, line, message);
else fn = string(file_name);
}
throw Error(Error::evaluation, line_number, fn, message);
} }
// RGB Functions /////////////////////////////////////////////////////// // RGB Functions ///////////////////////////////////////////////////////
Function_Descriptor rgb_descriptor = Function_Descriptor rgb_descriptor =
{ "rgb", "$red", "$green", "$blue", 0 }; { "rgb", "$red", "$green", "$blue", 0 };
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0]]); Node r(bindings[parameters[0]]);
Node g(bindings[parameters[1]]); Node g(bindings[parameters[1]]);
Node b(bindings[parameters[2]]); Node b(bindings[parameters[2]]);
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)) {
eval_error("arguments for rgb must be numbers", r.line_number, r.file_name); throw_eval_error("arguments for rgb must be numbers", r.path(), r.line());
} }
Node color(Node::numeric_color, registry, 0, 4); return new_Node(r.path(), r.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), 1.0);
color << r << g << b << Node(0, 1.0);
return color;
} }
Function_Descriptor rgba_4_descriptor = Function_Descriptor rgba_4_descriptor =
{ "rgba", "$red", "$green", "$blue", "$alpha", 0 }; { "rgba", "$red", "$green", "$blue", "$alpha", 0 };
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0]]); Node r(bindings[parameters[0]]);
Node g(bindings[parameters[1]]); Node g(bindings[parameters[1]]);
Node b(bindings[parameters[2]]); Node b(bindings[parameters[2]]);
Node a(bindings[parameters[3]]); Node a(bindings[parameters[3]]);
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)) {
eval_error("arguments for rgba must be numbers", r.line_number, r.file_name); throw_eval_error("arguments for rgba must be numbers", r.path(), r.line());
} }
Node color(Node::numeric_color, registry, 0, 4); return new_Node(r.path(), r.line(), r.numeric_value(), g.numeric_value(), b.numeric_value(), a.numeric_value());
color << r << g << b << a;
return color;
} }
Function_Descriptor rgba_2_descriptor = Function_Descriptor rgba_2_descriptor =
{ "rgba", "$color", "$alpha", 0 }; { "rgba", "$color", "$alpha", 0 };
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]].clone(registry)); Node color(bindings[parameters[0]]);
color[3] = bindings[parameters[1]]; Node r(color[0]);
return color; Node g(color[1]);
Node b(color[2]);
Node a(bindings[parameters[1]]);
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());
} }
Function_Descriptor red_descriptor = Function_Descriptor red_descriptor =
{ "red", "$color", 0 }; { "red", "$color", 0 };
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); Node color(bindings[parameters[0]]);
if (color.type != Node::numeric_color) eval_error("argument to red must be a color", color.line_number, color.file_name); 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 = Function_Descriptor green_descriptor =
{ "green", "$color", 0 }; { "green", "$color", 0 };
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); Node color(bindings[parameters[0]]);
if (color.type != Node::numeric_color) eval_error("argument to green must be a color", color.line_number, color.file_name); 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 = Function_Descriptor blue_descriptor =
{ "blue", "$color", 0 }; { "blue", "$color", 0 };
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); Node color(bindings[parameters[0]]);
if (color.type != Node::numeric_color) eval_error("argument to blue must be a color", color.line_number, color.file_name); 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, vector<vector<Node>*>& registry) { Node mix_impl(Node color1, Node color2, double weight, Node_Factory& new_Node) {
if (!(color1.type == Node::numeric_color && color2.type == Node::numeric_color)) { if (!(color1.type() == Node::numeric_color && color2.type() == Node::numeric_color)) {
eval_error("first two arguments to mix must be colors", color1.line_number, color1.file_name); throw_eval_error("first two arguments to mix must be colors", color1.path(), color1.line());
} }
double p = weight/100; double p = weight/100;
double w = 2*p - 1; double w = 2*p - 1;
double a = color1[3].content.numeric_value - color2[3].content.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(Node::numeric_color, registry, color1.line_number, 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 << Node(mixed.line_number, w1*color1[i].content.numeric_value + mixed << new_Node(mixed.path(), mixed.line(),
w2*color2[i].content.numeric_value); w1*color1[i].numeric_value() + w2*color2[i].numeric_value());
} }
double alpha = color1[3].content.numeric_value*p + color2[3].content.numeric_value*(1-p); double alpha = color1[3].numeric_value()*p + color2[3].numeric_value()*(1-p);
mixed << Node(mixed.line_number, alpha); mixed << new_Node(mixed.path(), mixed.line(), alpha);
return mixed; return mixed;
} }
Function_Descriptor mix_2_descriptor = Function_Descriptor mix_2_descriptor =
{ "mix", "$color1", "$color2", 0 }; { "mix", "$color1", "$color2", 0 };
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return mix_impl(bindings[parameters[0]], bindings[parameters[1]], 50, registry); return mix_impl(bindings[parameters[0]], bindings[parameters[1]], 50, new_Node);
} }
Function_Descriptor mix_3_descriptor = Function_Descriptor mix_3_descriptor =
{ "mix", "$color1", "$color2", "$weight", 0 }; { "mix", "$color1", "$color2", "$weight", 0 };
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node percentage(bindings[parameters[2]]); Node percentage(bindings[parameters[2]]);
if (!(percentage.type == Node::number || percentage.type == Node::numeric_percentage || percentage.type == Node::numeric_dimension)) { if (!(percentage.type() == Node::number || percentage.type() == Node::numeric_percentage || percentage.type() == Node::numeric_dimension)) {
eval_error("third argument to mix must be numeric", percentage.line_number, percentage.file_name); throw_eval_error("third argument to mix must be numeric", percentage.path(), percentage.line());
} }
return mix_impl(bindings[parameters[0]], return mix_impl(bindings[parameters[0]],
bindings[parameters[1]], bindings[parameters[1]],
percentage.numeric_value(), percentage.numeric_value(),
registry); new_Node);
} }
// HSL Functions /////////////////////////////////////////////////////// // HSL Functions ///////////////////////////////////////////////////////
...@@ -135,7 +132,7 @@ namespace Sass { ...@@ -135,7 +132,7 @@ namespace Sass {
return m1; return m1;
} }
Node hsla_impl(double h, double s, double l, double a, vector<vector<Node>*>& registry) { Node hsla_impl(double h, double s, double l, double a, Node_Factory& new_Node) {
h = static_cast<double>(((static_cast<int>(h) % 360) + 360) % 360) / 360.0; h = static_cast<double>(((static_cast<int>(h) % 360) + 360) % 360) / 360.0;
s = s / 100.0; s = s / 100.0;
l = l / 100.0; l = l / 100.0;
...@@ -148,53 +145,53 @@ namespace Sass { ...@@ -148,53 +145,53 @@ namespace Sass {
double g = h_to_rgb(m1, m2, h) * 255.0; double g = h_to_rgb(m1, m2, h) * 255.0;
double b = h_to_rgb(m1, m2, h-1.0/3.0) * 255.0; double b = h_to_rgb(m1, m2, h-1.0/3.0) * 255.0;
return Node(registry, 0, r, g, b, a); return new_Node("", 0, r, g, b, a);
} }
Function_Descriptor hsla_descriptor = Function_Descriptor hsla_descriptor =
{ "hsla", "$hue", "$saturation", "$lightness", "$alpha", 0 }; { "hsla", "$hue", "$saturation", "$lightness", "$alpha", 0 };
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
if (!(bindings[parameters[0]].is_numeric() && if (!(bindings[parameters[0]].is_numeric() &&
bindings[parameters[1]].is_numeric() && bindings[parameters[1]].is_numeric() &&
bindings[parameters[2]].is_numeric() && bindings[parameters[2]].is_numeric() &&
bindings[parameters[3]].is_numeric())) { bindings[parameters[3]].is_numeric())) {
eval_error("arguments to hsla must be numeric", bindings[parameters[0]].line_number, bindings[parameters[0]].file_name); throw_eval_error("arguments to hsla must be numeric", bindings[parameters[0]].path(), bindings[parameters[0]].line());
} }
double h = bindings[parameters[0]].numeric_value(); double h = bindings[parameters[0]].numeric_value();
double s = bindings[parameters[1]].numeric_value(); double s = bindings[parameters[1]].numeric_value();
double l = bindings[parameters[2]].numeric_value(); double l = bindings[parameters[2]].numeric_value();
double a = bindings[parameters[3]].numeric_value(); double a = bindings[parameters[3]].numeric_value();
Node color(hsla_impl(h, s, l, a, registry)); Node color(hsla_impl(h, s, l, a, new_Node));
color.line_number = bindings[parameters[0]].line_number; // color.line() = bindings[parameters[0]].line();
return color; return color;
} }
Function_Descriptor hsl_descriptor = Function_Descriptor hsl_descriptor =
{ "hsl", "$hue", "$saturation", "$lightness", 0 }; { "hsl", "$hue", "$saturation", "$lightness", 0 };
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
if (!(bindings[parameters[0]].is_numeric() && if (!(bindings[parameters[0]].is_numeric() &&
bindings[parameters[1]].is_numeric() && bindings[parameters[1]].is_numeric() &&
bindings[parameters[2]].is_numeric())) { bindings[parameters[2]].is_numeric())) {
eval_error("arguments to hsl must be numeric", bindings[parameters[0]].line_number, bindings[parameters[0]].file_name); throw_eval_error("arguments to hsl must be numeric", bindings[parameters[0]].path(), bindings[parameters[0]].line());
} }
double h = bindings[parameters[0]].numeric_value(); double h = bindings[parameters[0]].numeric_value();
double s = bindings[parameters[1]].numeric_value(); double s = bindings[parameters[1]].numeric_value();
double l = bindings[parameters[2]].numeric_value(); double l = bindings[parameters[2]].numeric_value();
Node color(hsla_impl(h, s, l, 1, registry)); Node color(hsla_impl(h, s, l, 1, new_Node));
color.line_number = bindings[parameters[0]].line_number; // color.line() = bindings[parameters[0]].line();
return color; return color;
} }
Function_Descriptor invert_descriptor = Function_Descriptor invert_descriptor =
{ "invert", "$color", 0 }; { "invert", "$color", 0 };
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]); Node orig(bindings[parameters[0]]);
if (orig.type != Node::numeric_color) eval_error("argument to invert must be a color", orig.line_number, orig.file_name); if (orig.type() != Node::numeric_color) throw_eval_error("argument to invert must be a color", orig.line_number, orig.file_name);
return Node(registry, orig.line_number, return Node(new_Node, orig.line_number,
255 - orig[0].content.numeric_value, 255 - orig[0].numeric_value(),
255 - orig[1].content.numeric_value, 255 - orig[1].numeric_value(),
255 - orig[2].content.numeric_value, 255 - orig[2].numeric_value(),
orig[3].content.numeric_value); orig[3].numeric_value());
} }
// Opacity Functions /////////////////////////////////////////////////// // Opacity Functions ///////////////////////////////////////////////////
...@@ -203,9 +200,9 @@ namespace Sass { ...@@ -203,9 +200,9 @@ namespace Sass {
{ "alpha", "$color", 0 }; { "alpha", "$color", 0 };
Function_Descriptor opacity_descriptor = Function_Descriptor opacity_descriptor =
{ "opacity", "$color", 0 }; { "opacity", "$color", 0 };
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); Node color(bindings[parameters[0]]);
if (color.type != Node::numeric_color) eval_error("argument to alpha must be a color", color.line_number, color.file_name); 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];
} }
...@@ -213,16 +210,16 @@ namespace Sass { ...@@ -213,16 +210,16 @@ namespace Sass {
{ "opacify", "$color", "$amount", 0 }; { "opacify", "$color", "$amount", 0 };
Function_Descriptor fade_in_descriptor = Function_Descriptor fade_in_descriptor =
{ "fade_in", "$color", "$amount", 0 }; { "fade_in", "$color", "$amount", 0 };
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(bindings[parameters[0]].clone(registry)); Node cpy(new_Node(bindings[parameters[0]]));
if (cpy.type != Node::numeric_color || !bindings[parameters[1]].is_numeric()) { if (cpy.type() != Node::numeric_color || !bindings[parameters[1]].is_numeric()) {
eval_error("arguments to opacify/fade_in must be a color and a numeric value", cpy.line_number, cpy.file_name); throw_eval_error("arguments to opacify/fade_in must be a color and a numeric value", cpy.path(), cpy.line());
} }
Node delta(bindings[parameters[1]]); Node delta(bindings[parameters[1]]);
if (delta.numeric_value() < 0 || delta.numeric_value() > 1) eval_error("amount must be between 0 and 1 for opacify/fade-in", delta.line_number, delta.file_name); if (delta.numeric_value() < 0 || delta.numeric_value() > 1) throw_eval_error("amount must be between 0 and 1 for opacify/fade-in", delta.path(), delta.line());
cpy[3].content.numeric_value += delta.numeric_value(); cpy[3].numeric_value() += delta.numeric_value();
if (cpy[3].numeric_value() > 1) cpy[3].content.numeric_value = 1; if (cpy[3].numeric_value() > 1) cpy[3].numeric_value() = 1;
if (cpy[3].numeric_value() < 0) cpy[3].content.numeric_value = 0; if (cpy[3].numeric_value() < 0) cpy[3].numeric_value() = 0;
return cpy; return cpy;
} }
...@@ -230,16 +227,16 @@ namespace Sass { ...@@ -230,16 +227,16 @@ namespace Sass {
{ "transparentize", "$color", "$amount", 0 }; { "transparentize", "$color", "$amount", 0 };
Function_Descriptor fade_out_descriptor = Function_Descriptor fade_out_descriptor =
{ "fade_out", "$color", "$amount", 0 }; { "fade_out", "$color", "$amount", 0 };
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(bindings[parameters[0]].clone(registry)); Node cpy(new_Node(bindings[parameters[0]]));
if (cpy.type != Node::numeric_color || !bindings[parameters[1]].is_numeric()) { if (cpy.type() != Node::numeric_color || !bindings[parameters[1]].is_numeric()) {
eval_error("arguments to transparentize/fade_out must be a color and a numeric value", cpy.line_number, cpy.file_name); throw_eval_error("arguments to transparentize/fade_out must be a color and a numeric value", cpy.path(), cpy.line());
} }
Node delta(bindings[parameters[1]]); Node delta(bindings[parameters[1]]);
if (delta.numeric_value() < 0 || delta.numeric_value() > 1) eval_error("amount must be between 0 and 1 for transparentize/fade-out", delta.line_number, delta.file_name); if (delta.numeric_value() < 0 || delta.numeric_value() > 1) throw_eval_error("amount must be between 0 and 1 for transparentize/fade-out", delta.path(), delta.line());
cpy[3].content.numeric_value -= delta.numeric_value(); cpy[3].numeric_value() -= delta.numeric_value();
if (cpy[3].numeric_value() > 1) cpy[3].content.numeric_value = 1; if (cpy[3].numeric_value() > 1) cpy[3].numeric_value() = 1;
if (cpy[3].numeric_value() < 0) cpy[3].content.numeric_value = 0; if (cpy[3].numeric_value() < 0) cpy[3].numeric_value() = 0;
return cpy; return cpy;
} }
...@@ -247,24 +244,24 @@ namespace Sass { ...@@ -247,24 +244,24 @@ namespace Sass {
Function_Descriptor unquote_descriptor = Function_Descriptor unquote_descriptor =
{ "unquote", "$string", 0 }; { "unquote", "$string", 0 };
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(bindings[parameters[0]].clone(registry)); Node cpy(new_Node(bindings[parameters[0]]));
// if (cpy.type != Node::string_constant /* && cpy.type != Node::concatenation */) { // if (cpy.type() != Node::string_constant /* && cpy.type() != Node::concatenation */) {
// eval_error("argument to unquote must be a string", cpy.line_number, cpy.file_name); // throw_eval_error("argument to unquote must be a string", cpy.path(), cpy.line());
// } // }
cpy.unquoted = true; cpy.is_unquoted() = true;
return cpy; return cpy;
} }
Function_Descriptor quote_descriptor = Function_Descriptor quote_descriptor =
{ "quote", "$string", 0 }; { "quote", "$string", 0 };
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(bindings[parameters[0]].clone(registry)); Node orig(bindings[parameters[0]]);
if (cpy.type != Node::string_constant && cpy.type != Node::identifier) { if (orig.type() != Node::string_constant && orig.type() != Node::identifier) {
eval_error("argument to quote must be a string or identifier", cpy.line_number, cpy.file_name); throw_eval_error("argument to quote must be a string or identifier", orig.path(), orig.line());
} }
cpy.type = Node::string_constant; Node cpy(new_Node(Node::string_constant, orig.path(), orig.line(), orig.token())
cpy.unquoted = false; cpy.is_unquoted() = false;
return cpy; return cpy;
} }
...@@ -272,75 +269,75 @@ namespace Sass { ...@@ -272,75 +269,75 @@ namespace Sass {
Function_Descriptor percentage_descriptor = Function_Descriptor percentage_descriptor =
{ "percentage", "$value", 0 }; { "percentage", "$value", 0 };
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(bindings[parameters[0]].clone(registry)); Node cpy(bindings[parameters[0]].clone(new_Node));
// TO DO: make sure it's not already a percentage // TO DO: make sure it's not already a percentage
if (cpy.type != Node::number) eval_error("argument to percentage must be a unitless number", cpy.line_number, cpy.file_name); if (cpy.type() != Node::number) throw_eval_error("argument to percentage must be a unitless number", cpy.path(), cpy.line());
cpy.content.numeric_value = cpy.content.numeric_value * 100; cpy.numeric_value() = cpy.numeric_value() * 100;
cpy.type = Node::numeric_percentage; cpy.type() = Node::numeric_percentage;
return cpy; return cpy;
} }
Function_Descriptor round_descriptor = Function_Descriptor round_descriptor =
{ "round", "$value", 0 }; { "round", "$value", 0 };
Node round(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node round(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(bindings[parameters[0]].clone(registry)); Node cpy(bindings[parameters[0]].clone(new_Node));
if (cpy.type == Node::numeric_dimension) { if (cpy.type() == Node::numeric_dimension) {
cpy.content.dimension.numeric_value = std::floor(cpy.content.dimension.numeric_value + 0.5); cpy.content.dimension.numeric_value = std::floor(cpy.content.dimension.numeric_value + 0.5);
} }
else if (cpy.type == Node::number || cpy.type == Node::numeric_percentage) { else if (cpy.type() == Node::number || cpy.type() == Node::numeric_percentage) {
cpy.content.numeric_value = std::floor(cpy.content.numeric_value + 0.5); cpy.numeric_value() = std::floor(cpy.numeric_value() + 0.5);
} }
else { else {
eval_error("argument to round must be numeric", cpy.line_number, cpy.file_name); throw_eval_error("argument to round must be numeric", cpy.path(), cpy.line());
} }
return cpy; return cpy;
} }
Function_Descriptor ceil_descriptor = Function_Descriptor ceil_descriptor =
{ "ceil", "$value", 0 }; { "ceil", "$value", 0 };
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(bindings[parameters[0]].clone(registry)); Node cpy(bindings[parameters[0]].clone(new_Node));
if (cpy.type == Node::numeric_dimension) { if (cpy.type() == Node::numeric_dimension) {
cpy.content.dimension.numeric_value = std::ceil(cpy.content.dimension.numeric_value); cpy.content.dimension.numeric_value = std::ceil(cpy.content.dimension.numeric_value);
} }
else if (cpy.type == Node::number || cpy.type == Node::numeric_percentage){ else if (cpy.type() == Node::number || cpy.type() == Node::numeric_percentage){
cpy.content.numeric_value = std::ceil(cpy.content.numeric_value); cpy.numeric_value() = std::ceil(cpy.numeric_value());
} }
else { else {
eval_error("argument to ceil must be numeric", cpy.line_number, cpy.file_name); throw_eval_error("argument to ceil must be numeric", cpy.path(), cpy.line());
} }
return cpy; return cpy;
} }
Function_Descriptor floor_descriptor = Function_Descriptor floor_descriptor =
{ "floor", "$value", 0 }; { "floor", "$value", 0 };
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(bindings[parameters[0]].clone(registry)); Node cpy(bindings[parameters[0]].clone(new_Node));
if (cpy.type == Node::numeric_dimension) { if (cpy.type() == Node::numeric_dimension) {
cpy.content.dimension.numeric_value = std::floor(cpy.content.dimension.numeric_value); cpy.content.dimension.numeric_value = std::floor(cpy.content.dimension.numeric_value);
} }
else if (cpy.type == Node::number || cpy.type == Node::numeric_percentage){ else if (cpy.type() == Node::number || cpy.type() == Node::numeric_percentage){
cpy.content.numeric_value = std::floor(cpy.content.numeric_value); cpy.numeric_value() = std::floor(cpy.numeric_value());
} }
else { else {
eval_error("argument to floor must be numeric", cpy.line_number, cpy.file_name); throw_eval_error("argument to floor must be numeric", cpy.path(), cpy.line());
} }
return cpy; return cpy;
} }
Function_Descriptor abs_descriptor = Function_Descriptor abs_descriptor =
{ "abs", "$value", 0 }; { "abs", "$value", 0 };
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(bindings[parameters[0]].clone(registry)); Node cpy(bindings[parameters[0]].clone(new_Node));
if (cpy.type == Node::numeric_dimension) { if (cpy.type() == Node::numeric_dimension) {
cpy.content.dimension.numeric_value = std::fabs(cpy.content.dimension.numeric_value); cpy.content.dimension.numeric_value = std::fabs(cpy.content.dimension.numeric_value);
} }
else if (cpy.type == Node::number || cpy.type == Node::numeric_percentage){ else if (cpy.type() == Node::number || cpy.type() == Node::numeric_percentage){
cpy.content.numeric_value = std::abs(cpy.content.numeric_value); cpy.numeric_value() = std::abs(cpy.numeric_value());
} }
else { else {
eval_error("argument to abs must be numeric", cpy.line_number, cpy.file_name); throw_eval_error("argument to abs must be numeric", cpy.path(), cpy.line());
} }
return cpy; return cpy;
} }
...@@ -349,12 +346,12 @@ namespace Sass { ...@@ -349,12 +346,12 @@ namespace Sass {
Function_Descriptor length_descriptor = Function_Descriptor length_descriptor =
{ "length", "$list", 0 }; { "length", "$list", 0 };
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node length(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node arg(bindings[parameters[0]]); Node arg(bindings[parameters[0]]);
if (arg.type == Node::space_list || arg.type == Node::comma_list) { if (arg.type() == Node::space_list || arg.type() == Node::comma_list) {
return Node(arg.line_number, arg.size()); return Node(arg.line_number, arg.size());
} }
else if (arg.type == Node::nil) { else if (arg.type() == Node::nil) {
return Node(arg.line_number, 0); return Node(arg.line_number, 0);
} }
// single objects should be reported as lists of length 1 // single objects should be reported as lists of length 1
...@@ -365,66 +362,66 @@ namespace Sass { ...@@ -365,66 +362,66 @@ namespace Sass {
Function_Descriptor nth_descriptor = Function_Descriptor nth_descriptor =
{ "nth", "$list", "$n", 0 }; { "nth", "$list", "$n", 0 };
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node l(bindings[parameters[0]]); Node l(bindings[parameters[0]]);
// TO DO: check for empty list // TO DO: check for empty list
if (l.type == Node::nil) eval_error("cannot index into an empty list", l.line_number, l.file_name); if (l.type() == Node::nil) throw_eval_error("cannot index into an empty list", l.line_number, l.file_name);
if (l.type != Node::space_list && l.type != Node::comma_list) { if (l.type() != Node::space_list && l.type() != Node::comma_list) {
l = Node(Node::space_list, registry, l.line_number, 1) << l; l = Node(Node::space_list, new_Node, l.line_number, 1) << l;
} }
Node n(bindings[parameters[1]]); Node n(bindings[parameters[1]]);
if (n.type != Node::number) eval_error("second argument to nth must be a number", n.line_number, n.file_name); if (n.type() != Node::number) throw_eval_error("second argument to nth must be a number", n.line_number, n.file_name);
if (n.numeric_value() < 1 || n.numeric_value() > l.size()) eval_error("out of range index for nth", n.line_number, n.file_name); if (n.numeric_value() < 1 || n.numeric_value() > l.size()) throw_eval_error("out of range index for nth", n.line_number, n.file_name);
return l[bindings[parameters[1]].content.numeric_value - 1]; return l[bindings[parameters[1]].numeric_value() - 1];
} }
extern const char separator_kwd[] = "$separator"; extern const char separator_kwd[] = "$separator";
Node join_impl(const vector<Token>& parameters, map<Token, Node>& bindings, bool has_sep, vector<vector<Node>*>& registry) { Node join_impl(const vector<Token>& parameters, map<Token, Node>& bindings, bool has_sep, 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]]); Node l1(bindings[parameters[0]]);
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 = Node(Node::space_list, registry, l1.line_number, 1) << l1; l1 = Node(Node::space_list, new_Node, l1.line_number, 1) << l1;
} }
Node l2(bindings[parameters[1]]); Node l2(bindings[parameters[1]]);
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 = Node(Node::space_list, registry, l2.line_number, 1) << l2; l2 = Node(Node::space_list, new_Node, l2.line_number, 1) << l2;
} }
// nil and nil is nil // nil and nil is nil
if (l1.type == Node::nil && l2.type == Node::nil) return Node(Node::nil, registry, l1.line_number); if (l1.type() == Node::nil && l2.type() == Node::nil) return Node(Node::nil, new_Node, l1.line_number);
// figure out the combined size in advance // figure out the combined size in advance
size_t size = 0; size_t size = 0;
if (l1.type != Node::nil) size += l1.size(); if (l1.type() != Node::nil) size += l1.size();
if (l2.type != Node::nil) size += l2.size(); if (l2.type() != Node::nil) size += l2.size();
// accumulate the result // accumulate the result
Node lr(l1.type, registry, l1.line_number, size); Node lr(l1.type(), new_Node, l1.line_number, size);
if (has_sep) { if (has_sep) {
string sep(bindings[parameters[2]].content.token.unquote()); string sep(bindings[parameters[2]].content.token.unquote());
if (sep == "comma") lr.type = Node::comma_list; if (sep == "comma") lr.type() = Node::comma_list;
else if (sep == "space") lr.type = Node::space_list; else if (sep == "space") lr.type() = Node::space_list;
else if (sep == "auto") ; // leave it alone else if (sep == "auto") ; // leave it alone
else { else {
eval_error("third argument to join must be 'space', 'comma', or 'auto'", l2.line_number, l2.file_name); throw_eval_error("third argument to join must be 'space', 'comma', or 'auto'", l2.line_number, l2.file_name);
} }
} }
else if (l1.type != Node::nil) lr.type = l1.type; else if (l1.type() != Node::nil) lr.type() = l1.type();
else if (l2.type != Node::nil) lr.type = l2.type; else if (l2.type() != Node::nil) lr.type() = l2.type();
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 = Function_Descriptor join_2_descriptor =
{ "join", "$list1", "$list2", 0 }; { "join", "$list1", "$list2", 0 };
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, false, registry); return join_impl(parameters, bindings, false, new_Node);
} }
Function_Descriptor join_3_descriptor = Function_Descriptor join_3_descriptor =
{ "join", "$list1", "$list2", "$separator", 0 }; { "join", "$list1", "$list2", "$separator", 0 };
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, true, registry); return join_impl(parameters, bindings, true, new_Node);
} }
// Introspection Functions ///////////////////////////////////////////// // Introspection Functions /////////////////////////////////////////////
...@@ -437,11 +434,11 @@ namespace Sass { ...@@ -437,11 +434,11 @@ namespace Sass {
Function_Descriptor type_of_descriptor = Function_Descriptor type_of_descriptor =
{ "type-of", "$value", 0 }; { "type-of", "$value", 0 };
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]); Node val(bindings[parameters[0]]);
Node type(Node::string_constant, val.line_number, Token::make()); Node type(Node::string_constant, val.line_number, Token::make());
type.unquoted = true; type.unquoted = true;
switch (val.type) switch (val.type())
{ {
case Node::number: case Node::number:
case Node::numeric_dimension: case Node::numeric_dimension:
...@@ -474,10 +471,10 @@ namespace Sass { ...@@ -474,10 +471,10 @@ namespace Sass {
Function_Descriptor unit_descriptor = Function_Descriptor unit_descriptor =
{ "unit", "$number", 0 }; { "unit", "$number", 0 };
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]); Node val(bindings[parameters[0]]);
Node u(Node::string_constant, val.line_number, Token::make()); Node u(Node::string_constant, val.line_number, Token::make());
switch (val.type) switch (val.type())
{ {
case Node::number: case Node::number:
u.content.token = Token::make(empty_str); u.content.token = Token::make(empty_str);
...@@ -489,7 +486,7 @@ namespace Sass { ...@@ -489,7 +486,7 @@ namespace Sass {
u.content.token = Token::make(val.content.dimension.unit, Prelexer::identifier(val.content.dimension.unit)); u.content.token = Token::make(val.content.dimension.unit, Prelexer::identifier(val.content.dimension.unit));
break; break;
default: default:
eval_error("argument to unit must be numeric", val.line_number, val.file_name); throw_eval_error("argument to unit must be numeric", val.line_number, val.file_name);
break; break;
} }
return u; return u;
...@@ -500,11 +497,11 @@ namespace Sass { ...@@ -500,11 +497,11 @@ namespace Sass {
Function_Descriptor unitless_descriptor = Function_Descriptor unitless_descriptor =
{ "unitless", "$number", 0 }; { "unitless", "$number", 0 };
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]); Node val(bindings[parameters[0]]);
Node result(Node::string_constant, val.line_number, Token::make()); Node result(Node::string_constant, val.line_number, Token::make());
result.unquoted = true; result.unquoted = true;
switch (val.type) switch (val.type())
{ {
case Node::number: { case Node::number: {
Node T(Node::boolean); Node T(Node::boolean);
...@@ -520,7 +517,7 @@ namespace Sass { ...@@ -520,7 +517,7 @@ namespace Sass {
return F; return F;
} break; } break;
default: default:
eval_error("argument to unitless must be numeric", val.line_number, val.file_name); throw_eval_error("argument to unitless must be numeric", val.line_number, val.file_name);
break; break;
} }
return result; return result;
...@@ -528,11 +525,11 @@ namespace Sass { ...@@ -528,11 +525,11 @@ namespace Sass {
Function_Descriptor comparable_descriptor = Function_Descriptor comparable_descriptor =
{ "comparable", "$number_1", "$number_2", 0 }; { "comparable", "$number_1", "$number_2", 0 };
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node n1(bindings[parameters[0]]); Node n1(bindings[parameters[0]]);
Node n2(bindings[parameters[1]]); Node n2(bindings[parameters[1]]);
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() ||
n1.is_numeric() && t2 == Node::number) { n1.is_numeric() && t2 == Node::number) {
Node T(Node::boolean); Node T(Node::boolean);
...@@ -566,7 +563,7 @@ namespace Sass { ...@@ -566,7 +563,7 @@ namespace Sass {
} }
} }
else if (!n1.is_numeric() && !n2.is_numeric()) { else if (!n1.is_numeric() && !n2.is_numeric()) {
eval_error("arguments to comparable must be numeric", n1.line_number, n1.file_name); throw_eval_error("arguments to comparable must be numeric", n1.line_number, n1.file_name);
} }
Node F(Node::boolean); Node F(Node::boolean);
...@@ -578,9 +575,9 @@ namespace Sass { ...@@ -578,9 +575,9 @@ namespace Sass {
// Boolean Functions /////////////////////////////////////////////////// // Boolean Functions ///////////////////////////////////////////////////
Function_Descriptor not_descriptor = Function_Descriptor not_descriptor =
{ "not", "value", 0 }; { "not", "value", 0 };
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) { Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]); Node val(bindings[parameters[0]]);
if (val.type == Node::boolean && val.content.boolean_value == false) { if (val.type() == Node::boolean && val.content.boolean_value == false) {
Node T(Node::boolean); Node T(Node::boolean);
T.line_number = val.line_number; T.line_number = val.line_number;
T.content.boolean_value = true; T.content.boolean_value = true;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
namespace Sass { namespace Sass {
using std::map; using std::map;
typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, vector<vector<Node>*>& registry); typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, Node_Factory& new_Node);
typedef const char* str; typedef const char* str;
typedef str Function_Descriptor[]; typedef str Function_Descriptor[];
...@@ -37,8 +37,8 @@ namespace Sass { ...@@ -37,8 +37,8 @@ namespace Sass {
} }
} }
Node operator()(map<Token, Node>& bindings, vector<vector<Node>*>& registry) const Node operator()(map<Token, Node>& bindings, Node_Factory& new_Node) const
{ return implementation(parameters, bindings, registry); } { return implementation(parameters, bindings, new_Node); }
}; };
...@@ -47,111 +47,111 @@ namespace Sass { ...@@ -47,111 +47,111 @@ namespace Sass {
// RGB Functions /////////////////////////////////////////////////////// // RGB Functions ///////////////////////////////////////////////////////
extern Function_Descriptor rgb_descriptor; extern Function_Descriptor rgb_descriptor;
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_4_descriptor; extern Function_Descriptor rgba_4_descriptor;
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_2_descriptor; extern Function_Descriptor rgba_2_descriptor;
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor red_descriptor; extern Function_Descriptor red_descriptor;
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor green_descriptor; extern Function_Descriptor green_descriptor;
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor blue_descriptor; extern Function_Descriptor blue_descriptor;
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_2_descriptor; extern Function_Descriptor mix_2_descriptor;
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_3_descriptor; extern Function_Descriptor mix_3_descriptor;
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// HSL Functions /////////////////////////////////////////////////////// // HSL Functions ///////////////////////////////////////////////////////
extern Function_Descriptor hsla_descriptor; extern Function_Descriptor hsla_descriptor;
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor hsl_descriptor; extern Function_Descriptor hsl_descriptor;
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor invert_descriptor; extern Function_Descriptor invert_descriptor;
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Opacity Functions /////////////////////////////////////////////////// // Opacity Functions ///////////////////////////////////////////////////
extern Function_Descriptor alpha_descriptor; extern Function_Descriptor alpha_descriptor;
extern Function_Descriptor opacity_descriptor; extern Function_Descriptor opacity_descriptor;
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor opacify_descriptor; extern Function_Descriptor opacify_descriptor;
extern Function_Descriptor fade_in_descriptor; extern Function_Descriptor fade_in_descriptor;
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor transparentize_descriptor; extern Function_Descriptor transparentize_descriptor;
extern Function_Descriptor fade_out_descriptor; extern Function_Descriptor fade_out_descriptor;
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// String Functions //////////////////////////////////////////////////// // String Functions ////////////////////////////////////////////////////
extern Function_Descriptor unquote_descriptor; extern Function_Descriptor unquote_descriptor;
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor quote_descriptor; extern Function_Descriptor quote_descriptor;
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Number Functions //////////////////////////////////////////////////// // Number Functions ////////////////////////////////////////////////////
extern Function_Descriptor percentage_descriptor; extern Function_Descriptor percentage_descriptor;
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor round_descriptor; extern Function_Descriptor round_descriptor;
Node round(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node round(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor ceil_descriptor; extern Function_Descriptor ceil_descriptor;
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor floor_descriptor; extern Function_Descriptor floor_descriptor;
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor abs_descriptor; extern Function_Descriptor abs_descriptor;
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// List Functions ////////////////////////////////////////////////////// // List Functions //////////////////////////////////////////////////////
extern Function_Descriptor length_descriptor; extern Function_Descriptor length_descriptor;
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node length(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor nth_descriptor; extern Function_Descriptor nth_descriptor;
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_2_descriptor; extern Function_Descriptor join_2_descriptor;
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_3_descriptor; extern Function_Descriptor join_3_descriptor;
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Introspection Functions ///////////////////////////////////////////// // Introspection Functions /////////////////////////////////////////////
extern Function_Descriptor type_of_descriptor; extern Function_Descriptor type_of_descriptor;
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unit_descriptor; extern Function_Descriptor unit_descriptor;
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unitless_descriptor; extern Function_Descriptor unitless_descriptor;
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor comparable_descriptor; extern Function_Descriptor comparable_descriptor;
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Boolean Functions /////////////////////////////////////////////////// // Boolean Functions ///////////////////////////////////////////////////
extern Function_Descriptor not_descriptor; extern Function_Descriptor not_descriptor;
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry); Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
} }
......
...@@ -213,7 +213,7 @@ namespace Sass { ...@@ -213,7 +213,7 @@ namespace Sass {
// Node_Impl method implementations // Node_Impl method implementations
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
double Node_Impl::numeric_value() double& Node_Impl::numeric_value()
{ {
switch (type) switch (type)
{ {
...@@ -226,7 +226,6 @@ namespace Sass { ...@@ -226,7 +226,6 @@ namespace Sass {
break; break;
// throw an exception? // throw an exception?
} }
return 0;
} }
extern const char percent_str[] = "%"; extern const char percent_str[] = "%";
......
...@@ -160,7 +160,7 @@ namespace Sass { ...@@ -160,7 +160,7 @@ namespace Sass {
bool has_backref() const; bool has_backref() const;
bool from_variable() const; bool from_variable() const;
bool& should_eval() const; bool& should_eval() const;
bool is_unquoted() const; bool& is_unquoted() const;
bool is_numeric() const; bool is_numeric() const;
string& path() const; string& path() const;
...@@ -178,7 +178,7 @@ namespace Sass { ...@@ -178,7 +178,7 @@ namespace Sass {
Node& operator+=(Node n); Node& operator+=(Node n);
bool& boolean_value() const; bool& boolean_value() const;
double numeric_value() const; double& numeric_value() const;
Token token() const; Token token() const;
Token unit() const; Token unit() const;
...@@ -272,7 +272,7 @@ namespace Sass { ...@@ -272,7 +272,7 @@ namespace Sass {
bool& boolean_value() bool& boolean_value()
{ return value.boolean; } { return value.boolean; }
double numeric_value(); double& numeric_value();
Token unit(); Token unit();
}; };
...@@ -294,7 +294,7 @@ namespace Sass { ...@@ -294,7 +294,7 @@ namespace Sass {
inline bool Node::has_backref() const { return ip_->has_backref; } inline bool Node::has_backref() const { return ip_->has_backref; }
inline bool Node::from_variable() const { return ip_->from_variable; } inline bool Node::from_variable() const { return ip_->from_variable; }
inline bool& Node::should_eval() const { return ip_->should_eval; } inline bool& Node::should_eval() const { return ip_->should_eval; }
inline bool Node::is_unquoted() const { return ip_->is_unquoted; } inline bool& Node::is_unquoted() const { return ip_->is_unquoted; }
inline bool Node::is_numeric() const { return ip_->is_numeric(); } inline bool Node::is_numeric() const { return ip_->is_numeric(); }
inline string& Node::path() const { return ip_->path; } inline string& Node::path() const { return ip_->path; }
...@@ -323,7 +323,7 @@ namespace Sass { ...@@ -323,7 +323,7 @@ namespace Sass {
return *this; return *this;
} }
inline bool& Node::boolean_value() const { return ip_->boolean_value(); } inline bool& Node::boolean_value() const { return ip_->boolean_value(); }
inline double Node::numeric_value() const { return ip_->numeric_value(); } inline double& Node::numeric_value() const { return ip_->numeric_value(); }
inline Token Node::token() const { return ip_->value.token; } inline Token Node::token() const { return ip_->value.token; }
inline Token Node::unit() const { return ip_->unit(); } inline Token Node::unit() const { return ip_->unit(); }
......
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