1+ #include " listize.hpp"
2+ #include " operators.hpp"
3+ #include " fn_utils.hpp"
4+ #include " fn_lists.hpp"
5+
6+ namespace Sass {
7+
8+ namespace Functions {
9+
10+ // ///////////////
11+ // LIST FUNCTIONS
12+ // ///////////////
13+
14+ Signature keywords_sig = " keywords($args)" ;
15+ BUILT_IN (keywords)
16+ {
17+ List_Obj arglist = SASS_MEMORY_COPY (ARG (" $args" , List)); // copy
18+ Map_Obj result = SASS_MEMORY_NEW (Map, pstate, 1 );
19+ for (size_t i = arglist->size (), L = arglist->length (); i < L; ++i) {
20+ Expression_Obj obj = arglist->at (i);
21+ Argument_Obj arg = (Argument_Ptr) obj.ptr (); // XXX
22+ std::string name = std::string (arg->name ());
23+ name = name.erase (0 , 1 ); // sanitize name (remove dollar sign)
24+ *result << std::make_pair (SASS_MEMORY_NEW (String_Quoted,
25+ pstate, name),
26+ arg->value ());
27+ }
28+ return result.detach ();
29+ }
30+
31+ Signature length_sig = " length($list)" ;
32+ BUILT_IN (length)
33+ {
34+ if (Selector_List_Ptr sl = Cast<Selector_List>(env[" $list" ])) {
35+ return SASS_MEMORY_NEW (Number, pstate, (double )sl->length ());
36+ }
37+ Expression_Ptr v = ARG (" $list" , Expression);
38+ if (v->concrete_type () == Expression::MAP) {
39+ Map_Ptr map = Cast<Map>(env[" $list" ]);
40+ return SASS_MEMORY_NEW (Number, pstate, (double )(map ? map->length () : 1 ));
41+ }
42+ if (v->concrete_type () == Expression::SELECTOR) {
43+ if (Compound_Selector_Ptr h = Cast<Compound_Selector>(v)) {
44+ return SASS_MEMORY_NEW (Number, pstate, (double )h->length ());
45+ } else if (Selector_List_Ptr ls = Cast<Selector_List>(v)) {
46+ return SASS_MEMORY_NEW (Number, pstate, (double )ls->length ());
47+ } else {
48+ return SASS_MEMORY_NEW (Number, pstate, 1 );
49+ }
50+ }
51+
52+ List_Ptr list = Cast<List>(env[" $list" ]);
53+ return SASS_MEMORY_NEW (Number,
54+ pstate,
55+ (double )(list ? list->size () : 1 ));
56+ }
57+
58+ Signature nth_sig = " nth($list, $n)" ;
59+ BUILT_IN (nth)
60+ {
61+ double nr = ARGVAL (" $n" );
62+ Map_Ptr m = Cast<Map>(env[" $list" ]);
63+ if (Selector_List_Ptr sl = Cast<Selector_List>(env[" $list" ])) {
64+ size_t len = m ? m->length () : sl->length ();
65+ bool empty = m ? m->empty () : sl->empty ();
66+ if (empty) error (" argument `$list` of `" + std::string (sig) + " ` must not be empty" , pstate, traces);
67+ double index = std::floor (nr < 0 ? len + nr : nr - 1 );
68+ if (index < 0 || index > len - 1 ) error (" index out of bounds for `" + std::string (sig) + " `" , pstate, traces);
69+ // return (*sl)[static_cast<int>(index)];
70+ Listize listize;
71+ return Cast<Value>((*sl)[static_cast <int >(index)]->perform (&listize));
72+ }
73+ List_Obj l = Cast<List>(env[" $list" ]);
74+ if (nr == 0 ) error (" argument `$n` of `" + std::string (sig) + " ` must be non-zero" , pstate, traces);
75+ // if the argument isn't a list, then wrap it in a singleton list
76+ if (!m && !l) {
77+ l = SASS_MEMORY_NEW (List, pstate, 1 );
78+ l->append (ARG (" $list" , Expression));
79+ }
80+ size_t len = m ? m->length () : l->length ();
81+ bool empty = m ? m->empty () : l->empty ();
82+ if (empty) error (" argument `$list` of `" + std::string (sig) + " ` must not be empty" , pstate, traces);
83+ double index = std::floor (nr < 0 ? len + nr : nr - 1 );
84+ if (index < 0 || index > len - 1 ) error (" index out of bounds for `" + std::string (sig) + " `" , pstate, traces);
85+
86+ if (m) {
87+ l = SASS_MEMORY_NEW (List, pstate, 1 );
88+ l->append (m->keys ()[static_cast <unsigned int >(index)]);
89+ l->append (m->at (m->keys ()[static_cast <unsigned int >(index)]));
90+ return l.detach ();
91+ }
92+ else {
93+ Value_Obj rv = l->value_at_index (static_cast <int >(index));
94+ rv->set_delayed (false );
95+ return rv.detach ();
96+ }
97+ }
98+
99+ Signature set_nth_sig = " set-nth($list, $n, $value)" ;
100+ BUILT_IN (set_nth)
101+ {
102+ Map_Obj m = Cast<Map>(env[" $list" ]);
103+ List_Obj l = Cast<List>(env[" $list" ]);
104+ Number_Obj n = ARG (" $n" , Number);
105+ Expression_Obj v = ARG (" $value" , Expression);
106+ if (!l) {
107+ l = SASS_MEMORY_NEW (List, pstate, 1 );
108+ l->append (ARG (" $list" , Expression));
109+ }
110+ if (m) {
111+ l = m->to_list (pstate);
112+ }
113+ if (l->empty ()) error (" argument `$list` of `" + std::string (sig) + " ` must not be empty" , pstate, traces);
114+ double index = std::floor (n->value () < 0 ? l->length () + n->value () : n->value () - 1 );
115+ if (index < 0 || index > l->length () - 1 ) error (" index out of bounds for `" + std::string (sig) + " `" , pstate, traces);
116+ List_Ptr result = SASS_MEMORY_NEW (List, pstate, l->length (), l->separator (), false , l->is_bracketed ());
117+ for (size_t i = 0 , L = l->length (); i < L; ++i) {
118+ result->append (((i == index) ? v : (*l)[i]));
119+ }
120+ return result;
121+ }
122+
123+ Signature index_sig = " index($list, $value)" ;
124+ BUILT_IN (index)
125+ {
126+ Map_Obj m = Cast<Map>(env[" $list" ]);
127+ List_Obj l = Cast<List>(env[" $list" ]);
128+ Expression_Obj v = ARG (" $value" , Expression);
129+ if (!l) {
130+ l = SASS_MEMORY_NEW (List, pstate, 1 );
131+ l->append (ARG (" $list" , Expression));
132+ }
133+ if (m) {
134+ l = m->to_list (pstate);
135+ }
136+ for (size_t i = 0 , L = l->length (); i < L; ++i) {
137+ if (Operators::eq (l->value_at_index (i), v)) return SASS_MEMORY_NEW (Number, pstate, (double )(i+1 ));
138+ }
139+ return SASS_MEMORY_NEW (Null, pstate);
140+ }
141+
142+ Signature join_sig = " join($list1, $list2, $separator: auto, $bracketed: auto)" ;
143+ BUILT_IN (join)
144+ {
145+ Map_Obj m1 = Cast<Map>(env[" $list1" ]);
146+ Map_Obj m2 = Cast<Map>(env[" $list2" ]);
147+ List_Obj l1 = Cast<List>(env[" $list1" ]);
148+ List_Obj l2 = Cast<List>(env[" $list2" ]);
149+ String_Constant_Obj sep = ARG (" $separator" , String_Constant);
150+ enum Sass_Separator sep_val = (l1 ? l1->separator () : SASS_SPACE);
151+ Value* bracketed = ARG (" $bracketed" , Value);
152+ bool is_bracketed = (l1 ? l1->is_bracketed () : false );
153+ if (!l1) {
154+ l1 = SASS_MEMORY_NEW (List, pstate, 1 );
155+ l1->append (ARG (" $list1" , Expression));
156+ sep_val = (l2 ? l2->separator () : SASS_SPACE);
157+ is_bracketed = (l2 ? l2->is_bracketed () : false );
158+ }
159+ if (!l2) {
160+ l2 = SASS_MEMORY_NEW (List, pstate, 1 );
161+ l2->append (ARG (" $list2" , Expression));
162+ }
163+ if (m1) {
164+ l1 = m1->to_list (pstate);
165+ sep_val = SASS_COMMA;
166+ }
167+ if (m2) {
168+ l2 = m2->to_list (pstate);
169+ }
170+ size_t len = l1->length () + l2->length ();
171+ std::string sep_str = unquote (sep->value ());
172+ if (sep_str == " space" ) sep_val = SASS_SPACE;
173+ else if (sep_str == " comma" ) sep_val = SASS_COMMA;
174+ else if (sep_str != " auto" ) error (" argument `$separator` of `" + std::string (sig) + " ` must be `space`, `comma`, or `auto`" , pstate, traces);
175+ String_Constant_Obj bracketed_as_str = Cast<String_Constant>(bracketed);
176+ bool bracketed_is_auto = bracketed_as_str && unquote (bracketed_as_str->value ()) == " auto" ;
177+ if (!bracketed_is_auto) {
178+ is_bracketed = !bracketed->is_false ();
179+ }
180+ List_Obj result = SASS_MEMORY_NEW (List, pstate, len, sep_val, false , is_bracketed);
181+ result->concat (l1);
182+ result->concat (l2);
183+ return result.detach ();
184+ }
185+
186+ Signature append_sig = " append($list, $val, $separator: auto)" ;
187+ BUILT_IN (append)
188+ {
189+ Map_Obj m = Cast<Map>(env[" $list" ]);
190+ List_Obj l = Cast<List>(env[" $list" ]);
191+ Expression_Obj v = ARG (" $val" , Expression);
192+ if (Selector_List_Ptr sl = Cast<Selector_List>(env[" $list" ])) {
193+ Listize listize;
194+ l = Cast<List>(sl->perform (&listize));
195+ }
196+ String_Constant_Obj sep = ARG (" $separator" , String_Constant);
197+ if (!l) {
198+ l = SASS_MEMORY_NEW (List, pstate, 1 );
199+ l->append (ARG (" $list" , Expression));
200+ }
201+ if (m) {
202+ l = m->to_list (pstate);
203+ }
204+ List_Ptr result = SASS_MEMORY_COPY (l);
205+ std::string sep_str (unquote (sep->value ()));
206+ if (sep_str != " auto" ) { // check default first
207+ if (sep_str == " space" ) result->separator (SASS_SPACE);
208+ else if (sep_str == " comma" ) result->separator (SASS_COMMA);
209+ else error (" argument `$separator` of `" + std::string (sig) + " ` must be `space`, `comma`, or `auto`" , pstate, traces);
210+ }
211+ if (l->is_arglist ()) {
212+ result->append (SASS_MEMORY_NEW (Argument,
213+ v->pstate (),
214+ v,
215+ " " ,
216+ false ,
217+ false ));
218+
219+ } else {
220+ result->append (v);
221+ }
222+ return result;
223+ }
224+
225+ Signature zip_sig = " zip($lists...)" ;
226+ BUILT_IN (zip)
227+ {
228+ List_Obj arglist = SASS_MEMORY_COPY (ARG (" $lists" , List));
229+ size_t shortest = 0 ;
230+ for (size_t i = 0 , L = arglist->length (); i < L; ++i) {
231+ List_Obj ith = Cast<List>(arglist->value_at_index (i));
232+ Map_Obj mith = Cast<Map>(arglist->value_at_index (i));
233+ if (!ith) {
234+ if (mith) {
235+ ith = mith->to_list (pstate);
236+ } else {
237+ ith = SASS_MEMORY_NEW (List, pstate, 1 );
238+ ith->append (arglist->value_at_index (i));
239+ }
240+ if (arglist->is_arglist ()) {
241+ Argument_Obj arg = (Argument_Ptr)(arglist->at (i).ptr ()); // XXX
242+ arg->value (ith);
243+ } else {
244+ (*arglist)[i] = ith;
245+ }
246+ }
247+ shortest = (i ? std::min (shortest, ith->length ()) : ith->length ());
248+ }
249+ List_Ptr zippers = SASS_MEMORY_NEW (List, pstate, shortest, SASS_COMMA);
250+ size_t L = arglist->length ();
251+ for (size_t i = 0 ; i < shortest; ++i) {
252+ List_Ptr zipper = SASS_MEMORY_NEW (List, pstate, L);
253+ for (size_t j = 0 ; j < L; ++j) {
254+ zipper->append (Cast<List>(arglist->value_at_index (j))->at (i));
255+ }
256+ zippers->append (zipper);
257+ }
258+ return zippers;
259+ }
260+
261+ Signature list_separator_sig = " list_separator($list)" ;
262+ BUILT_IN (list_separator)
263+ {
264+ List_Obj l = Cast<List>(env[" $list" ]);
265+ if (!l) {
266+ l = SASS_MEMORY_NEW (List, pstate, 1 );
267+ l->append (ARG (" $list" , Expression));
268+ }
269+ return SASS_MEMORY_NEW (String_Quoted,
270+ pstate,
271+ l->separator () == SASS_COMMA ? " comma" : " space" );
272+ }
273+
274+ Signature is_bracketed_sig = " is-bracketed($list)" ;
275+ BUILT_IN (is_bracketed)
276+ {
277+ Value_Obj value = ARG (" $list" , Value);
278+ List_Obj list = Cast<List>(value);
279+ return SASS_MEMORY_NEW (Boolean, pstate, list && list->is_bracketed ());
280+ }
281+
282+ }
283+
284+ }
0 commit comments