Text-Sass-XS
view release on metacpan or search on metacpan
libsass/old/eval_apply.cpp view on Meta::CPAN
using std::cerr; using std::endl;
static void throw_eval_error(Backtrace& bt, string message, string path, size_t line)
{
if (!path.empty() && Prelexer::string_constant(path.c_str()))
path = path.substr(1, path.size() - 1);
Backtrace top(&bt, path, line, "");
message += top.to_string();
throw Error(Error::evaluation, path, line, message);
}
// Expansion function for nodes in an expansion context.
void expand(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, Backtrace& bt, bool function_name, const Node content)
{
switch (expr.type())
{
case Node::root: {
for (size_t i = 0, S = expr.size(); i < S; ++i) {
if (i == 19) {
expand(expr[i], prefix, env, f_env, new_Node, ctx, bt, false, content);
}
else {
expand(expr[i], prefix, env, f_env, new_Node, ctx, bt, false, content);
}
}
} break;
case Node::mixin: { // mixin definition
env[expr[0].token()] = expr;
} break;
case Node::function: { // function definition
f_env[expr[0].to_string()] = Function(expr);
} break;
case Node::mixin_call: { // mixin invocation
Token name(expr[0].token());
Node args(expr[1]);
Node this_content = expr.size() == 3 ? expr[2] : Node();
if (!this_content.is_null()) expand(this_content, prefix, env, f_env, new_Node, ctx, bt, false, content);
if (!env.query(name)) throw_eval_error(bt, "mixin " + name.to_string() + " is undefined", expr.path(), expr.line());
Node mixin(env[name]);
Backtrace here(&bt, expr.path(), expr.line(), ", in mixin '" + name.to_string() + "'");
Node expansion(apply_mixin(mixin, args, this_content, prefix, env, f_env, new_Node, ctx, here));
expr.pop_all(); // pop the mixin metadata
expr += expansion; // push the expansion
} break;
case Node::mixin_content: {
if (!content.is_null()) {
expr += new_Node(content);
for (size_t i = 0, S = expr.size(); i < S; ++i) {
re_expand(expr[i], prefix, env, f_env, new_Node, ctx, bt, false, content);
}
}
} break;
case Node::propset: {
// TO DO: perform the property expansion here, rather than in the emitter (also requires the parser to allow interpolants in the property names)
expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx, bt);
expand(expr[1], prefix, env, f_env, new_Node, ctx, bt, false, content);
// Node block(expr[1]);
// for (size_t i = 0, S = block.size(); i < S; ++i) {
// Node stm(block[i]);
// switch (stm.type())
// {
// case Node::propset:
// case Node::mixin_call:
// case Node::if_directive:
// case Node::for_through_directive:
// case Node::for_to_directive:
// case Node::each_directive:
// case Node::while_directive:
// case Node::warning: {
// expand(stm, prefix, env, f_env, new_Node, ctx, bt, false, content);
// } break;
// }
// }
} break;
case Node::ruleset: {
// if the selector contains interpolants, eval it and re-parse
if (!expr[0].is_null() && expr[0].type() == Node::selector_schema) {
Node schema(expr[0]);
string expansion;
for (size_t i = 0, S = schema.size(); i < S; ++i) {
schema[i] = eval(schema[i], prefix, env, f_env, new_Node, ctx, bt);
if (schema[i].type() == Node::string_constant) {
expansion += schema[i].token().unquote();
}
else {
expansion += schema[i].to_string();
}
}
// need to re-parse the selector because its structure may have changed
expansion += " {"; // the parser looks for an lbrace to end a selector
char* expn_src = new char[expansion.size() + 1];
strcpy(expn_src, expansion.c_str());
Document needs_reparsing(Document::make_from_source_chars(ctx, expn_src, schema.path(), true));
needs_reparsing.line = schema.line(); // set the line number to the original node's line
expr[0] = needs_reparsing.parse_selector_group();
}
// Expand the selector with the prefix and save it in expr[2].
expr << expand_selector(expr[0], prefix, new_Node);
expand(expr[1], expr.back(), env, f_env, new_Node, ctx, bt, false, content);
} break;
case Node::media_query: {
Node id(expr[0]);
if( id.is_schema() || id.should_eval()) {
expr[0] = eval(id, prefix, env, f_env, new_Node, ctx, bt);
} else {
expand(expr[0], prefix, env, f_env, new_Node, ctx, bt, false, content);
}
expand(expr[1], prefix, env, f_env, new_Node, ctx, bt, false, content);
expr << prefix;
} break;
case Node::media_expression_group: {
for (size_t i = 0, S = expr.size(); i < S; ++i) {
expand(expr[i], prefix, env, f_env, new_Node, ctx, bt, false, content);
}
} break;
case Node::media_expression: {
( run in 1.580 second using v1.01-cache-2.11-cpan-71847e10f99 )