Commit 4b86ac98 by Dean Mao

Merge branch 'master' of git://github.com/hcatlin/libsass

parents ba80ff04 b3e8d772
#define SASS_COLOR_NAMES_INCLUDED
namespace Sass {
const char* color_names[] =
{
"aliceblue",
"antiquewhite",
"aqua",
"aquamarine",
"azure",
"beige",
"bisque",
"black",
"blanchedalmond",
"blue",
"blueviolet",
"brown",
"burlywood",
"cadetblue",
"chartreuse",
"chocolate",
"coral",
"cornflowerblue",
"cornsilk",
"crimson",
"cyan",
"darkblue",
"darkcyan",
"darkgoldenrod",
"darkgray",
"darkgrey",
"darkgreen",
"darkkhaki",
"darkmagenta",
"darkolivegreen",
"darkorange",
"darkorchid",
"darkred",
"darksalmon",
"darkseagreen",
"darkslateblue",
"darkslategray",
"darkslategrey",
"darkturquoise",
"darkviolet",
"deeppink",
"deepskyblue",
"dimgray",
"dimgrey",
"dodgerblue",
"firebrick",
"floralwhite",
"forestgreen",
"fuchsia",
"gainsboro",
"ghostwhite",
"gold",
"goldenrod",
"gray",
"grey",
"green",
"greenyellow",
"honeydew",
"hotpink",
"indianred",
"indigo",
"ivory",
"khaki",
"lavender",
"lavenderblush",
"lawngreen",
"lemonchiffon",
"lightblue",
"lightcoral",
"lightcyan",
"lightgoldenrodyellow",
"lightgray",
"lightgrey",
"lightgreen",
"lightpink",
"lightsalmon",
"lightseagreen",
"lightskyblue",
"lightslategray",
"lightslategrey",
"lightsteelblue",
"lightyellow",
"lime",
"limegreen",
"linen",
"magenta",
"maroon",
"mediumaquamarine",
"mediumblue",
"mediumorchid",
"mediumpurple",
"mediumseagreen",
"mediumslateblue",
"mediumspringgreen",
"mediumturquoise",
"mediumvioletred",
"midnightblue",
"mintcream",
"mistyrose",
"moccasin",
"navajowhite",
"navy",
"oldlace",
"olive",
"olivedrab",
"orange",
"orangered",
"orchid",
"palegoldenrod",
"palegreen",
"paleturquoise",
"palevioletred",
"papayawhip",
"peachpuff",
"peru",
"pink",
"plum",
"powderblue",
"purple",
"red",
"rosybrown",
"royalblue",
"saddlebrown",
"salmon",
"sandybrown",
"seagreen",
"seashell",
"sienna",
"silver",
"skyblue",
"slateblue",
"slategray",
"slategrey",
"snow",
"springgreen",
"steelblue",
"tan",
"teal",
"thistle",
"tomato",
"turquoise",
"violet",
"wheat",
"white",
"whitesmoke",
"yellow",
"yellowgreen",
// sentinel value
0
};
const double color_values[] =
{
0xf0, 0xf8, 0xff,
0xfa, 0xeb, 0xd7,
0x00, 0xff, 0xff,
0x7f, 0xff, 0xd4,
0xf0, 0xff, 0xff,
0xf5, 0xf5, 0xdc,
0xff, 0xe4, 0xc4,
0x00, 0x00, 0x00,
0xff, 0xeb, 0xcd,
0x00, 0x00, 0xff,
0x8a, 0x2b, 0xe2,
0xa5, 0x2a, 0x2a,
0xde, 0xb8, 0x87,
0x5f, 0x9e, 0xa0,
0x7f, 0xff, 0x00,
0xd2, 0x69, 0x1e,
0xff, 0x7f, 0x50,
0x64, 0x95, 0xed,
0xff, 0xf8, 0xdc,
0xdc, 0x14, 0x3c,
0x00, 0xff, 0xff,
0x00, 0x00, 0x8b,
0x00, 0x8b, 0x8b,
0xb8, 0x86, 0x0b,
0xa9, 0xa9, 0xa9,
0xa9, 0xa9, 0xa9,
0x00, 0x64, 0x00,
0xbd, 0xb7, 0x6b,
0x8b, 0x00, 0x8b,
0x55, 0x6b, 0x2f,
0xff, 0x8c, 0x00,
0x99, 0x32, 0xcc,
0x8b, 0x00, 0x00,
0xe9, 0x96, 0x7a,
0x8f, 0xbc, 0x8f,
0x48, 0x3d, 0x8b,
0x2f, 0x4f, 0x4f,
0x2f, 0x4f, 0x4f,
0x00, 0xce, 0xd1,
0x94, 0x00, 0xd3,
0xff, 0x14, 0x93,
0x00, 0xbf, 0xff,
0x69, 0x69, 0x69,
0x69, 0x69, 0x69,
0x1e, 0x90, 0xff,
0xb2, 0x22, 0x22,
0xff, 0xfa, 0xf0,
0x22, 0x8b, 0x22,
0xff, 0x00, 0xff,
0xdc, 0xdc, 0xdc,
0xf8, 0xf8, 0xff,
0xff, 0xd7, 0x00,
0xda, 0xa5, 0x20,
0x80, 0x80, 0x80,
0x80, 0x80, 0x80,
0x00, 0x80, 0x00,
0xad, 0xff, 0x2f,
0xf0, 0xff, 0xf0,
0xff, 0x69, 0xb4,
0xcd, 0x5c, 0x5c,
0x4b, 0x00, 0x82,
0xff, 0xff, 0xf0,
0xf0, 0xe6, 0x8c,
0xe6, 0xe6, 0xfa,
0xff, 0xf0, 0xf5,
0x7c, 0xfc, 0x00,
0xff, 0xfa, 0xcd,
0xad, 0xd8, 0xe6,
0xf0, 0x80, 0x80,
0xe0, 0xff, 0xff,
0xfa, 0xfa, 0xd2,
0xd3, 0xd3, 0xd3,
0xd3, 0xd3, 0xd3,
0x90, 0xee, 0x90,
0xff, 0xb6, 0xc1,
0xff, 0xa0, 0x7a,
0x20, 0xb2, 0xaa,
0x87, 0xce, 0xfa,
0x77, 0x88, 0x99,
0x77, 0x88, 0x99,
0xb0, 0xc4, 0xde,
0xff, 0xff, 0xe0,
0x00, 0xff, 0x00,
0x32, 0xcd, 0x32,
0xfa, 0xf0, 0xe6,
0xff, 0x00, 0xff,
0x80, 0x00, 0x00,
0x66, 0xcd, 0xaa,
0x00, 0x00, 0xcd,
0xba, 0x55, 0xd3,
0x93, 0x70, 0xd8,
0x3c, 0xb3, 0x71,
0x7b, 0x68, 0xee,
0x00, 0xfa, 0x9a,
0x48, 0xd1, 0xcc,
0xc7, 0x15, 0x85,
0x19, 0x19, 0x70,
0xf5, 0xff, 0xfa,
0xff, 0xe4, 0xe1,
0xff, 0xe4, 0xb5,
0xff, 0xde, 0xad,
0x00, 0x00, 0x80,
0xfd, 0xf5, 0xe6,
0x80, 0x80, 0x00,
0x6b, 0x8e, 0x23,
0xff, 0xa5, 0x00,
0xff, 0x45, 0x00,
0xda, 0x70, 0xd6,
0xee, 0xe8, 0xaa,
0x98, 0xfb, 0x98,
0xaf, 0xee, 0xee,
0xd8, 0x70, 0x93,
0xff, 0xef, 0xd5,
0xff, 0xda, 0xb9,
0xcd, 0x85, 0x3f,
0xff, 0xc0, 0xcb,
0xdd, 0xa0, 0xdd,
0xb0, 0xe0, 0xe6,
0x80, 0x00, 0x80,
0xff, 0x00, 0x00,
0xbc, 0x8f, 0x8f,
0x41, 0x69, 0xe1,
0x8b, 0x45, 0x13,
0xfa, 0x80, 0x72,
0xf4, 0xa4, 0x60,
0x2e, 0x8b, 0x57,
0xff, 0xf5, 0xee,
0xa0, 0x52, 0x2d,
0xc0, 0xc0, 0xc0,
0x87, 0xce, 0xeb,
0x6a, 0x5a, 0xcd,
0x70, 0x80, 0x90,
0x70, 0x80, 0x90,
0xff, 0xfa, 0xfa,
0x00, 0xff, 0x7f,
0x46, 0x82, 0xb4,
0xd2, 0xb4, 0x8c,
0x00, 0x80, 0x80,
0xd8, 0xbf, 0xd8,
0xff, 0x63, 0x47,
0x40, 0xe0, 0xd0,
0xee, 0x82, 0xee,
0xf5, 0xde, 0xb3,
0xff, 0xff, 0xff,
0xf5, 0xf5, 0xf5,
0xff, 0xff, 0x00,
0x9a, 0xcd, 0x32,
// sentinel value
0xfff
};
}
\ No newline at end of file
#include "context.hpp" #include "context.hpp"
#include <cstring>
#include <iostream> #include <iostream>
#include <unistd.h> #include <unistd.h>
#include "prelexer.hpp" #include "prelexer.hpp"
#include "color_names.hpp"
using std::cerr; using std::endl; using std::cerr; using std::endl;
namespace Sass { namespace Sass {
...@@ -40,19 +42,28 @@ namespace Sass { ...@@ -40,19 +42,28 @@ namespace Sass {
// } // }
} }
Context::Context(const char* paths_str) Context::Context(const char* paths_str, const char* img_path_str)
: global_env(Environment()), : global_env(Environment()),
function_env(map<pair<string, size_t>, Function>()), function_env(map<string, Function>()),
extensions(multimap<Node, Node>()), extensions(multimap<Node, Node>()),
pending_extensions(vector<pair<Node, Node> >()), pending_extensions(vector<pair<Node, Node> >()),
source_refs(vector<char*>()), source_refs(vector<char*>()),
include_paths(vector<string>()), include_paths(vector<string>()),
color_names_to_values(map<string, Node>()),
color_values_to_names(map<Node, string>()),
new_Node(Node_Factory()), new_Node(Node_Factory()),
image_path(0),
ref_count(0), ref_count(0),
has_extensions(false) has_extensions(false)
{ {
register_functions(); register_functions();
collect_include_paths(paths_str); collect_include_paths(paths_str);
setup_color_map();
string path_string(img_path_str);
path_string = "'" + path_string + "/'";
image_path = new char[path_string.length() + 1];
std::strcpy(image_path, path_string.c_str());
} }
Context::~Context() Context::~Context()
...@@ -60,21 +71,28 @@ namespace Sass { ...@@ -60,21 +71,28 @@ namespace Sass {
for (size_t i = 0; i < source_refs.size(); ++i) { for (size_t i = 0; i < source_refs.size(); ++i) {
delete[] source_refs[i]; delete[] source_refs[i];
} }
delete[] image_path;
new_Node.free(); new_Node.free();
// cerr << "Deallocated " << i << " source string(s)." << endl; // cerr << "Deallocated " << i << " source string(s)." << endl;
} }
inline void Context::register_function(Function_Descriptor d, Primitive ip) inline void Context::register_function(Function_Descriptor d, Primitive ip)
{ {
Function f(d, ip); Function f(d, ip, new_Node);
function_env[pair<string, size_t>(f.name, f.parameters.size())] = f; // function_env[pair<string, size_t>(f.name, f.parameters.size())] = f;
function_env[f.name] = f;
} }
inline void Context::register_function(Function_Descriptor d, Primitive ip, size_t arity) inline void Context::register_function(Function_Descriptor d, Primitive ip, size_t arity)
{ {
Function f(d, ip); Function f(d, ip, new_Node);
function_env[pair<string, size_t>(f.name, arity)] = f; // function_env[pair<string, size_t>(f.name, arity)] = f;
function_env[f.name] = f;
}
inline void Context::register_overload_stub(string name)
{
function_env[name] = Function(name, true);
} }
void Context::register_functions() void Context::register_functions()
...@@ -82,11 +100,13 @@ namespace Sass { ...@@ -82,11 +100,13 @@ namespace Sass {
using namespace Functions; using namespace Functions;
// RGB Functions // RGB Functions
register_function(rgb_descriptor, rgb); register_function(rgb_descriptor, rgb);
register_overload_stub("rgba");
register_function(rgba_4_descriptor, rgba_4); register_function(rgba_4_descriptor, rgba_4);
register_function(rgba_2_descriptor, rgba_2); register_function(rgba_2_descriptor, rgba_2);
register_function(red_descriptor, red); register_function(red_descriptor, red);
register_function(green_descriptor, green); register_function(green_descriptor, green);
register_function(blue_descriptor, blue); register_function(blue_descriptor, blue);
register_overload_stub("mix");
register_function(mix_2_descriptor, mix_2); register_function(mix_2_descriptor, mix_2);
register_function(mix_3_descriptor, mix_3); register_function(mix_3_descriptor, mix_3);
// HSL Functions // HSL Functions
...@@ -112,10 +132,13 @@ namespace Sass { ...@@ -112,10 +132,13 @@ namespace Sass {
// List Functions // List Functions
register_function(length_descriptor, length); register_function(length_descriptor, length);
register_function(nth_descriptor, nth); register_function(nth_descriptor, nth);
register_overload_stub("join");
register_function(join_2_descriptor, join_2); register_function(join_2_descriptor, join_2);
register_function(join_3_descriptor, join_3); register_function(join_3_descriptor, join_3);
register_overload_stub("append");
register_function(append_2_descriptor, append_2); register_function(append_2_descriptor, append_2);
register_function(append_3_descriptor, append_3); register_function(append_3_descriptor, append_3);
register_overload_stub("compact");
register_function(compact_1_descriptor, compact); register_function(compact_1_descriptor, compact);
register_function(compact_2_descriptor, compact); register_function(compact_2_descriptor, compact);
register_function(compact_3_descriptor, compact); register_function(compact_3_descriptor, compact);
...@@ -126,6 +149,8 @@ namespace Sass { ...@@ -126,6 +149,8 @@ namespace Sass {
register_function(compact_8_descriptor, compact); register_function(compact_8_descriptor, compact);
register_function(compact_9_descriptor, compact); register_function(compact_9_descriptor, compact);
register_function(compact_10_descriptor, compact); register_function(compact_10_descriptor, compact);
register_function(compact_11_descriptor, compact);
register_function(compact_12_descriptor, compact);
// Introspection Functions // Introspection Functions
register_function(type_of_descriptor, type_of); register_function(type_of_descriptor, type_of);
register_function(unit_descriptor, unit); register_function(unit_descriptor, unit);
...@@ -135,4 +160,20 @@ namespace Sass { ...@@ -135,4 +160,20 @@ namespace Sass {
register_function(not_descriptor, not_impl); register_function(not_descriptor, not_impl);
} }
void Context::setup_color_map()
{
size_t i = 0;
while (color_names[i]) {
string name(color_names[i]);
Node value(new_Node("[COLOR TABLE]", 0,
color_values[i*3],
color_values[i*3+1],
color_values[i*3+2],
1));
color_names_to_values[name] = value;
color_values_to_names[value] = name;
++i;
}
}
} }
...@@ -42,24 +42,29 @@ namespace Sass { ...@@ -42,24 +42,29 @@ namespace Sass {
struct Context { struct Context {
Environment global_env; Environment global_env;
map<pair<string, size_t>, Function> function_env; map<string, Function> function_env;
multimap<Node, Node> extensions; multimap<Node, Node> extensions;
vector<pair<Node, Node> > pending_extensions; vector<pair<Node, Node> > pending_extensions;
vector<char*> source_refs; // all the source c-strings vector<char*> source_refs; // all the source c-strings
vector<string> include_paths; vector<string> include_paths;
map<string, Node> color_names_to_values;
map<Node, string> color_values_to_names;
Node_Factory new_Node; Node_Factory new_Node;
char* image_path;
size_t ref_count; size_t ref_count;
string sass_path; // string sass_path;
string css_path; // string css_path;
bool has_extensions; bool has_extensions;
void collect_include_paths(const char* paths_str); void collect_include_paths(const char* paths_str);
Context(const char* paths_str = 0); Context(const char* paths_str = 0, const char* img_path_str = 0);
~Context(); ~Context();
void register_function(Function_Descriptor d, Primitive ip); void register_function(Function_Descriptor d, Primitive ip);
void register_function(Function_Descriptor d, Primitive ip, size_t arity); void register_function(Function_Descriptor d, Primitive ip, size_t arity);
void register_overload_stub(string name);
void register_functions(); void register_functions();
void setup_color_map();
}; };
} }
AliceBlue #F0F8FF
AntiqueWhite #FAEBD7
Aqua #00FFFF
Aquamarine #7FFFD4
Azure #F0FFFF
Beige #F5F5DC
Bisque #FFE4C4
Black #000000
BlanchedAlmond #FFEBCD
Blue #0000FF
BlueViolet #8A2BE2
Brown #A52A2A
BurlyWood #DEB887
CadetBlue #5F9EA0
Chartreuse #7FFF00
Chocolate #D2691E
Coral #FF7F50
CornflowerBlue #6495ED
Cornsilk #FFF8DC
Crimson #DC143C
Cyan #00FFFF
DarkBlue #00008B
DarkCyan #008B8B
DarkGoldenRod #B8860B
DarkGray #A9A9A9
DarkGrey #A9A9A9
DarkGreen #006400
DarkKhaki #BDB76B
DarkMagenta #8B008B
DarkOliveGreen #556B2F
Darkorange #FF8C00
DarkOrchid #9932CC
DarkRed #8B0000
DarkSalmon #E9967A
DarkSeaGreen #8FBC8F
DarkSlateBlue #483D8B
DarkSlateGray #2F4F4F
DarkSlateGrey #2F4F4F
DarkTurquoise #00CED1
DarkViolet #9400D3
DeepPink #FF1493
DeepSkyBlue #00BFFF
DimGray #696969
DimGrey #696969
DodgerBlue #1E90FF
FireBrick #B22222
FloralWhite #FFFAF0
ForestGreen #228B22
Fuchsia #FF00FF
Gainsboro #DCDCDC
GhostWhite #F8F8FF
Gold #FFD700
GoldenRod #DAA520
Gray #808080
Grey #808080
Green #008000
GreenYellow #ADFF2F
HoneyDew #F0FFF0
HotPink #FF69B4
IndianRed #CD5C5C
Indigo #4B0082
Ivory #FFFFF0
Khaki #F0E68C
Lavender #E6E6FA
LavenderBlush #FFF0F5
LawnGreen #7CFC00
LemonChiffon #FFFACD
LightBlue #ADD8E6
LightCoral #F08080
LightCyan #E0FFFF
LightGoldenRodYellow #FAFAD2
LightGray #D3D3D3
LightGrey #D3D3D3
LightGreen #90EE90
LightPink #FFB6C1
LightSalmon #FFA07A
LightSeaGreen #20B2AA
LightSkyBlue #87CEFA
LightSlateGray #778899
LightSlateGrey #778899
LightSteelBlue #B0C4DE
LightYellow #FFFFE0
Lime #00FF00
LimeGreen #32CD32
Linen #FAF0E6
Magenta #FF00FF
Maroon #800000
MediumAquaMarine #66CDAA
MediumBlue #0000CD
MediumOrchid #BA55D3
MediumPurple #9370D8
MediumSeaGreen #3CB371
MediumSlateBlue #7B68EE
MediumSpringGreen #00FA9A
MediumTurquoise #48D1CC
MediumVioletRed #C71585
MidnightBlue #191970
MintCream #F5FFFA
MistyRose #FFE4E1
Moccasin #FFE4B5
NavajoWhite #FFDEAD
Navy #000080
OldLace #FDF5E6
Olive #808000
OliveDrab #6B8E23
Orange #FFA500
OrangeRed #FF4500
Orchid #DA70D6
PaleGoldenRod #EEE8AA
PaleGreen #98FB98
PaleTurquoise #AFEEEE
PaleVioletRed #D87093
PapayaWhip #FFEFD5
PeachPuff #FFDAB9
Peru #CD853F
Pink #FFC0CB
Plum #DDA0DD
PowderBlue #B0E0E6
Purple #800080
Red #FF0000
RosyBrown #BC8F8F
RoyalBlue #4169E1
SaddleBrown #8B4513
Salmon #FA8072
SandyBrown #F4A460
SeaGreen #2E8B57
SeaShell #FFF5EE
Sienna #A0522D
Silver #C0C0C0
SkyBlue #87CEEB
SlateBlue #6A5ACD
SlateGray #708090
SlateGrey #708090
Snow #FFFAFA
SpringGreen #00FF7F
SteelBlue #4682B4
Tan #D2B48C
Teal #008080
Thistle #D8BFD8
Tomato #FF6347
Turquoise #40E0D0
Violet #EE82EE
Wheat #F5DEB3
White #FFFFFF
WhiteSmoke #F5F5F5
Yellow #FFFF00
YellowGreen #9ACD32
\ No newline at end of file
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "error.hpp" #include "error.hpp"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <sys/stat.h>
namespace Sass { namespace Sass {
...@@ -30,28 +31,28 @@ namespace Sass { ...@@ -30,28 +31,28 @@ namespace Sass {
{ {
std::FILE *f; std::FILE *f;
const char* path_str = path.c_str(); const char* path_str = path.c_str();
f = std::fopen(path_str, "rb"); struct stat st;
if (!f) { string tmp;
string path_with_extension(path + ".scss"); if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
f = std::fopen(path_with_extension.c_str(), "rb"); tmp = path + ".scss";
if (!f) { path_str = tmp.c_str();
const char* file_name_str = Prelexer::folders(path_str); if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
string path_with_underscore(Token::make(path_str, file_name_str).to_string() + const char *full_path_str = path.c_str();
const char *file_name_str = Prelexer::folders(full_path_str);
tmp = Token::make(full_path_str, file_name_str).to_string() +
"_" + "_" +
Token::make(file_name_str).to_string()); string(file_name_str);
f = std::fopen(path_with_underscore.c_str(), "rb"); path_str = tmp.c_str();
if (!f) { if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
string path_with_underscore_and_extension(path_with_underscore + ".scss"); tmp = tmp + ".scss";
f = std::fopen(path_with_underscore_and_extension.c_str(), "rb"); path_str = tmp.c_str();
if (!f) throw path; if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode))
throw path;
} }
} }
} }
if (std::fseek(f, 0, SEEK_END)) throw path; f = std::fopen(path_str, "rb");
int status = std::ftell(f); size_t len = st.st_size;
if (status < 0) throw path;
size_t len = status;
std::rewind(f);
char* source = new char[len + 1]; char* source = new char[len + 1];
size_t bytes_read = std::fread(source, sizeof(char), len, f); size_t bytes_read = std::fread(source, sizeof(char), len, f);
if (bytes_read != len) { if (bytes_read != len) {
...@@ -61,6 +62,8 @@ namespace Sass { ...@@ -61,6 +62,8 @@ namespace Sass {
source[len] = '\0'; source[len] = '\0';
char* end = source + len; char* end = source + len;
if (std::fclose(f)) throw path; if (std::fclose(f)) throw path;
const char *file_name_str = Prelexer::folders(path_str);
string include_path(path_str, file_name_str - path_str);
Document doc(ctx); Document doc(ctx);
doc.path = path; doc.path = path;
...@@ -72,6 +75,9 @@ namespace Sass { ...@@ -72,6 +75,9 @@ namespace Sass {
doc.end = end; doc.end = end;
doc.position = source; doc.position = source;
doc.context.source_refs.push_back(source); doc.context.source_refs.push_back(source);
if (!include_path.empty()) {
doc.context.include_paths.push_back(include_path);
}
return doc; return doc;
} }
...@@ -136,7 +142,8 @@ namespace Sass { ...@@ -136,7 +142,8 @@ namespace Sass {
// trim trailing whitespace // trim trailing whitespace
if (!retval.empty()) { if (!retval.empty()) {
size_t newlines = 0; size_t newlines = 0;
for (size_t i = retval.length() - 1; i >= 0; --i) { size_t i = retval.length();
while (i--) {
if (retval[i] == '\n') { if (retval[i] == '\n') {
++newlines; ++newlines;
continue; continue;
......
...@@ -101,17 +101,16 @@ namespace Sass { ...@@ -101,17 +101,16 @@ namespace Sass {
if (!lex< string_constant >()) throw_syntax_error("@import directive requires a url or quoted path"); if (!lex< string_constant >()) throw_syntax_error("@import directive requires a url or quoted path");
// TO DO: BETTER PATH HANDLING // TO DO: BETTER PATH HANDLING
string import_path(lexed.unquote()); string import_path(lexed.unquote());
const char* curr_path_start = path.c_str(); for (vector<string>::iterator path = context.include_paths.begin(); path < context.include_paths.end(); ++path) {
const char* curr_path_end = folders(curr_path_start);
string current_path(curr_path_start, curr_path_end - curr_path_start);
try { try {
Document importee(Document::make_from_file(context, current_path + import_path)); Document importee(Document::make_from_file(context, *path + import_path));
importee.parse_scss(); importee.parse_scss();
return importee.root; return importee.root;
} }
catch (string& path) { catch (string& path) {
throw_read_error("error reading file \"" + path + "\"");
} }
}
throw_read_error("error reading file \"" + import_path + "\"");
// unreached statement // unreached statement
return Node(); return Node();
} }
...@@ -523,6 +522,7 @@ namespace Sass { ...@@ -523,6 +522,7 @@ namespace Sass {
else if (lex < return_directive >()) { else if (lex < return_directive >()) {
Node ret_expr(context.new_Node(Node::return_directive, path, line, 1)); Node ret_expr(context.new_Node(Node::return_directive, path, line, 1));
ret_expr << parse_list(); ret_expr << parse_list();
ret_expr.should_eval() = true;
block << ret_expr; block << ret_expr;
semicolon = true; semicolon = true;
} }
...@@ -813,14 +813,26 @@ namespace Sass { ...@@ -813,14 +813,26 @@ namespace Sass {
const char* value = position; const char* value = position;
const char* rparen = find_first< exactly<')'> >(position); const char* rparen = find_first< exactly<')'> >(position);
if (!rparen) throw_syntax_error("URI is missing ')'"); if (!rparen) throw_syntax_error("URI is missing ')'");
Token contents(Token::make(value, rparen)); Token content_tok(Token::make(value, rparen));
Node content_node(context.new_Node(Node::string_constant, path, line, content_tok));
// lex< string_constant >(); // lex< string_constant >();
Node result(context.new_Node(Node::uri, path, line, contents)); Node result(context.new_Node(Node::uri, path, line, 1));
result << content_node;
position = rparen; position = rparen;
lex< exactly<')'> >(); lex< exactly<')'> >();
return result; return result;
} }
if (lex< image_url_prefix >())
{
Node url(parse_value());
if (!lex< exactly<')'> >()) throw_syntax_error("call to image-url is missing ')'");
Node the_call(context.new_Node(Node::image_url, path, line, 1));
the_call << url;
the_call.should_eval() = true;
return the_call;
}
if (peek< functional >()) if (peek< functional >())
{ return parse_function_call(); } { return parse_function_call(); }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "eval_apply.hpp" #include "eval_apply.hpp"
#include "document.hpp" #include "document.hpp"
#include "error.hpp" #include "error.hpp"
#include <cctype>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <cstdlib> #include <cstdlib>
...@@ -19,7 +20,7 @@ namespace Sass { ...@@ -19,7 +20,7 @@ namespace Sass {
// Evaluate the parse tree in-place (mostly). Most nodes will be left alone. // Evaluate the parse tree in-place (mostly). Most nodes will be left alone.
Node eval(Node expr, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx) Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name)
{ {
switch (expr.type()) switch (expr.type())
{ {
...@@ -29,7 +30,7 @@ namespace Sass { ...@@ -29,7 +30,7 @@ namespace Sass {
} break; } break;
case Node::function: { case Node::function: {
f_env[pair<string, size_t>(expr[0].to_string(), expr[1].size())] = Function(expr); f_env[expr[0].to_string()] = Function(expr);
return expr; return expr;
} break; } break;
...@@ -288,12 +289,24 @@ namespace Sass { ...@@ -288,12 +289,24 @@ namespace Sass {
return env[expr.token()]; return env[expr.token()];
} break; } break;
case Node::image_url: {
Node base(eval(expr[0], prefix, env, f_env, new_Node, ctx));
Node prefix(new_Node(Node::identifier, base.path(), base.line(), Token::make(ctx.image_path)));
Node fullpath(new_Node(Node::concatenation, base.path(), base.line(), 2));
Node url(new_Node(Node::uri, base.path(), base.line(), 1));
fullpath << prefix << base;
url << fullpath;
return url;
} break;
case Node::function_call: { case Node::function_call: {
// TO DO: default-constructed Function should be a generic callback (maybe) // TO DO: default-constructed Function should be a generic callback (maybe)
// eval the function name in case it's interpolated // eval the function name in case it's interpolated
expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx); expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx, true);
pair<string, size_t> sig(expr[0].to_string(), expr[1].size()); string name(expr[0].to_string());
if (!f_env.count(sig)) { if (!f_env.count(name)) {
// no definition available; just pass it through (with evaluated args)
Node args(expr[1]); Node args(expr[1]);
for (size_t i = 0, S = args.size(); i < S; ++i) { for (size_t i = 0, S = args.size(); i < S; ++i) {
args[i] = eval(args[i], prefix, env, f_env, new_Node, ctx); args[i] = eval(args[i], prefix, env, f_env, new_Node, ctx);
...@@ -301,7 +314,16 @@ namespace Sass { ...@@ -301,7 +314,16 @@ namespace Sass {
return expr; return expr;
} }
else { else {
return apply_function(f_env[sig], expr[1], prefix, env, f_env, new_Node, ctx); // check to see if the function is primitive/built-in
Function f(f_env[name]);
if (f.overloaded) {
stringstream s;
s << name << " " << expr[1].size();
string resolved_name(s.str());
if (!f_env.count(resolved_name)) throw_eval_error("wrong number of arguments to " + name, expr.path(), expr.line());
f = f_env[resolved_name];
}
return apply_function(f, expr[1], prefix, env, f_env, new_Node, ctx);
} }
} break; } break;
...@@ -327,6 +349,17 @@ namespace Sass { ...@@ -327,6 +349,17 @@ namespace Sass {
} }
} break; } break;
case Node::identifier: {
string id_str(expr.to_string());
to_lowercase(id_str);
if (!function_name && ctx.color_names_to_values.count(id_str)) {
return ctx.color_names_to_values[id_str];
}
else {
return expr;
}
} break;
case Node::string_schema: case Node::string_schema:
case Node::value_schema: case Node::value_schema:
case Node::identifier_schema: { case Node::identifier_schema: {
...@@ -582,7 +615,7 @@ namespace Sass { ...@@ -582,7 +615,7 @@ namespace Sass {
// environment to the current one, then copy the body and eval in the new // environment to the current one, then copy the body and eval in the new
// environment. // environment.
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope) Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope)
{ {
Node params(mixin[1]); Node params(mixin[1]);
Node body(new_Node(mixin[2])); // clone the body Node body(new_Node(mixin[2])); // clone the body
...@@ -650,7 +683,7 @@ namespace Sass { ...@@ -650,7 +683,7 @@ namespace Sass {
// Apply a function -- bind the arguments and pass them to the underlying // Apply a function -- bind the arguments and pass them to the underlying
// primitive function implementation, then return its value. // primitive function implementation, then return its value.
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx) Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx)
{ {
if (f.primitive) { if (f.primitive) {
map<Token, Node> bindings; map<Token, Node> bindings;
...@@ -663,7 +696,7 @@ namespace Sass { ...@@ -663,7 +696,7 @@ namespace Sass {
} }
else { else {
// TO DO: ensure (j < f.parameters.size()) // TO DO: ensure (j < f.parameters.size())
bindings[f.parameters[j]] = eval(args[i], prefix, env, f_env, new_Node, ctx); bindings[f.parameters[j].token()] = eval(args[i], prefix, env, f_env, new_Node, ctx);
++j; ++j;
} }
} }
...@@ -827,7 +860,13 @@ namespace Sass { ...@@ -827,7 +860,13 @@ namespace Sass {
} break; } break;
case Node::return_directive: { case Node::return_directive: {
return eval(stm[0], Node(), bindings, ctx.function_env, new_Node, ctx); Node retval(eval(stm[0], Node(), bindings, ctx.function_env, new_Node, ctx));
if (retval.type() == Node::comma_list || retval.type() == Node::space_list) {
for (size_t i = 0, S = retval.size(); i < S; ++i) {
retval[i] = eval(retval[i], Node(), bindings, ctx.function_env, new_Node, ctx);
}
}
return retval;
} break; } break;
default: { default: {
...@@ -1177,11 +1216,9 @@ namespace Sass { ...@@ -1177,11 +1216,9 @@ namespace Sass {
default: { default: {
// something // something
cerr << "pux!" << endl;
} break; } break;
} }
} }
cerr << "blux!" << endl;
return Node(); return Node();
} }
...@@ -1243,4 +1280,7 @@ namespace Sass { ...@@ -1243,4 +1280,7 @@ namespace Sass {
Node selector_butlast(Node sel, Node_Factory& new_Node) Node selector_butlast(Node sel, Node_Factory& new_Node)
{ return selector_but(sel, new_Node, 0, 1); } { return selector_but(sel, new_Node, 0, 1); }
void to_lowercase(string& s)
{ for (size_t i = 0, L = s.length(); i < L; ++i) s[i] = tolower(s[i]); }
} }
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
namespace Sass { namespace Sass {
using std::map; using std::map;
Node eval(Node expr, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx); Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name = false);
Node function_eval(string name, Node stm, Environment& bindings, Node_Factory& new_Node, Context& ctx, bool toplevel = false); Node function_eval(string name, Node stm, Environment& bindings, Node_Factory& new_Node, Context& ctx, bool toplevel = false);
Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node); Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node);
double operate(Node::Type op, double lhs, double rhs); double operate(Node::Type op, double lhs, double rhs);
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope = false); Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope = false);
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx); Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx);
Node expand_selector(Node sel, Node pre, Node_Factory& new_Node); Node expand_selector(Node sel, Node pre, Node_Factory& new_Node);
Node expand_backref(Node sel, Node pre); Node expand_backref(Node sel, Node pre);
void extend_selectors(vector<pair<Node, Node> >&, multimap<Node, Node>&, Node_Factory&); void extend_selectors(vector<pair<Node, Node> >&, multimap<Node, Node>&, Node_Factory&);
...@@ -29,4 +29,5 @@ namespace Sass { ...@@ -29,4 +29,5 @@ namespace Sass {
Node selector_butfirst(Node sel, Node_Factory& new_Node); Node selector_butfirst(Node sel, Node_Factory& new_Node);
Node selector_butlast(Node sel, Node_Factory& new_Node); Node selector_butlast(Node sel, Node_Factory& new_Node);
void to_lowercase(string& s);
} }
\ No newline at end of file
...@@ -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());
} }
...@@ -34,12 +34,12 @@ namespace Sass { ...@@ -34,12 +34,12 @@ namespace Sass {
} }
Function_Descriptor rgba_4_descriptor = Function_Descriptor rgba_4_descriptor =
{ "rgba", "$red", "$green", "$blue", "$alpha", 0 }; { "rgba 4", "$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());
} }
...@@ -47,37 +47,37 @@ namespace Sass { ...@@ -47,37 +47,37 @@ namespace Sass {
} }
Function_Descriptor rgba_2_descriptor = Function_Descriptor rgba_2_descriptor =
{ "rgba", "$color", "$alpha", 0 }; { "rgba 2", "$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];
} }
...@@ -104,20 +104,20 @@ namespace Sass { ...@@ -104,20 +104,20 @@ namespace Sass {
} }
Function_Descriptor mix_2_descriptor = Function_Descriptor mix_2_descriptor =
{ "mix", "$color1", "$color2", 0 }; { "mix 2", "$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 3", "$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();
...@@ -505,19 +505,19 @@ namespace Sass { ...@@ -505,19 +505,19 @@ namespace Sass {
} }
Function_Descriptor join_2_descriptor = Function_Descriptor join_2_descriptor =
{ "join", "$list1", "$list2", 0 }; { "join 2", "$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 3", "$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 2", "$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 3", "$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));
...@@ -583,30 +583,37 @@ namespace Sass { ...@@ -583,30 +583,37 @@ namespace Sass {
} }
Function_Descriptor compact_1_descriptor = Function_Descriptor compact_1_descriptor =
{ "compact", "$arg1", 0 }; { "compact 1", "$arg1", 0 };
Function_Descriptor compact_2_descriptor = Function_Descriptor compact_2_descriptor =
{ "compact", "$arg1", "$arg2", 0 }; { "compact 2", "$arg1", "$arg2", 0 };
Function_Descriptor compact_3_descriptor = Function_Descriptor compact_3_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", 0 }; { "compact 3", "$arg1", "$arg2", "$arg3", 0 };
Function_Descriptor compact_4_descriptor = Function_Descriptor compact_4_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", 0 }; { "compact 4", "$arg1", "$arg2", "$arg3", "$arg4", 0 };
Function_Descriptor compact_5_descriptor = Function_Descriptor compact_5_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", 0 }; { "compact 5", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", 0 };
Function_Descriptor compact_6_descriptor = Function_Descriptor compact_6_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", { "compact 6", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", 0 }; "$arg6", 0 };
Function_Descriptor compact_7_descriptor = Function_Descriptor compact_7_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", { "compact 7", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", 0 }; "$arg6", "$arg7", 0 };
Function_Descriptor compact_8_descriptor = Function_Descriptor compact_8_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", { "compact 8", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", "$arg8", 0 }; "$arg6", "$arg7", "$arg8", 0 };
Function_Descriptor compact_9_descriptor = Function_Descriptor compact_9_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", { "compact 9", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", "$arg8", "$arg9", 0 }; "$arg6", "$arg7", "$arg8", "$arg9", 0 };
Function_Descriptor compact_10_descriptor = Function_Descriptor compact_10_descriptor =
{ "compact", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", { "compact 10", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5",
"$arg6", "$arg7", "$arg8", "$arg9", "$arg10", 0 }; "$arg6", "$arg7", "$arg8", "$arg9", "$arg10", 0 };
Function_Descriptor compact_11_descriptor =
{ "compact 11", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", "$arg6",
"$arg7", "$arg8", "$arg9", "$arg10", "$arg11", 0 };
Function_Descriptor compact_12_descriptor =
{ "compact 12", "$arg1", "$arg2", "$arg3", "$arg4", "$arg5", "arg6",
"$arg7", "$arg8", "$arg9", "$arg10", "$arg11", "$arg12", 0 };
// Introspection Functions ///////////////////////////////////////////// // Introspection Functions /////////////////////////////////////////////
...@@ -619,8 +626,8 @@ namespace Sass { ...@@ -619,8 +626,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 +665,8 @@ namespace Sass { ...@@ -658,8 +665,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 +691,8 @@ namespace Sass { ...@@ -684,8 +691,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 +714,9 @@ namespace Sass { ...@@ -707,9 +714,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 +749,8 @@ namespace Sass { ...@@ -742,8 +749,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,41 +8,52 @@ ...@@ -8,41 +8,52 @@
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;
bool overloaded;
Function() Function()
{ /* TO DO: set up the generic callback here */ } { /* TO DO: set up the generic callback here */ }
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),
overloaded(false)
{ } { }
Function(Function_Descriptor d, Primitive ip) // Stub for overloaded primitives
Function(string name, bool overloaded = true)
: name(name),
parameters(Node()),
definition(Node()),
primitive(0),
overloaded(overloaded)
{ }
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),
overloaded(false)
{ {
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 +70,98 @@ namespace Sass { ...@@ -59,98 +70,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 +173,28 @@ namespace Sass { ...@@ -162,26 +173,28 @@ 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); extern Function_Descriptor compact_11_descriptor;
extern Function_Descriptor compact_12_descriptor;
Node compact(const Node parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Introspection Functions ///////////////////////////////////////////// // Introspection Functions /////////////////////////////////////////////
extern Function_Descriptor type_of_descriptor; extern 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);
} }
......
...@@ -128,6 +128,7 @@ namespace Sass { ...@@ -128,6 +128,7 @@ namespace Sass {
value, value,
identifier, identifier,
uri, uri,
image_url,
textual_percentage, textual_percentage,
textual_dimension, textual_dimension,
textual_number, textual_number,
......
...@@ -268,7 +268,8 @@ namespace Sass { ...@@ -268,7 +268,8 @@ namespace Sass {
case uri: { case uri: {
string result("url("); string result("url(");
result += token().to_string(); // result += token().to_string();
result += at(0).to_string();
result += ")"; result += ")";
return result; return result;
} break; } break;
......
...@@ -278,6 +278,11 @@ namespace Sass { ...@@ -278,6 +278,11 @@ namespace Sass {
optional<spaces>, optional<spaces>,
exactly<')'> >(src); exactly<')'> >(src);
} }
// Match SCSS image-url function
extern const char image_url_kwd[] = "image-url(";
const char* image_url_prefix(const char* src) {
return exactly<image_url_kwd>(src);
}
// Match CSS "!important" keyword. // Match CSS "!important" keyword.
extern const char important_kwd[] = "important"; extern const char important_kwd[] = "important";
const char* important(const char* src) { const char* important(const char* src) {
......
...@@ -354,6 +354,8 @@ namespace Sass { ...@@ -354,6 +354,8 @@ namespace Sass {
// Match CSS uri specifiers. // Match CSS uri specifiers.
const char* uri_prefix(const char* src); const char* uri_prefix(const char* src);
const char* uri(const char* src); const char* uri(const char* src);
// Match SCSS image-url function.
const char* image_url_prefix(const char* src);
// Match CSS "!important" keyword. // Match CSS "!important" keyword.
const char* important(const char* src); const char* important(const char* src);
// Match Sass "!default" keyword. // Match Sass "!default" keyword.
......
...@@ -58,7 +58,8 @@ extern "C" { ...@@ -58,7 +58,8 @@ extern "C" {
{ {
using namespace Sass; using namespace Sass;
try { try {
Context cpp_ctx(c_ctx->options.include_paths); Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path);
// cpp_ctx.image_path = c_ctx->options.image_path;
// Document doc(0, c_ctx->input_string, cpp_ctx); // Document doc(0, c_ctx->input_string, cpp_ctx);
Document doc(Document::make_from_source_chars(cpp_ctx, c_ctx->source_string)); Document doc(Document::make_from_source_chars(cpp_ctx, c_ctx->source_string));
c_ctx->output_string = process_document(doc, c_ctx->options.output_style); c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
...@@ -93,8 +94,11 @@ extern "C" { ...@@ -93,8 +94,11 @@ extern "C" {
{ {
using namespace Sass; using namespace Sass;
try { try {
Context cpp_ctx(c_ctx->options.include_paths); Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path);
// Document doc(c_ctx->input_path, 0, cpp_ctx); // Document doc(c_ctx->input_path, 0, cpp_ctx);
// string path_string(c_ctx->options.image_path);
// path_string = "'" + path_string + "/";
// cpp_ctx.image_path = c_ctx->options.image_path;
Document doc(Document::make_from_file(cpp_ctx, string(c_ctx->input_path))); Document doc(Document::make_from_file(cpp_ctx, string(c_ctx->input_path)));
// cerr << "MADE A DOC AND CONTEXT OBJ" << endl; // cerr << "MADE A DOC AND CONTEXT OBJ" << endl;
// cerr << "REGISTRY: " << doc.context.registry.size() << endl; // cerr << "REGISTRY: " << doc.context.registry.size() << endl;
......
...@@ -12,6 +12,7 @@ extern "C" { ...@@ -12,6 +12,7 @@ extern "C" {
struct sass_options { struct sass_options {
int output_style; int output_style;
char* include_paths; char* include_paths;
char* image_path;
}; };
struct sass_context { struct sass_context {
......
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