Commit 9d10d034 by Aaron Leung

Bam, all allocations are deallocated.

parent 104d269a
......@@ -42,6 +42,7 @@ namespace Sass {
: global_env(Environment()),
function_env(map<pair<string, size_t>, Function>()),
source_refs(vector<char*>()),
registry(vector<vector<Node>*>()),
include_paths(vector<string>()),
ref_count(0)
{
......@@ -51,9 +52,11 @@ namespace Sass {
Context::~Context()
{
for (int i = 0; i < source_refs.size(); ++i) {
int i;
for (i = 0; i < source_refs.size(); ++i) {
delete[] source_refs[i];
}
cerr << "Deallocated " << i << " source string(s)." << endl;
}
inline void Context::register_function(Function_Descriptor d, Implementation ip)
......
......@@ -45,6 +45,7 @@ namespace Sass {
Environment global_env;
map<pair<string, size_t>, Function> function_env;
vector<char*> source_refs; // all the source c-strings
vector<vector<Node>*> registry; // all the child vectors
size_t ref_count;
void collect_include_paths(const char* paths_str);
......
......@@ -12,7 +12,7 @@ namespace Sass {
source(source_str),
line_number(1),
context(ctx),
root(Node(Node::root, 1)),
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{
if (source_str) {
......@@ -49,7 +49,7 @@ namespace Sass {
: path(path), source(source),
line_number(1), own_source(false),
context(*(new Context())),
root(Node(Node::root, 1)),
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{
if (!source) {
......@@ -78,7 +78,7 @@ namespace Sass {
: path(path), source(0),
line_number(1), own_source(false),
context(context),
root(Node(Node::root, 1)),
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{
std::FILE *f;
......@@ -108,7 +108,7 @@ namespace Sass {
line_number(line_number),
own_source(false),
context(context),
root(Node(Node::root, 1)),
root(Node(Node::root, context.registry, 1)),
lexed(Token::make())
{ }
......
......@@ -26,7 +26,7 @@ namespace Sass {
root[0].has_expansions = true;
if (!lex< exactly<';'> >()) syntax_error("top-level @include directive must be terminated by ';'");
}
else if (peek< variable >(position)) {
else if (peek< variable >(position)) {
root << parse_assignment();
if (!lex< exactly<';'> >()) syntax_error("top-level variable binding must be terminated by ';'");
}
......@@ -64,14 +64,14 @@ namespace Sass {
Node params(parse_mixin_parameters());
if (!peek< exactly<'{'> >()) syntax_error("body for mixin " + name.content.token.to_string() + " must begin with a '{'");
Node body(parse_block(true));
Node mixin(Node::mixin, line_number, 3);
Node mixin(Node::mixin, context.registry, line_number, 3);
mixin << name << params << body;
return mixin;
}
Node Document::parse_mixin_parameters()
{
Node params(Node::parameters, line_number);
Node params(Node::parameters, context.registry, line_number);
Token name(lexed);
if (lex< exactly<'('> >()) {
if (peek< variable >()) {
......@@ -92,7 +92,7 @@ namespace Sass {
Node var(Node::variable, line_number, lexed);
if (lex< exactly<':'> >()) { // default value
Node val(parse_space_list());
Node par_and_val(Node::assignment, line_number, 2);
Node par_and_val(Node::assignment, context.registry, line_number, 2);
par_and_val << var << val;
return par_and_val;
}
......@@ -107,7 +107,7 @@ namespace Sass {
if (!lex< identifier >()) syntax_error("invalid name in @include directive");
Node name(Node::identifier, line_number, lexed);
Node args(parse_arguments());
Node call(Node::expansion, line_number, 3);
Node call(Node::expansion, context.registry, line_number, 3);
call << name << args;
return call;
}
......@@ -115,7 +115,7 @@ namespace Sass {
Node Document::parse_arguments()
{
Token name(lexed);
Node args(Node::arguments, line_number);
Node args(Node::arguments, context.registry, line_number);
if (lex< exactly<'('> >()) {
if (!peek< exactly<')'> >(position)) {
args << parse_argument();
......@@ -137,7 +137,7 @@ namespace Sass {
Node var(Node::variable, line_number, lexed);
lex< exactly<':'> >();
Node val(parse_space_list());
Node assn(Node::assignment, line_number, 2);
Node assn(Node::assignment, context.registry, line_number, 2);
assn << var << val;
return assn;
}
......@@ -152,14 +152,14 @@ namespace Sass {
Node var(Node::variable, line_number, lexed);
if (!lex< exactly<':'> >()) syntax_error("expected ':' after " + lexed.to_string() + " in assignment statement");
Node val(parse_list());
Node assn(Node::assignment, line_number, 2);
Node assn(Node::assignment, context.registry, line_number, 2);
assn << var << val;
return assn;
}
Node Document::parse_ruleset(bool definition)
{
Node ruleset(Node::ruleset, line_number, 2);
Node ruleset(Node::ruleset, context.registry, line_number, 2);
ruleset << parse_selector_group();
// if (ruleset[0].type == Node::selector) cerr << "ruleset starts with selector" << endl;
// if (ruleset[0].type == Node::selector_group) cerr << "ruleset starts with selector_group" << endl;
......@@ -178,7 +178,7 @@ namespace Sass {
Node sel1(parse_selector());
if (!peek< exactly<','> >()) return sel1;
Node group(Node::selector_group, line_number, 2);
Node group(Node::selector_group, context.registry, line_number, 2);
group << sel1;
while (lex< exactly<','> >()) group << parse_selector();
return group;
......@@ -212,7 +212,7 @@ namespace Sass {
peek< exactly<')'> >() ||
peek< exactly<'{'> >()) return seq1;
Node selector(Node::selector, line_number, 2);
Node selector(Node::selector, context.registry, line_number, 2);
if (seq1.has_backref) selector.has_backref = true;
selector << seq1;
......@@ -255,7 +255,7 @@ namespace Sass {
{ return simp1; }
// now we know we have a sequence of simple selectors
Node seq(Node::simple_selector_sequence, line_number, 2);
Node seq(Node::simple_selector_sequence, context.registry, line_number, 2);
seq << simp1;
seq.has_backref = saw_backref;
......@@ -323,14 +323,14 @@ namespace Sass {
Node Document::parse_pseudo() {
if (lex< pseudo_not >()) {
Node ps_not(Node::pseudo_negation, line_number, 2);
Node ps_not(Node::pseudo_negation, context.registry, line_number, 2);
ps_not << Node(Node::value, line_number, lexed);
ps_not << parse_selector_group();
lex< exactly<')'> >();
return ps_not;
}
else if (lex< sequence< pseudo_prefix, functional > >()) {
Node pseudo(Node::functional_pseudo, line_number, 2);
Node pseudo(Node::functional_pseudo, context.registry, line_number, 2);
Token name(lexed);
pseudo << Node(Node::value, line_number, name);
if (lex< alternatives< even, odd > >()) {
......@@ -370,7 +370,7 @@ namespace Sass {
Node Document::parse_attribute_selector()
{
Node attr_sel(Node::attribute_selector, line_number, 3);
Node attr_sel(Node::attribute_selector, context.registry, line_number, 3);
lex< exactly<'['> >();
if (!lex< type_selector >()) syntax_error("invalid attribute name in attribute selector");
Token name(lexed);
......@@ -390,7 +390,7 @@ namespace Sass {
{
lex< exactly<'{'> >();
bool semicolon = false;
Node block(Node::block, line_number, 1);
Node block(Node::block, context.registry, line_number, 1);
block << Node(Node::flags);
while (!lex< exactly<'}'> >()) {
if (semicolon) {
......@@ -463,7 +463,7 @@ namespace Sass {
}
Node Document::parse_rule() {
Node rule(Node::rule, line_number, 2);
Node rule(Node::rule, context.registry, line_number, 2);
if (!lex< identifier >()) syntax_error("invalid property name");
rule << Node(Node::property, line_number, lexed);
if (!lex< exactly<':'> >()) syntax_error("property \"" + lexed.to_string() + "\" must be followed by a ':'");
......@@ -482,12 +482,12 @@ namespace Sass {
peek< exactly<'}'> >(position) ||
peek< exactly<'{'> >(position) ||
peek< exactly<')'> >(position))
{ return Node(Node::nil, line_number); }
{ return Node(Node::nil, context.registry, line_number); }
Node list1(parse_space_list());
// if it's a singleton, return it directly; don't wrap it
if (!peek< exactly<','> >(position)) return list1;
Node comma_list(Node::comma_list, line_number, 2);
Node comma_list(Node::comma_list, context.registry, line_number, 2);
comma_list << list1;
comma_list.eval_me |= list1.eval_me;
......@@ -512,7 +512,7 @@ namespace Sass {
peek< exactly<','> >(position))
{ return disj1; }
Node space_list(Node::space_list, line_number, 2);
Node space_list(Node::space_list, context.registry, line_number, 2);
space_list << disj1;
space_list.eval_me |= disj1.eval_me;
......@@ -536,7 +536,7 @@ namespace Sass {
// if it's a singleton, return it directly; don't wrap it
if (!peek< sequence< or_kwd, negate< identifier > > >()) return conj1;
Node disjunction(Node::disjunction, line_number, 2);
Node disjunction(Node::disjunction, context.registry, line_number, 2);
disjunction << conj1;
while (lex< sequence< or_kwd, negate< identifier > > >()) disjunction << parse_conjunction();
disjunction.eval_me = true;
......@@ -550,7 +550,7 @@ namespace Sass {
// if it's a singleton, return it directly; don't wrap it
if (!peek< sequence< and_kwd, negate< identifier > > >()) return rel1;
Node conjunction(Node::conjunction, line_number, 2);
Node conjunction(Node::conjunction, context.registry, line_number, 2);
conjunction << rel1;
while (lex< sequence< and_kwd, negate< identifier > > >()) conjunction << parse_relation();
conjunction.eval_me = true;
......@@ -569,7 +569,7 @@ namespace Sass {
peek< lte_op >(position)))
{ return expr1; }
Node relation(Node::relation, line_number, 3);
Node relation(Node::relation, context.registry, line_number, 3);
expr1.eval_me = true;
relation << expr1;
......@@ -596,7 +596,7 @@ namespace Sass {
peek< sequence< negate< number >, exactly<'-'> > >(position)))
{ return term1; }
Node expression(Node::expression, line_number, 3);
Node expression(Node::expression, context.registry, line_number, 3);
term1.eval_me = true;
expression << term1;
......@@ -624,7 +624,7 @@ namespace Sass {
peek< exactly<'/'> >(position)))
{ return fact1; }
Node term(Node::term, line_number, 3);
Node term(Node::term, context.registry, line_number, 3);
term << fact1;
if (fact1.eval_me) term.eval_me = true;
......@@ -725,7 +725,7 @@ namespace Sass {
lex< identifier >();
Node name(Node::identifier, line_number, lexed);
Node args(parse_arguments());
Node call(Node::function_call, line_number, 2);
Node call(Node::function_call, context.registry, line_number, 2);
call << name << args;
call.eval_me = true;
return call;
......
......@@ -17,7 +17,7 @@ namespace Sass {
throw Error(Error::evaluation, line_number, fn, message);
}
Node eval(Node& expr, Environment& env, map<pair<string, size_t>, Function>& f_env)
Node eval(Node& expr, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry)
{
switch (expr.type)
{
......@@ -31,7 +31,7 @@ namespace Sass {
Node args(expr[1]);
if (!env.query(name)) eval_error("mixin " + name.to_string() + " is undefined", expr.line_number, expr.file_name);
Node mixin(env[name]);
Node expansion(apply_mixin(mixin, args, env, f_env));
Node expansion(apply_mixin(mixin, args, env, f_env, registry));
expr.content.children->pop_back();
expr.content.children->pop_back();
expr += expansion;
......@@ -39,13 +39,13 @@ namespace Sass {
} break;
case Node::ruleset: {
eval(expr[1], env, f_env);
eval(expr[1], env, f_env, registry);
return expr;
} break;
case Node::root: {
for (int i = 0; i < expr.size(); ++i) {
eval(expr[i], env, f_env);
eval(expr[i], env, f_env, registry);
}
return expr;
} break;
......@@ -54,7 +54,7 @@ namespace Sass {
Environment current;
current.link(env);
for (int i = 0; i < expr.size(); ++i) {
eval(expr[i], current, f_env);
eval(expr[i], current, f_env, registry);
}
return expr;
} break;
......@@ -63,11 +63,11 @@ namespace Sass {
Node val(expr[1]);
if (val.type == Node::comma_list || val.type == Node::space_list) {
for (int i = 0; i < val.size(); ++i) {
if (val[i].eval_me) val[i] = eval(val[i], env, f_env);
if (val[i].eval_me) val[i] = eval(val[i], env, f_env, registry);
}
}
else {
val = eval(val, env, f_env);
val = eval(val, env, f_env, registry);
}
Node var(expr[0]);
if (env.query(var.content.token)) {
......@@ -83,18 +83,18 @@ namespace Sass {
Node rhs(expr[1]);
if (rhs.type == Node::comma_list || rhs.type == Node::space_list) {
for (int i = 0; i < rhs.size(); ++i) {
if (rhs[i].eval_me) rhs[i] = eval(rhs[i], env, f_env);
if (rhs[i].eval_me) rhs[i] = eval(rhs[i], env, f_env, registry);
}
}
else {
if (rhs.eval_me) expr[1] = eval(rhs, env, f_env);
if (rhs.eval_me) expr[1] = eval(rhs, env, f_env, registry);
}
return expr;
} break;
case Node::comma_list:
case Node::space_list: {
if (expr.eval_me) expr[0] = eval(expr[0], env, f_env);
if (expr.eval_me) expr[0] = eval(expr[0], env, f_env, registry);
return expr;
} break;
......@@ -103,7 +103,7 @@ namespace Sass {
for (int i = 0; i < expr.size(); ++i) {
// if (expr[i].type == Node::relation ||
// expr[i].type == Node::function_call && expr[0].content.token.to_string() == "not") {
result = eval(expr[i], env, f_env);
result = eval(expr[i], env, f_env, registry);
if (result.type == Node::boolean && result.content.boolean_value == false) continue;
else return result;
}
......@@ -113,7 +113,7 @@ namespace Sass {
case Node::conjunction: {
Node result;
for (int i = 0; i < expr.size(); ++i) {
result = eval(expr[i], env, f_env);
result = eval(expr[i], env, f_env, registry);
if (result.type == Node::boolean && result.content.boolean_value == false) return result;
}
return result;
......@@ -121,9 +121,9 @@ namespace Sass {
case Node::relation: {
Node lhs(eval(expr[0], env, f_env));
Node lhs(eval(expr[0], env, f_env, registry));
Node op(expr[1]);
Node rhs(eval(expr[2], env, f_env));
Node rhs(eval(expr[2], env, f_env, registry));
Node T(Node::boolean);
T.line_number = lhs.line_number;
......@@ -142,26 +142,26 @@ namespace Sass {
} break;
case Node::expression: {
Node acc(Node::expression, expr.line_number, 1);
acc << eval(expr[0], env, f_env);
Node rhs(eval(expr[2], env, f_env));
accumulate(expr[1].type, acc, rhs);
Node acc(Node::expression, registry, expr.line_number, 1);
acc << eval(expr[0], env, f_env, registry);
Node rhs(eval(expr[2], env, f_env, registry));
accumulate(expr[1].type, acc, rhs, registry);
for (int i = 3; i < expr.size(); i += 2) {
Node rhs(eval(expr[i+1], env, f_env));
accumulate(expr[i].type, acc, rhs);
Node rhs(eval(expr[i+1], env, f_env, registry));
accumulate(expr[i].type, acc, rhs, registry);
}
return acc.size() == 1 ? acc[0] : acc;
} break;
case Node::term: {
if (expr.eval_me) {
Node acc(Node::expression, expr.line_number, 1);
acc << eval(expr[0], env, f_env);
Node rhs(eval(expr[2], env, f_env));
accumulate(expr[1].type, acc, rhs);
Node acc(Node::expression, registry, expr.line_number, 1);
acc << eval(expr[0], env, f_env, registry);
Node rhs(eval(expr[2], env, f_env, registry));
accumulate(expr[1].type, acc, rhs, registry);
for (int i = 3; i < expr.size(); i += 2) {
Node rhs(eval(expr[i+1], env, f_env));
accumulate(expr[i].type, acc, rhs);
Node rhs(eval(expr[i+1], env, f_env, registry));
accumulate(expr[i].type, acc, rhs, registry);
}
return acc.size() == 1 ? acc[0] : acc;
}
......@@ -188,7 +188,7 @@ namespace Sass {
} break;
case Node::textual_hex: {
Node triple(Node::numeric_color, expr.line_number, 4);
Node triple(Node::numeric_color, registry, expr.line_number, 4);
Token hext(Token::make(expr.content.token.begin+1, expr.content.token.end));
if (hext.length() == 6) {
for (int i = 0; i < 6; i += 2) {
......@@ -217,7 +217,7 @@ namespace Sass {
ss << "no function named " << expr[0].content.token.to_string() << " taking " << expr[1].size() << " arguments has been defined";
eval_error(ss.str(), expr.line_number, expr.file_name);
}
return apply_function(f_env[sig], expr[1], env, f_env);
return apply_function(f_env[sig], expr[1], env, f_env, registry);
} break;
default: {
......@@ -226,7 +226,7 @@ namespace Sass {
}
}
Node accumulate(Node::Type op, Node& acc, Node& rhs)
Node accumulate(Node::Type op, Node& acc, Node& rhs, vector<vector<Node>*>& registry)
{
Node lhs(acc.content.children->back());
double lnum = lhs.content.numeric_value;
......@@ -266,7 +266,7 @@ namespace Sass {
double b = operate(op, lhs.content.numeric_value, rhs[2].content.numeric_value);
double a = rhs[3].content.numeric_value;
acc.content.children->pop_back();
acc << Node(acc.line_number, r, g, b, a);
acc << Node(registry, acc.line_number, r, g, b, a);
}
// trying to handle weird edge cases ... not sure if it's worth it
else if (op == Node::div) {
......@@ -287,7 +287,7 @@ namespace Sass {
double b = operate(op, lhs[2].content.numeric_value, rhs.content.numeric_value);
double a = lhs[3].content.numeric_value;
acc.content.children->pop_back();
acc << Node(acc.line_number, r, g, b, a);
acc << Node(registry, acc.line_number, r, g, b, a);
}
else if (lhs.type == Node::numeric_color && rhs.type == Node::numeric_color) {
if (lhs[3].content.numeric_value != rhs[3].content.numeric_value) eval_error("alpha channels must be equal for " + lhs.to_string("") + " + " + rhs.to_string(""), lhs.line_number, lhs.file_name);
......@@ -296,7 +296,7 @@ namespace Sass {
double b = operate(op, lhs[2].content.numeric_value, rhs[2].content.numeric_value);
double a = lhs[3].content.numeric_value;
acc.content.children->pop_back();
acc << Node(acc.line_number, r, g, b, a);
acc << Node(registry, acc.line_number, r, g, b, a);
}
// else if (lhs.type == Node::concatenation) {
// lhs << rhs;
......@@ -327,10 +327,10 @@ namespace Sass {
}
}
Node apply_mixin(Node& mixin, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env)
Node apply_mixin(Node& mixin, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry)
{
Node params(mixin[1]);
Node body(mixin[2].clone());
Node body(mixin[2].clone(registry));
Environment bindings;
// bind arguments
for (int i = 0, j = 0; i < args.size(); ++i) {
......@@ -349,7 +349,7 @@ namespace Sass {
}
if (!valid_param) eval_error("mixin " + mixin[0].to_string("") + " has no parameter named " + name.to_string(), arg.line_number, arg.file_name);
if (!bindings.query(name)) {
bindings[name] = eval(arg[1], env, f_env);
bindings[name] = eval(arg[1], env, f_env, registry);
}
}
else {
......@@ -361,7 +361,7 @@ namespace Sass {
}
Node param(params[j]);
Token name(param.type == Node::variable ? param.content.token : param[0].content.token);
bindings[name] = eval(args[i], env, f_env);
bindings[name] = eval(args[i], env, f_env, registry);
++j;
}
}
......@@ -371,19 +371,19 @@ namespace Sass {
Node param(params[i]);
Token name(param[0].content.token);
if (!bindings.query(name)) {
bindings[name] = eval(param[1], env, f_env);
bindings[name] = eval(param[1], env, f_env, registry);
}
}
}
// lexically link the new environment and eval the mixin's body
bindings.link(env.global ? *env.global : env);
for (int i = 0; i < body.size(); ++i) {
body[i] = eval(body[i], bindings, f_env);
body[i] = eval(body[i], bindings, f_env, registry);
}
return body;
}
Node apply_function(const Function& f, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env)
Node apply_function(const Function& f, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry)
{
map<Token, Node> bindings;
// bind arguments
......@@ -391,15 +391,15 @@ namespace Sass {
if (args[i].type == Node::assignment) {
Node arg(args[i]);
Token name(arg[0].content.token);
bindings[name] = eval(arg[1], env, f_env);
bindings[name] = eval(arg[1], env, f_env, registry);
}
else {
// TO DO: ensure (j < f.parameters.size())
bindings[f.parameters[j]] = eval(args[i], env, f_env);
bindings[f.parameters[j]] = eval(args[i], env, f_env, registry);
++j;
}
}
return f(bindings);
return f(bindings, registry);
}
}
\ No newline at end of file
......@@ -11,10 +11,10 @@
namespace Sass {
using std::map;
Node eval(Node& expr, Environment& env, map<pair<string, size_t>, Function>& f_env);
Node accumulate(Node::Type op, Node& acc, Node& rhs);
Node eval(Node& expr, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry);
Node accumulate(Node::Type op, Node& acc, Node& rhs, vector<vector<Node>*>& registry);
double operate(Node::Type op, double lhs, double rhs);
Node apply_mixin(Node& mixin, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env);
Node apply_function(const Function& f, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env);
Node apply_mixin(Node& mixin, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry);
Node apply_function(const Function& f, const Node& args, Environment& env, map<pair<string, size_t>, Function>& f_env, vector<vector<Node>*>& registry);
}
\ No newline at end of file
......@@ -25,21 +25,21 @@ namespace Sass {
Function_Descriptor rgb_descriptor =
{ "rgb", "$red", "$green", "$blue", 0 };
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node r(bindings[parameters[0]]);
Node g(bindings[parameters[1]]);
Node b(bindings[parameters[2]]);
if (!(r.type == Node::number && g.type == Node::number && b.type == Node::number)) {
eval_error("arguments for rgb must be numbers", r.line_number, r.file_name);
}
Node color(Node::numeric_color, 0, 4);
Node color(Node::numeric_color, registry, 0, 4);
color << r << g << b << Node(0, 1.0);
return color;
}
Function_Descriptor rgba_4_descriptor =
{ "rgba", "$red", "$green", "$blue", "$alpha", 0 };
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node r(bindings[parameters[0]]);
Node g(bindings[parameters[1]]);
Node b(bindings[parameters[2]]);
......@@ -47,22 +47,22 @@ namespace Sass {
if (!(r.type == Node::number && g.type == Node::number && b.type == Node::number && a.type == Node::number)) {
eval_error("arguments for rgba must be numbers", r.line_number, r.file_name);
}
Node color(Node::numeric_color, 0, 4);
Node color(Node::numeric_color, registry, 0, 4);
color << r << g << b << a;
return color;
}
Function_Descriptor rgba_2_descriptor =
{ "rgba", "$color", "$alpha", 0 };
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node color(bindings[parameters[0]].clone());
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node color(bindings[parameters[0]].clone(registry));
color[3] = bindings[parameters[1]];
return color;
}
Function_Descriptor red_descriptor =
{ "red", "$color", 0 };
Node red(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node color(bindings[parameters[0]]);
if (color.type != Node::numeric_color) eval_error("argument to red must be a color", color.line_number, color.file_name);
return color[0];
......@@ -70,7 +70,7 @@ namespace Sass {
Function_Descriptor green_descriptor =
{ "green", "$color", 0 };
Node green(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node color(bindings[parameters[0]]);
if (color.type != Node::numeric_color) eval_error("argument to green must be a color", color.line_number, color.file_name);
return color[1];
......@@ -78,13 +78,13 @@ namespace Sass {
Function_Descriptor blue_descriptor =
{ "blue", "$color", 0 };
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node color(bindings[parameters[0]]);
if (color.type != Node::numeric_color) eval_error("argument to blue must be a color", color.line_number, color.file_name);
return color[2];
}
Node mix_impl(Node color1, Node color2, double weight = 50) {
Node mix_impl(Node color1, Node color2, double weight, vector<vector<Node>*>& registry) {
if (!(color1.type == Node::numeric_color && color2.type == Node::numeric_color)) {
eval_error("first two arguments to mix must be colors", color1.line_number, color1.file_name);
}
......@@ -95,7 +95,7 @@ namespace Sass {
double w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0;
double w2 = 1 - w1;
Node mixed(Node::numeric_color, color1.line_number, 4);
Node mixed(Node::numeric_color, registry, color1.line_number, 4);
for (int i = 0; i < 3; ++i) {
mixed << Node(mixed.line_number, w1*color1[i].content.numeric_value +
w2*color2[i].content.numeric_value);
......@@ -107,20 +107,21 @@ namespace Sass {
Function_Descriptor mix_2_descriptor =
{ "mix", "$color1", "$color2", 0 };
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings) {
return mix_impl(bindings[parameters[0]], bindings[parameters[1]]);
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
return mix_impl(bindings[parameters[0]], bindings[parameters[1]], 50, registry);
}
Function_Descriptor mix_3_descriptor =
{ "mix", "$color1", "$color2", "$weight", 0 };
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node percentage(bindings[parameters[2]]);
if (!(percentage.type == Node::number || percentage.type == Node::numeric_percentage || percentage.type == Node::numeric_dimension)) {
eval_error("third argument to mix must be numeric", percentage.line_number, percentage.file_name);
}
return mix_impl(bindings[parameters[0]],
bindings[parameters[1]],
percentage.numeric_value());
percentage.numeric_value(),
registry);
}
// HSL Functions ///////////////////////////////////////////////////////
......@@ -134,7 +135,7 @@ namespace Sass {
return m1;
}
Node hsla_impl(double h, double s, double l, double a = 1) {
Node hsla_impl(double h, double s, double l, double a, vector<vector<Node>*>& registry) {
h = static_cast<double>(((static_cast<int>(h) % 360) + 360) % 360) / 360.0;
s = s / 100.0;
l = l / 100.0;
......@@ -147,12 +148,12 @@ namespace Sass {
double g = h_to_rgb(m1, m2, h) * 255.0;
double b = h_to_rgb(m1, m2, h-1.0/3.0) * 255.0;
return Node(0, r, g, b, a);
return Node(registry, 0, r, g, b, a);
}
Function_Descriptor hsla_descriptor =
{ "hsla", "$hue", "$saturation", "$lightness", "$alpha", 0 };
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
if (!(bindings[parameters[0]].is_numeric() &&
bindings[parameters[1]].is_numeric() &&
bindings[parameters[2]].is_numeric() &&
......@@ -163,14 +164,14 @@ namespace Sass {
double s = bindings[parameters[1]].numeric_value();
double l = bindings[parameters[2]].numeric_value();
double a = bindings[parameters[3]].numeric_value();
Node color(hsla_impl(h, s, l, a));
Node color(hsla_impl(h, s, l, a, registry));
color.line_number = bindings[parameters[0]].line_number;
return color;
}
Function_Descriptor hsl_descriptor =
{ "hsl", "$hue", "$saturation", "$lightness", 0 };
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
if (!(bindings[parameters[0]].is_numeric() &&
bindings[parameters[1]].is_numeric() &&
bindings[parameters[2]].is_numeric())) {
......@@ -179,17 +180,17 @@ namespace Sass {
double h = bindings[parameters[0]].numeric_value();
double s = bindings[parameters[1]].numeric_value();
double l = bindings[parameters[2]].numeric_value();
Node color(hsla_impl(h, s, l));
Node color(hsla_impl(h, s, l, 1, registry));
color.line_number = bindings[parameters[0]].line_number;
return color;
}
Function_Descriptor invert_descriptor =
{ "invert", "$color", 0 };
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node orig(bindings[parameters[0]]);
if (orig.type != Node::numeric_color) eval_error("argument to invert must be a color", orig.line_number, orig.file_name);
return Node(orig.line_number,
return Node(registry, orig.line_number,
255 - orig[0].content.numeric_value,
255 - orig[1].content.numeric_value,
255 - orig[2].content.numeric_value,
......@@ -202,7 +203,7 @@ namespace Sass {
{ "alpha", "$color", 0 };
Function_Descriptor opacity_descriptor =
{ "opacity", "$color", 0 };
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node color(bindings[parameters[0]]);
if (color.type != Node::numeric_color) eval_error("argument to alpha must be a color", color.line_number, color.file_name);
return color[3];
......@@ -212,8 +213,8 @@ namespace Sass {
{ "opacify", "$color", "$amount", 0 };
Function_Descriptor fade_in_descriptor =
{ "fade_in", "$color", "$amount", 0 };
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node cpy(bindings[parameters[0]].clone());
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node cpy(bindings[parameters[0]].clone(registry));
if (cpy.type != Node::numeric_color || !bindings[parameters[1]].is_numeric()) {
eval_error("arguments to opacify/fade_in must be a color and a numeric value", cpy.line_number, cpy.file_name);
}
......@@ -229,8 +230,8 @@ namespace Sass {
{ "transparentize", "$color", "$amount", 0 };
Function_Descriptor fade_out_descriptor =
{ "fade_out", "$color", "$amount", 0 };
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node cpy(bindings[parameters[0]].clone());
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node cpy(bindings[parameters[0]].clone(registry));
if (cpy.type != Node::numeric_color || !bindings[parameters[1]].is_numeric()) {
eval_error("arguments to transparentize/fade_out must be a color and a numeric value", cpy.line_number, cpy.file_name);
}
......@@ -246,8 +247,8 @@ namespace Sass {
Function_Descriptor unquote_descriptor =
{ "unquote", "$string", 0 };
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node cpy(bindings[parameters[0]].clone());
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node cpy(bindings[parameters[0]].clone(registry));
// if (cpy.type != Node::string_constant /* && cpy.type != Node::concatenation */) {
// eval_error("argument to unquote must be a string", cpy.line_number, cpy.file_name);
// }
......@@ -257,8 +258,8 @@ namespace Sass {
Function_Descriptor quote_descriptor =
{ "quote", "$string", 0 };
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node cpy(bindings[parameters[0]].clone());
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node cpy(bindings[parameters[0]].clone(registry));
if (cpy.type != Node::string_constant && cpy.type != Node::identifier) {
eval_error("argument to quote must be a string or identifier", cpy.line_number, cpy.file_name);
}
......@@ -271,8 +272,8 @@ namespace Sass {
Function_Descriptor percentage_descriptor =
{ "percentage", "$value", 0 };
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node cpy(bindings[parameters[0]].clone());
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node cpy(bindings[parameters[0]].clone(registry));
// TO DO: make sure it's not already a percentage
if (cpy.type != Node::number) eval_error("argument to percentage must be a unitless number", cpy.line_number, cpy.file_name);
cpy.content.numeric_value = cpy.content.numeric_value * 100;
......@@ -282,8 +283,8 @@ namespace Sass {
Function_Descriptor round_descriptor =
{ "round", "$value", 0 };
Node round(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node cpy(bindings[parameters[0]].clone());
Node round(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node cpy(bindings[parameters[0]].clone(registry));
if (cpy.type == Node::numeric_dimension) {
cpy.content.dimension.numeric_value = std::floor(cpy.content.dimension.numeric_value + 0.5);
}
......@@ -298,8 +299,8 @@ namespace Sass {
Function_Descriptor ceil_descriptor =
{ "ceil", "$value", 0 };
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node cpy(bindings[parameters[0]].clone());
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node cpy(bindings[parameters[0]].clone(registry));
if (cpy.type == Node::numeric_dimension) {
cpy.content.dimension.numeric_value = std::ceil(cpy.content.dimension.numeric_value);
}
......@@ -314,8 +315,8 @@ namespace Sass {
Function_Descriptor floor_descriptor =
{ "floor", "$value", 0 };
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node cpy(bindings[parameters[0]].clone());
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node cpy(bindings[parameters[0]].clone(registry));
if (cpy.type == Node::numeric_dimension) {
cpy.content.dimension.numeric_value = std::floor(cpy.content.dimension.numeric_value);
}
......@@ -330,8 +331,8 @@ namespace Sass {
Function_Descriptor abs_descriptor =
{ "abs", "$value", 0 };
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node cpy(bindings[parameters[0]].clone());
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node cpy(bindings[parameters[0]].clone(registry));
if (cpy.type == Node::numeric_dimension) {
cpy.content.dimension.numeric_value = std::fabs(cpy.content.dimension.numeric_value);
}
......@@ -348,7 +349,7 @@ namespace Sass {
Function_Descriptor length_descriptor =
{ "length", "$list", 0 };
Node length(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node arg(bindings[parameters[0]]);
if (arg.type == Node::space_list || arg.type == Node::comma_list) {
return Node(arg.line_number, arg.size());
......@@ -364,12 +365,12 @@ namespace Sass {
Function_Descriptor nth_descriptor =
{ "nth", "$list", "$n", 0 };
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node l(bindings[parameters[0]]);
// TO DO: check for empty list
if (l.type == Node::nil) eval_error("cannot index into an empty list", l.line_number, l.file_name);
if (l.type != Node::space_list && l.type != Node::comma_list) {
l = Node(Node::space_list, l.line_number, 1) << l;
l = Node(Node::space_list, registry, l.line_number, 1) << l;
}
Node n(bindings[parameters[1]]);
if (n.type != Node::number) eval_error("second argument to nth must be a number", n.line_number, n.file_name);
......@@ -378,25 +379,25 @@ namespace Sass {
}
extern const char separator_kwd[] = "$separator";
Node join_impl(const vector<Token>& parameters, map<Token, Node>& bindings, bool has_sep = false) {
Node join_impl(const vector<Token>& parameters, map<Token, Node>& bindings, bool has_sep, vector<vector<Node>*>& registry) {
// if the args aren't lists, turn them into singleton lists
Node l1(bindings[parameters[0]]);
if (l1.type != Node::space_list && l1.type != Node::comma_list && l1.type != Node::nil) {
l1 = Node(Node::space_list, l1.line_number, 1) << l1;
l1 = Node(Node::space_list, registry, l1.line_number, 1) << l1;
}
Node l2(bindings[parameters[1]]);
if (l2.type != Node::space_list && l2.type != Node::comma_list && l2.type != Node::nil) {
l2 = Node(Node::space_list, l2.line_number, 1) << l2;
l2 = Node(Node::space_list, registry, l2.line_number, 1) << l2;
}
// nil and nil is nil
if (l1.type == Node::nil && l2.type == Node::nil) return Node(Node::nil, l1.line_number);
if (l1.type == Node::nil && l2.type == Node::nil) return Node(Node::nil, registry, l1.line_number);
// figure out the combined size in advance
size_t size = 0;
if (l1.type != Node::nil) size += l1.size();
if (l2.type != Node::nil) size += l2.size();
// accumulate the result
Node lr(l1.type, l1.line_number, size);
Node lr(l1.type, registry, l1.line_number, size);
if (has_sep) {
string sep(bindings[parameters[2]].content.token.unquote());
if (sep == "comma") lr.type = Node::comma_list;
......@@ -416,14 +417,14 @@ namespace Sass {
Function_Descriptor join_2_descriptor =
{ "join", "$list1", "$list2", 0 };
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings) {
return join_impl(parameters, bindings);
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
return join_impl(parameters, bindings, false, registry);
}
Function_Descriptor join_3_descriptor =
{ "join", "$list1", "$list2", "$separator", 0 };
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings) {
return join_impl(parameters, bindings, true);
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
return join_impl(parameters, bindings, true, registry);
}
// Introspection Functions /////////////////////////////////////////////
......@@ -436,7 +437,7 @@ namespace Sass {
Function_Descriptor type_of_descriptor =
{ "type-of", "$value", 0 };
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node val(bindings[parameters[0]]);
Node type(Node::string_constant, val.line_number, Token::make());
type.unquoted = true;
......@@ -472,7 +473,7 @@ namespace Sass {
Function_Descriptor unit_descriptor =
{ "unit", "$number", 0 };
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node val(bindings[parameters[0]]);
Node u(Node::string_constant, val.line_number, Token::make());
switch (val.type)
......@@ -498,7 +499,7 @@ namespace Sass {
Function_Descriptor unitless_descriptor =
{ "unitless", "$number", 0 };
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node val(bindings[parameters[0]]);
Node result(Node::string_constant, val.line_number, Token::make());
result.unquoted = true;
......@@ -526,7 +527,7 @@ namespace Sass {
Function_Descriptor comparable_descriptor =
{ "comparable", "$number_1", "$number_2", 0 };
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node n1(bindings[parameters[0]]);
Node n2(bindings[parameters[1]]);
Node::Type t1 = n1.type;
......@@ -577,7 +578,7 @@ namespace Sass {
// Boolean Functions ///////////////////////////////////////////////////
Function_Descriptor not_descriptor =
{ "not", "value", 0 };
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings) {
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry) {
Node val(bindings[parameters[0]]);
if (val.type == Node::boolean && val.content.boolean_value == false) {
Node T(Node::boolean);
......
......@@ -8,7 +8,7 @@
namespace Sass {
using std::map;
typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&);
typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, vector<vector<Node>*>& registry);
typedef const char* str;
typedef str Function_Descriptor[];
......@@ -37,8 +37,8 @@ namespace Sass {
}
}
Node operator()(map<Token, Node>& bindings) const
{ return implementation(parameters, bindings); }
Node operator()(map<Token, Node>& bindings, vector<vector<Node>*>& registry) const
{ return implementation(parameters, bindings, registry); }
};
......@@ -47,111 +47,111 @@ namespace Sass {
// RGB Functions ///////////////////////////////////////////////////////
extern Function_Descriptor rgb_descriptor;
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings);
Node rgb(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor rgba_4_descriptor;
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings);
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor rgba_2_descriptor;
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings);
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor red_descriptor;
Node red(const vector<Token>& parameters, map<Token, Node>& bindings);
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor green_descriptor;
Node green(const vector<Token>& parameters, map<Token, Node>& bindings);
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor blue_descriptor;
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings);
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor mix_2_descriptor;
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings);
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor mix_3_descriptor;
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings);
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// HSL Functions ///////////////////////////////////////////////////////
extern Function_Descriptor hsla_descriptor;
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings);
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor hsl_descriptor;
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings);
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor invert_descriptor;
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings);
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// Opacity Functions ///////////////////////////////////////////////////
extern Function_Descriptor alpha_descriptor;
extern Function_Descriptor opacity_descriptor;
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings);
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor opacify_descriptor;
extern Function_Descriptor fade_in_descriptor;
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings);
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor transparentize_descriptor;
extern Function_Descriptor fade_out_descriptor;
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings);
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// String Functions ////////////////////////////////////////////////////
extern Function_Descriptor unquote_descriptor;
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings);
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor quote_descriptor;
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings);
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// Number Functions ////////////////////////////////////////////////////
extern Function_Descriptor percentage_descriptor;
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings);
Node percentage(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor round_descriptor;
Node round(const vector<Token>& parameters, map<Token, Node>& bindings);
Node round(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor ceil_descriptor;
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings);
Node ceil(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor floor_descriptor;
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings);
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor abs_descriptor;
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings);
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// List Functions //////////////////////////////////////////////////////
extern Function_Descriptor length_descriptor;
Node length(const vector<Token>& parameters, map<Token, Node>& bindings);
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor nth_descriptor;
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings);
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor join_2_descriptor;
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings);
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor join_3_descriptor;
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings);
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// Introspection Functions /////////////////////////////////////////////
extern Function_Descriptor type_of_descriptor;
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings);
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor unit_descriptor;
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings);
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor unitless_descriptor;
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings);
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
extern Function_Descriptor comparable_descriptor;
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings);
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
// Boolean Functions ///////////////////////////////////////////////////
extern Function_Descriptor not_descriptor;
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings);
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, vector<vector<Node>*>& registry);
}
......
......@@ -23,7 +23,7 @@ namespace Sass {
++allocations;
n.content.children->reserve(size());
for (int i = 0; i < size(); ++i) {
n << at(i).clone();
n << at(i).clone(registry);
}
registry.push_back(n.content.children);
}
......
......@@ -190,7 +190,7 @@ namespace Sass {
void emit_nested_css(stringstream& buf, size_t depth);
void emit_expanded_css(stringstream& buf, const string& prefix);
Node clone() const;
Node clone(vector<vector<Node>*>& registry) const;
void flatten();
Node()
......
......@@ -37,10 +37,21 @@ extern "C" {
static char* process_document(Sass::Document& doc, int style)
{
using namespace Sass;
doc.parse_scss();
eval(doc.root, doc.context.global_env, doc.context.function_env);
cerr << "PARSED" << endl;
eval(doc.root, doc.context.global_env, doc.context.function_env, doc.context.registry);
cerr << "EVALUATED" << endl;
string output(doc.emit_css(static_cast<Document::CSS_Style>(style)));
cerr << "EMITTED" << endl;
cerr << "Allocations:\t" << Node::allocations << endl;
cerr << "Registry size:\t" << doc.context.registry.size() << endl;
int i;
for (i = 0; i < doc.context.registry.size(); ++i) {
delete doc.context.registry[i];
}
cerr << "Deallocations:\t" << i << endl;
char* c_output = (char*) malloc(output.size() + 1);
strcpy(c_output, output.c_str());
......@@ -87,6 +98,8 @@ extern "C" {
try {
Context cpp_ctx(c_ctx->options.include_paths);
Document doc(c_ctx->input_path, 0, cpp_ctx);
cerr << "MADE A DOC AND CONTEXT OBJ" << endl;
cerr << "REGISTRY: " << doc.context.registry.size() << endl;
c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
c_ctx->error_message = 0;
c_ctx->error_status = 0;
......
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