Skip to content

Commit

Permalink
Merge pull request #2178 from xzyfer/feat/maps-as-lists
Browse files Browse the repository at this point in the history
Support list functions on maps
  • Loading branch information
xzyfer authored Sep 13, 2016
2 parents be81001 + 081748c commit ba9258a
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
16 changes: 16 additions & 0 deletions src/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2226,4 +2226,20 @@ namespace Sass {
}
}

//////////////////////////////////////////////////////////////////////////////////////////
// Convert map to (key, value) list.
//////////////////////////////////////////////////////////////////////////////////////////
List* Map::to_list(Context& ctx, ParserState& pstate) {
List* ret = SASS_MEMORY_NEW(ctx.mem, List, pstate, length(), SASS_COMMA);

for (auto key : keys()) {
List* l = SASS_MEMORY_NEW(ctx.mem, List, pstate, 2);
*l << key;
*l << at(key);
*ret << l;
}

return ret;
}

}
1 change: 1 addition & 0 deletions src/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,7 @@ namespace Sass {
std::string type() { return "map"; }
static std::string type_name() { return "map"; }
bool is_invisible() const { return empty(); }
List* to_list(Context& ctx, ParserState& pstate);

virtual size_t hash()
{
Expand Down
30 changes: 28 additions & 2 deletions src/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1291,13 +1291,17 @@ namespace Sass {
Signature set_nth_sig = "set-nth($list, $n, $value)";
BUILT_IN(set_nth)
{
Map* m = dynamic_cast<Map*>(env["$list"]);
List* l = dynamic_cast<List*>(env["$list"]);
Number* n = ARG("$n", Number);
Expression* v = ARG("$value", Expression);
if (!l) {
l = SASS_MEMORY_NEW(ctx.mem, List, pstate, 1);
*l << ARG("$list", Expression);
}
if (m) {
l = m->to_list(ctx, pstate);
}
if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate);
double index = std::floor(n->value() < 0 ? l->length() + n->value() : n->value() - 1);
if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate);
Expand All @@ -1311,12 +1315,16 @@ namespace Sass {
Signature index_sig = "index($list, $value)";
BUILT_IN(index)
{
Map* m = dynamic_cast<Map*>(env["$list"]);
List* l = dynamic_cast<List*>(env["$list"]);
Expression* v = ARG("$value", Expression);
if (!l) {
l = SASS_MEMORY_NEW(ctx.mem, List, pstate, 1);
*l << ARG("$list", Expression);
}
if (m) {
l = m->to_list(ctx, pstate);
}
for (size_t i = 0, L = l->length(); i < L; ++i) {
if (Eval::eq(l->value_at_index(i), v)) return SASS_MEMORY_NEW(ctx.mem, Number, pstate, (double)(i+1));
}
Expand All @@ -1326,6 +1334,8 @@ namespace Sass {
Signature join_sig = "join($list1, $list2, $separator: auto)";
BUILT_IN(join)
{
Map* m1 = dynamic_cast<Map*>(env["$list1"]);
Map* m2 = dynamic_cast<Map*>(env["$list2"]);
List* l1 = dynamic_cast<List*>(env["$list1"]);
List* l2 = dynamic_cast<List*>(env["$list2"]);
String_Constant* sep = ARG("$separator", String_Constant);
Expand All @@ -1339,6 +1349,13 @@ namespace Sass {
l2 = SASS_MEMORY_NEW(ctx.mem, List, pstate, 1);
*l2 << ARG("$list2", Expression);
}
if (m1) {
l1 = m1->to_list(ctx, pstate);
sep_val = SASS_COMMA;
}
if (m2) {
l2 = m2->to_list(ctx, pstate);
}
size_t len = l1->length() + l2->length();
std::string sep_str = unquote(sep->value());
if (sep_str == "space") sep_val = SASS_SPACE;
Expand All @@ -1353,6 +1370,7 @@ namespace Sass {
Signature append_sig = "append($list, $val, $separator: auto)";
BUILT_IN(append)
{
Map* m = dynamic_cast<Map*>(env["$list"]);
List* l = dynamic_cast<List*>(env["$list"]);
Expression* v = ARG("$val", Expression);
if (CommaSequence_Selector* sl = dynamic_cast<CommaSequence_Selector*>(env["$list"])) {
Expand All @@ -1364,6 +1382,9 @@ namespace Sass {
l = SASS_MEMORY_NEW(ctx.mem, List, pstate, 1);
*l << ARG("$list", Expression);
}
if (m) {
l = m->to_list(ctx, pstate);
}
List* result = SASS_MEMORY_NEW(ctx.mem, List, pstate, l->length() + 1, l->separator());
std::string sep_str(unquote(sep->value()));
if (sep_str == "space") result->separator(SASS_SPACE);
Expand Down Expand Up @@ -1393,9 +1414,14 @@ namespace Sass {
size_t shortest = 0;
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
List* ith = dynamic_cast<List*>(arglist->value_at_index(i));
Map* mith = dynamic_cast<Map*>(arglist->value_at_index(i));
if (!ith) {
ith = SASS_MEMORY_NEW(ctx.mem, List, pstate, 1);
*ith << arglist->value_at_index(i);
if (mith) {
ith = mith->to_list(ctx, pstate);
} else {
ith = SASS_MEMORY_NEW(ctx.mem, List, pstate, 1);
*ith << arglist->value_at_index(i);
}
if (arglist->is_arglist()) {
((Argument*)(*arglist)[i])->value(ith);
} else {
Expand Down

0 comments on commit ba9258a

Please # to comment.