Commit a4fcf741 by Aaron Leung

Improving the function call resolver so that it works with more complex real-world usages.

parent 038c77f9
...@@ -23,10 +23,10 @@ namespace Sass { ...@@ -23,10 +23,10 @@ namespace Sass {
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, Node_Factory& new_Node) { Node rgb(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0]]); Node r(bindings[parameters[0].token()]);
Node g(bindings[parameters[1]]); Node g(bindings[parameters[1].token()]);
Node b(bindings[parameters[2]]); 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());
} }
...@@ -35,11 +35,11 @@ namespace Sass { ...@@ -35,11 +35,11 @@ namespace Sass {
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, Node_Factory& new_Node) { Node rgba_4(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node r(bindings[parameters[0]]); Node r(bindings[parameters[0].token()]);
Node g(bindings[parameters[1]]); Node g(bindings[parameters[1].token()]);
Node b(bindings[parameters[2]]); Node b(bindings[parameters[2].token()]);
Node a(bindings[parameters[3]]); Node a(bindings[parameters[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());
} }
...@@ -48,36 +48,36 @@ namespace Sass { ...@@ -48,36 +48,36 @@ namespace Sass {
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, Node_Factory& new_Node) { Node rgba_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); 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]]); Node a(bindings[parameters[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 = Function_Descriptor red_descriptor =
{ "red", "$color", 0 }; { "red", "$color", 0 };
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node red(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); 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 = Function_Descriptor green_descriptor =
{ "green", "$color", 0 }; { "green", "$color", 0 };
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node green(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); 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 = Function_Descriptor blue_descriptor =
{ "blue", "$color", 0 }; { "blue", "$color", 0 };
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node blue(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); 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];
} }
...@@ -105,19 +105,19 @@ namespace Sass { ...@@ -105,19 +105,19 @@ namespace Sass {
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, Node_Factory& new_Node) { Node mix_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return mix_impl(bindings[parameters[0]], bindings[parameters[1]], 50, new_Node); return mix_impl(bindings[parameters[0].token()], bindings[parameters[1].token()], 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, Node_Factory& new_Node) { Node mix_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node percentage(bindings[parameters[2]]); Node percentage(bindings[parameters[2].token()]);
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)) {
throw_eval_error("third argument to mix must be numeric", percentage.path(), percentage.line()); 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].token()],
bindings[parameters[1]], bindings[parameters[1].token()],
percentage.numeric_value(), percentage.numeric_value(),
new_Node); new_Node);
} }
...@@ -151,42 +151,42 @@ namespace Sass { ...@@ -151,42 +151,42 @@ namespace Sass {
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, Node_Factory& new_Node) { Node hsla(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
if (!(bindings[parameters[0]].is_numeric() && if (!(bindings[parameters[0].token()].is_numeric() &&
bindings[parameters[1]].is_numeric() && bindings[parameters[1].token()].is_numeric() &&
bindings[parameters[2]].is_numeric() && bindings[parameters[2].token()].is_numeric() &&
bindings[parameters[3]].is_numeric())) { bindings[parameters[3].token()].is_numeric())) {
throw_eval_error("arguments to hsla must be numeric", bindings[parameters[0]].path(), bindings[parameters[0]].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]].numeric_value(); double h = bindings[parameters[0].token()].numeric_value();
double s = bindings[parameters[1]].numeric_value(); double s = bindings[parameters[1].token()].numeric_value();
double l = bindings[parameters[2]].numeric_value(); double l = bindings[parameters[2].token()].numeric_value();
double a = bindings[parameters[3]].numeric_value(); double a = bindings[parameters[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]].line(); // color.line() = bindings[parameters[0].token()].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, Node_Factory& new_Node) { Node hsl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
if (!(bindings[parameters[0]].is_numeric() && if (!(bindings[parameters[0].token()].is_numeric() &&
bindings[parameters[1]].is_numeric() && bindings[parameters[1].token()].is_numeric() &&
bindings[parameters[2]].is_numeric())) { bindings[parameters[2].token()].is_numeric())) {
throw_eval_error("arguments to hsl must be numeric", bindings[parameters[0]].path(), bindings[parameters[0]].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]].numeric_value(); double h = bindings[parameters[0].token()].numeric_value();
double s = bindings[parameters[1]].numeric_value(); double s = bindings[parameters[1].token()].numeric_value();
double l = bindings[parameters[2]].numeric_value(); double l = bindings[parameters[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]].line(); // color.line() = bindings[parameters[0].token()].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, Node_Factory& new_Node) { Node invert(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]); 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(),
...@@ -201,8 +201,8 @@ namespace Sass { ...@@ -201,8 +201,8 @@ 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, Node_Factory& new_Node) { Node alpha(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); 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()); 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];
} }
...@@ -211,9 +211,9 @@ namespace Sass { ...@@ -211,9 +211,9 @@ 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, Node_Factory& new_Node) { Node opacify(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); Node color(bindings[parameters[0].token()]);
Node delta(bindings[parameters[1]]); 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());
} }
...@@ -231,9 +231,9 @@ namespace Sass { ...@@ -231,9 +231,9 @@ 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, Node_Factory& new_Node) { Node transparentize(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node color(bindings[parameters[0]]); Node color(bindings[parameters[0].token()]);
Node delta(bindings[parameters[1]]); 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());
} }
...@@ -251,8 +251,8 @@ namespace Sass { ...@@ -251,8 +251,8 @@ 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, Node_Factory& new_Node) { Node unquote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node cpy(new_Node(bindings[parameters[0]])); 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());
// } // }
...@@ -263,8 +263,8 @@ namespace Sass { ...@@ -263,8 +263,8 @@ namespace Sass {
Function_Descriptor quote_descriptor = Function_Descriptor quote_descriptor =
{ "quote", "$string", 0 }; { "quote", "$string", 0 };
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node quote(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]); Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
default: { default: {
...@@ -289,8 +289,8 @@ namespace Sass { ...@@ -289,8 +289,8 @@ 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, Node_Factory& new_Node) { Node percentage(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]); 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());
} }
...@@ -299,8 +299,8 @@ namespace Sass { ...@@ -299,8 +299,8 @@ namespace Sass {
Function_Descriptor round_descriptor = Function_Descriptor round_descriptor =
{ "round", "$value", 0 }; { "round", "$value", 0 };
Node round(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node round(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]); Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
case Node::numeric_dimension: { case Node::numeric_dimension: {
...@@ -329,8 +329,8 @@ namespace Sass { ...@@ -329,8 +329,8 @@ namespace Sass {
Function_Descriptor ceil_descriptor = Function_Descriptor ceil_descriptor =
{ "ceil", "$value", 0 }; { "ceil", "$value", 0 };
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node ceil(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]); Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
case Node::numeric_dimension: { case Node::numeric_dimension: {
...@@ -359,8 +359,8 @@ namespace Sass { ...@@ -359,8 +359,8 @@ namespace Sass {
Function_Descriptor floor_descriptor = Function_Descriptor floor_descriptor =
{ "floor", "$value", 0 }; { "floor", "$value", 0 };
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node floor(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]); Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
case Node::numeric_dimension: { case Node::numeric_dimension: {
...@@ -389,8 +389,8 @@ namespace Sass { ...@@ -389,8 +389,8 @@ namespace Sass {
Function_Descriptor abs_descriptor = Function_Descriptor abs_descriptor =
{ "abs", "$value", 0 }; { "abs", "$value", 0 };
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node abs(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node orig(bindings[parameters[0]]); Node orig(bindings[parameters[0].token()]);
switch (orig.type()) switch (orig.type())
{ {
case Node::numeric_dimension: { case Node::numeric_dimension: {
...@@ -421,8 +421,8 @@ namespace Sass { ...@@ -421,8 +421,8 @@ 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, Node_Factory& new_Node) { Node length(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node arg(bindings[parameters[0]]); Node arg(bindings[parameters[0].token()]);
switch (arg.type()) switch (arg.type())
{ {
case Node::space_list: case Node::space_list:
...@@ -445,9 +445,9 @@ namespace Sass { ...@@ -445,9 +445,9 @@ 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, Node_Factory& new_Node) { Node nth(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node l(bindings[parameters[0]]); Node l(bindings[parameters[0].token()]);
Node n(bindings[parameters[1]]); 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());
} }
...@@ -466,13 +466,13 @@ namespace Sass { ...@@ -466,13 +466,13 @@ namespace Sass {
} }
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, Node_Factory& new_Node) { Node join_impl(const Node 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].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]]); Node l2(bindings[parameters[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;
} }
...@@ -487,7 +487,7 @@ namespace Sass { ...@@ -487,7 +487,7 @@ namespace Sass {
// 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) { if (has_sep) {
string sep(bindings[parameters[2]].token().unquote()); string sep(bindings[parameters[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();
...@@ -506,18 +506,18 @@ namespace Sass { ...@@ -506,18 +506,18 @@ namespace Sass {
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, Node_Factory& new_Node) { Node join_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, false, new_Node); 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, Node_Factory& new_Node) { Node join_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return join_impl(parameters, bindings, true, new_Node); return join_impl(parameters, bindings, true, new_Node);
} }
Node append_impl(const vector<Token>& parameters, map<Token, Node>& bindings, bool has_sep, Node_Factory& new_Node) { Node append_impl(const Node parameters, map<Token, Node>& bindings, bool has_sep, Node_Factory& new_Node) {
Node list(bindings[parameters[0]]); Node list(bindings[parameters[0].token()]);
switch (list.type()) switch (list.type())
{ {
case Node::space_list: case Node::space_list:
...@@ -532,7 +532,7 @@ namespace Sass { ...@@ -532,7 +532,7 @@ namespace Sass {
} }
Node::Type sep_type = list.type(); Node::Type sep_type = list.type();
if (has_sep) { if (has_sep) {
string sep_string = bindings[parameters[2]].token().unquote(); string sep_string = bindings[parameters[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();
...@@ -540,27 +540,27 @@ namespace Sass { ...@@ -540,27 +540,27 @@ namespace Sass {
} }
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]]; new_list << bindings[parameters[1].token()];
return new_list; return new_list;
} }
Function_Descriptor append_2_descriptor = Function_Descriptor append_2_descriptor =
{ "append", "$list", "$val", 0 }; { "append", "$list", "$val", 0 };
Node append_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node append_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return append_impl(parameters, bindings, false, new_Node); return append_impl(parameters, bindings, false, new_Node);
} }
Function_Descriptor append_3_descriptor = Function_Descriptor append_3_descriptor =
{ "append", "$list", "$val", "$separator", 0 }; { "append", "$list", "$val", "$separator", 0 };
Node append_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node append_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
return append_impl(parameters, bindings, true, new_Node); return append_impl(parameters, bindings, true, new_Node);
} }
Node compact(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node) { Node compact(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
size_t num_args = bindings.size(); 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]]); Node arg1(bindings[parameters[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)) {
...@@ -570,7 +570,7 @@ namespace Sass { ...@@ -570,7 +570,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]]; list << bindings[parameters[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));
...@@ -619,8 +619,8 @@ namespace Sass { ...@@ -619,8 +619,8 @@ 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, Node_Factory& new_Node) { Node type_of(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]); Node val(bindings[parameters[0].token()]);
Token type_name; Token type_name;
switch (val.type()) switch (val.type())
{ {
...@@ -658,8 +658,8 @@ namespace Sass { ...@@ -658,8 +658,8 @@ 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, Node_Factory& new_Node) { Node unit(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]); Node val(bindings[parameters[0].token()]);
switch (val.type()) switch (val.type())
{ {
case Node::number: { case Node::number: {
...@@ -684,8 +684,8 @@ namespace Sass { ...@@ -684,8 +684,8 @@ 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, Node_Factory& new_Node) { Node unitless(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]); Node val(bindings[parameters[0].token()]);
switch (val.type()) switch (val.type())
{ {
case Node::number: { case Node::number: {
...@@ -707,9 +707,9 @@ namespace Sass { ...@@ -707,9 +707,9 @@ 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, Node_Factory& new_Node) { Node comparable(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node n1(bindings[parameters[0]]); Node n1(bindings[parameters[0].token()]);
Node n2(bindings[parameters[1]]); 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()) ||
...@@ -742,8 +742,8 @@ namespace Sass { ...@@ -742,8 +742,8 @@ 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, Node_Factory& new_Node) { Node not_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node) {
Node val(bindings[parameters[0]]); 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);
} }
......
...@@ -8,14 +8,15 @@ ...@@ -8,14 +8,15 @@
namespace Sass { namespace Sass {
using std::map; using std::map;
typedef Node (*Primitive)(const vector<Token>&, map<Token, Node>&, Node_Factory& new_Node); typedef Node (*Primitive)(const Node, map<Token, Node>&, Node_Factory& new_Node);
typedef const char* str; typedef const char* str;
typedef str Function_Descriptor[]; typedef str Function_Descriptor[];
struct Function { struct Function {
string name; string name;
vector<Token> parameters; // vector<Token> parameters;
Node parameters;
Node definition; Node definition;
Primitive primitive; Primitive primitive;
...@@ -24,25 +25,23 @@ namespace Sass { ...@@ -24,25 +25,23 @@ namespace Sass {
Function(Node def) Function(Node def)
: name(def[0].to_string()), : name(def[0].to_string()),
parameters(vector<Token>()), parameters(def[1]),
definition(def), definition(def),
primitive(0) primitive(0)
{ } { }
Function(Function_Descriptor d, Primitive ip) Function(Function_Descriptor d, Primitive ip, Node_Factory& new_Node)
: name(d[0]), : name(d[0]),
parameters(vector<Token>()), parameters(new_Node(Node::parameters, "[PRIMITIVE FUNCTIONS]", 0, 0)),
definition(Node()), definition(Node()),
primitive(ip) primitive(ip)
{ {
size_t len = 0; size_t len = 0;
while (d[len+1]) ++len; while (d[len+1]) ++len;
parameters.reserve(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];
Token name(Token::make(p, p + std::strlen(p))); parameters.push_back(new_Node(Node::variable, "[PRIMITIVE FUNCTIONS]", 0, Token::make(p, p + std::strlen(p))));
parameters.push_back(name);
} }
} }
...@@ -59,98 +58,98 @@ namespace Sass { ...@@ -59,98 +58,98 @@ 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, Node_Factory& new_Node); Node rgb(const Node 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, Node_Factory& new_Node); Node rgba_4(const Node 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, Node_Factory& new_Node); Node rgba_2(const Node 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, Node_Factory& new_Node); Node red(const Node 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, Node_Factory& new_Node); Node green(const Node 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, Node_Factory& new_Node); Node blue(const Node 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, Node_Factory& new_Node); Node mix_2(const Node 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, Node_Factory& new_Node); Node mix_3(const Node 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, Node_Factory& new_Node); Node hsla(const Node 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, Node_Factory& new_Node); Node hsl(const Node 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, Node_Factory& new_Node); Node invert(const Node 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, Node_Factory& new_Node); Node alpha(const Node 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, Node_Factory& new_Node); Node opacify(const Node 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, Node_Factory& new_Node); Node transparentize(const Node 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, Node_Factory& new_Node); Node unquote(const Node 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, Node_Factory& new_Node); Node quote(const Node 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, Node_Factory& new_Node); Node percentage(const Node 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, Node_Factory& new_Node); Node round(const Node 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, Node_Factory& new_Node); Node ceil(const Node 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, Node_Factory& new_Node); Node floor(const Node 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, Node_Factory& new_Node); Node abs(const Node 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, Node_Factory& new_Node); Node length(const Node 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, Node_Factory& new_Node); Node nth(const Node 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, Node_Factory& new_Node); Node join_2(const Node 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, Node_Factory& new_Node); Node join_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor append_2_descriptor; extern Function_Descriptor append_2_descriptor;
Node append_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node append_2(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor append_3_descriptor; extern Function_Descriptor append_3_descriptor;
Node append_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node append_3(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor compact_1_descriptor; extern Function_Descriptor compact_1_descriptor;
extern Function_Descriptor compact_2_descriptor; extern Function_Descriptor compact_2_descriptor;
...@@ -162,26 +161,26 @@ namespace Sass { ...@@ -162,26 +161,26 @@ namespace Sass {
extern Function_Descriptor compact_8_descriptor; extern Function_Descriptor compact_8_descriptor;
extern Function_Descriptor compact_9_descriptor; extern Function_Descriptor compact_9_descriptor;
extern Function_Descriptor compact_10_descriptor; extern Function_Descriptor compact_10_descriptor;
Node compact(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node); Node compact(const Node 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, Node_Factory& new_Node); Node type_of(const Node 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, Node_Factory& new_Node); Node unit(const Node 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, Node_Factory& new_Node); Node unitless(const Node 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, Node_Factory& new_Node); Node comparable(const Node 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, Node_Factory& new_Node); Node not_impl(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
} }
......
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