-
Notifications
You must be signed in to change notification settings - Fork 463
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move list functions to own compile unit
- Loading branch information
Showing
8 changed files
with
329 additions
and
292 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
#include "listize.hpp" | ||
#include "operators.hpp" | ||
#include "fn_utils.hpp" | ||
#include "fn_lists.hpp" | ||
|
||
namespace Sass { | ||
|
||
namespace Functions { | ||
|
||
///////////////// | ||
// LIST FUNCTIONS | ||
///////////////// | ||
|
||
Signature keywords_sig = "keywords($args)"; | ||
BUILT_IN(keywords) | ||
{ | ||
List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List)); // copy | ||
Map_Obj result = SASS_MEMORY_NEW(Map, pstate, 1); | ||
for (size_t i = arglist->size(), L = arglist->length(); i < L; ++i) { | ||
Expression_Obj obj = arglist->at(i); | ||
Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX | ||
std::string name = std::string(arg->name()); | ||
name = name.erase(0, 1); // sanitize name (remove dollar sign) | ||
*result << std::make_pair(SASS_MEMORY_NEW(String_Quoted, | ||
pstate, name), | ||
arg->value()); | ||
} | ||
return result.detach(); | ||
} | ||
|
||
Signature length_sig = "length($list)"; | ||
BUILT_IN(length) | ||
{ | ||
if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) { | ||
return SASS_MEMORY_NEW(Number, pstate, (double)sl->length()); | ||
} | ||
Expression_Ptr v = ARG("$list", Expression); | ||
if (v->concrete_type() == Expression::MAP) { | ||
Map_Ptr map = Cast<Map>(env["$list"]); | ||
return SASS_MEMORY_NEW(Number, pstate, (double)(map ? map->length() : 1)); | ||
} | ||
if (v->concrete_type() == Expression::SELECTOR) { | ||
if (Compound_Selector_Ptr h = Cast<Compound_Selector>(v)) { | ||
return SASS_MEMORY_NEW(Number, pstate, (double)h->length()); | ||
} else if (Selector_List_Ptr ls = Cast<Selector_List>(v)) { | ||
return SASS_MEMORY_NEW(Number, pstate, (double)ls->length()); | ||
} else { | ||
return SASS_MEMORY_NEW(Number, pstate, 1); | ||
} | ||
} | ||
|
||
List_Ptr list = Cast<List>(env["$list"]); | ||
return SASS_MEMORY_NEW(Number, | ||
pstate, | ||
(double)(list ? list->size() : 1)); | ||
} | ||
|
||
Signature nth_sig = "nth($list, $n)"; | ||
BUILT_IN(nth) | ||
{ | ||
double nr = ARGVAL("$n"); | ||
Map_Ptr m = Cast<Map>(env["$list"]); | ||
if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) { | ||
size_t len = m ? m->length() : sl->length(); | ||
bool empty = m ? m->empty() : sl->empty(); | ||
if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces); | ||
double index = std::floor(nr < 0 ? len + nr : nr - 1); | ||
if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces); | ||
// return (*sl)[static_cast<int>(index)]; | ||
Listize listize; | ||
return Cast<Value>((*sl)[static_cast<int>(index)]->perform(&listize)); | ||
} | ||
List_Obj l = Cast<List>(env["$list"]); | ||
if (nr == 0) error("argument `$n` of `" + std::string(sig) + "` must be non-zero", pstate, traces); | ||
// if the argument isn't a list, then wrap it in a singleton list | ||
if (!m && !l) { | ||
l = SASS_MEMORY_NEW(List, pstate, 1); | ||
l->append(ARG("$list", Expression)); | ||
} | ||
size_t len = m ? m->length() : l->length(); | ||
bool empty = m ? m->empty() : l->empty(); | ||
if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces); | ||
double index = std::floor(nr < 0 ? len + nr : nr - 1); | ||
if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces); | ||
|
||
if (m) { | ||
l = SASS_MEMORY_NEW(List, pstate, 1); | ||
l->append(m->keys()[static_cast<unsigned int>(index)]); | ||
l->append(m->at(m->keys()[static_cast<unsigned int>(index)])); | ||
return l.detach(); | ||
} | ||
else { | ||
Value_Obj rv = l->value_at_index(static_cast<int>(index)); | ||
rv->set_delayed(false); | ||
return rv.detach(); | ||
} | ||
} | ||
|
||
Signature set_nth_sig = "set-nth($list, $n, $value)"; | ||
BUILT_IN(set_nth) | ||
{ | ||
Map_Obj m = Cast<Map>(env["$list"]); | ||
List_Obj l = Cast<List>(env["$list"]); | ||
Number_Obj n = ARG("$n", Number); | ||
Expression_Obj v = ARG("$value", Expression); | ||
if (!l) { | ||
l = SASS_MEMORY_NEW(List, pstate, 1); | ||
l->append(ARG("$list", Expression)); | ||
} | ||
if (m) { | ||
l = m->to_list(pstate); | ||
} | ||
if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces); | ||
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, traces); | ||
List_Ptr result = SASS_MEMORY_NEW(List, pstate, l->length(), l->separator(), false, l->is_bracketed()); | ||
for (size_t i = 0, L = l->length(); i < L; ++i) { | ||
result->append(((i == index) ? v : (*l)[i])); | ||
} | ||
return result; | ||
} | ||
|
||
Signature index_sig = "index($list, $value)"; | ||
BUILT_IN(index) | ||
{ | ||
Map_Obj m = Cast<Map>(env["$list"]); | ||
List_Obj l = Cast<List>(env["$list"]); | ||
Expression_Obj v = ARG("$value", Expression); | ||
if (!l) { | ||
l = SASS_MEMORY_NEW(List, pstate, 1); | ||
l->append(ARG("$list", Expression)); | ||
} | ||
if (m) { | ||
l = m->to_list(pstate); | ||
} | ||
for (size_t i = 0, L = l->length(); i < L; ++i) { | ||
if (Operators::eq(l->value_at_index(i), v)) return SASS_MEMORY_NEW(Number, pstate, (double)(i+1)); | ||
} | ||
return SASS_MEMORY_NEW(Null, pstate); | ||
} | ||
|
||
Signature join_sig = "join($list1, $list2, $separator: auto, $bracketed: auto)"; | ||
BUILT_IN(join) | ||
{ | ||
Map_Obj m1 = Cast<Map>(env["$list1"]); | ||
Map_Obj m2 = Cast<Map>(env["$list2"]); | ||
List_Obj l1 = Cast<List>(env["$list1"]); | ||
List_Obj l2 = Cast<List>(env["$list2"]); | ||
String_Constant_Obj sep = ARG("$separator", String_Constant); | ||
enum Sass_Separator sep_val = (l1 ? l1->separator() : SASS_SPACE); | ||
Value* bracketed = ARG("$bracketed", Value); | ||
bool is_bracketed = (l1 ? l1->is_bracketed() : false); | ||
if (!l1) { | ||
l1 = SASS_MEMORY_NEW(List, pstate, 1); | ||
l1->append(ARG("$list1", Expression)); | ||
sep_val = (l2 ? l2->separator() : SASS_SPACE); | ||
is_bracketed = (l2 ? l2->is_bracketed() : false); | ||
} | ||
if (!l2) { | ||
l2 = SASS_MEMORY_NEW(List, pstate, 1); | ||
l2->append(ARG("$list2", Expression)); | ||
} | ||
if (m1) { | ||
l1 = m1->to_list(pstate); | ||
sep_val = SASS_COMMA; | ||
} | ||
if (m2) { | ||
l2 = m2->to_list(pstate); | ||
} | ||
size_t len = l1->length() + l2->length(); | ||
std::string sep_str = unquote(sep->value()); | ||
if (sep_str == "space") sep_val = SASS_SPACE; | ||
else if (sep_str == "comma") sep_val = SASS_COMMA; | ||
else if (sep_str != "auto") error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces); | ||
String_Constant_Obj bracketed_as_str = Cast<String_Constant>(bracketed); | ||
bool bracketed_is_auto = bracketed_as_str && unquote(bracketed_as_str->value()) == "auto"; | ||
if (!bracketed_is_auto) { | ||
is_bracketed = !bracketed->is_false(); | ||
} | ||
List_Obj result = SASS_MEMORY_NEW(List, pstate, len, sep_val, false, is_bracketed); | ||
result->concat(l1); | ||
result->concat(l2); | ||
return result.detach(); | ||
} | ||
|
||
Signature append_sig = "append($list, $val, $separator: auto)"; | ||
BUILT_IN(append) | ||
{ | ||
Map_Obj m = Cast<Map>(env["$list"]); | ||
List_Obj l = Cast<List>(env["$list"]); | ||
Expression_Obj v = ARG("$val", Expression); | ||
if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) { | ||
Listize listize; | ||
l = Cast<List>(sl->perform(&listize)); | ||
} | ||
String_Constant_Obj sep = ARG("$separator", String_Constant); | ||
if (!l) { | ||
l = SASS_MEMORY_NEW(List, pstate, 1); | ||
l->append(ARG("$list", Expression)); | ||
} | ||
if (m) { | ||
l = m->to_list(pstate); | ||
} | ||
List_Ptr result = SASS_MEMORY_COPY(l); | ||
std::string sep_str(unquote(sep->value())); | ||
if (sep_str != "auto") { // check default first | ||
if (sep_str == "space") result->separator(SASS_SPACE); | ||
else if (sep_str == "comma") result->separator(SASS_COMMA); | ||
else error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces); | ||
} | ||
if (l->is_arglist()) { | ||
result->append(SASS_MEMORY_NEW(Argument, | ||
v->pstate(), | ||
v, | ||
"", | ||
false, | ||
false)); | ||
|
||
} else { | ||
result->append(v); | ||
} | ||
return result; | ||
} | ||
|
||
Signature zip_sig = "zip($lists...)"; | ||
BUILT_IN(zip) | ||
{ | ||
List_Obj arglist = SASS_MEMORY_COPY(ARG("$lists", List)); | ||
size_t shortest = 0; | ||
for (size_t i = 0, L = arglist->length(); i < L; ++i) { | ||
List_Obj ith = Cast<List>(arglist->value_at_index(i)); | ||
Map_Obj mith = Cast<Map>(arglist->value_at_index(i)); | ||
if (!ith) { | ||
if (mith) { | ||
ith = mith->to_list(pstate); | ||
} else { | ||
ith = SASS_MEMORY_NEW(List, pstate, 1); | ||
ith->append(arglist->value_at_index(i)); | ||
} | ||
if (arglist->is_arglist()) { | ||
Argument_Obj arg = (Argument_Ptr)(arglist->at(i).ptr()); // XXX | ||
arg->value(ith); | ||
} else { | ||
(*arglist)[i] = ith; | ||
} | ||
} | ||
shortest = (i ? std::min(shortest, ith->length()) : ith->length()); | ||
} | ||
List_Ptr zippers = SASS_MEMORY_NEW(List, pstate, shortest, SASS_COMMA); | ||
size_t L = arglist->length(); | ||
for (size_t i = 0; i < shortest; ++i) { | ||
List_Ptr zipper = SASS_MEMORY_NEW(List, pstate, L); | ||
for (size_t j = 0; j < L; ++j) { | ||
zipper->append(Cast<List>(arglist->value_at_index(j))->at(i)); | ||
} | ||
zippers->append(zipper); | ||
} | ||
return zippers; | ||
} | ||
|
||
Signature list_separator_sig = "list_separator($list)"; | ||
BUILT_IN(list_separator) | ||
{ | ||
List_Obj l = Cast<List>(env["$list"]); | ||
if (!l) { | ||
l = SASS_MEMORY_NEW(List, pstate, 1); | ||
l->append(ARG("$list", Expression)); | ||
} | ||
return SASS_MEMORY_NEW(String_Quoted, | ||
pstate, | ||
l->separator() == SASS_COMMA ? "comma" : "space"); | ||
} | ||
|
||
Signature is_bracketed_sig = "is-bracketed($list)"; | ||
BUILT_IN(is_bracketed) | ||
{ | ||
Value_Obj value = ARG("$list", Value); | ||
List_Obj list = Cast<List>(value); | ||
return SASS_MEMORY_NEW(Boolean, pstate, list && list->is_bracketed()); | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#ifndef SASS_FN_LISTS_H | ||
#define SASS_FN_LISTS_H | ||
|
||
#include "fn_utils.hpp" | ||
|
||
namespace Sass { | ||
|
||
namespace Functions { | ||
|
||
extern Signature length_sig; | ||
extern Signature nth_sig; | ||
extern Signature index_sig; | ||
extern Signature join_sig; | ||
extern Signature append_sig; | ||
extern Signature zip_sig; | ||
extern Signature list_separator_sig; | ||
extern Signature is_bracketed_sig; | ||
extern Signature keywords_sig; | ||
|
||
BUILT_IN(length); | ||
BUILT_IN(nth); | ||
BUILT_IN(index); | ||
BUILT_IN(join); | ||
BUILT_IN(append); | ||
BUILT_IN(zip); | ||
BUILT_IN(list_separator); | ||
BUILT_IN(is_bracketed); | ||
BUILT_IN(keywords); | ||
|
||
} | ||
|
||
} | ||
|
||
#endif |
Oops, something went wrong.