Skip to content
This repository was archived by the owner on Oct 24, 2025. It is now read-only.

Commit 83f641c

Browse files
committed
Move selector functions to own compile unit
Remove selector signatures
1 parent 8b74ede commit 83f641c

File tree

9 files changed

+286
-441
lines changed

9 files changed

+286
-441
lines changed

Makefile.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ SOURCES = \
1212
constants.cpp \
1313
fn_utils.cpp \
1414
fn_numbers.cpp \
15+
fn_selectors.cpp \
1516
functions.cpp \
1617
color_maps.cpp \
1718
environment.cpp \

src/context.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include "prelexer.hpp"
3131
#include "emitter.hpp"
3232
#include "fn_utils.hpp"
33+
#include "fn_numbers.hpp"
34+
#include "fn_selectors.hpp"
3335

3436
namespace Sass {
3537
using namespace Constants;

src/fn_selectors.cpp

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
#include "parser.hpp"
2+
#include "extend.hpp"
3+
#include "fn_utils.hpp"
4+
#include "fn_selectors.hpp"
5+
6+
namespace Sass {
7+
8+
namespace Functions {
9+
10+
Signature selector_nest_sig = "selector-nest($selectors...)";
11+
BUILT_IN(selector_nest)
12+
{
13+
List_Ptr arglist = ARG("$selectors", List);
14+
15+
// Not enough parameters
16+
if( arglist->length() == 0 )
17+
error("$selectors: At least one selector must be passed for `selector-nest'", pstate, traces);
18+
19+
// Parse args into vector of selectors
20+
SelectorStack parsedSelectors;
21+
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
22+
Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
23+
if (exp->concrete_type() == Expression::NULL_VAL) {
24+
std::stringstream msg;
25+
msg << "$selectors: null is not a valid selector: it must be a string,\n";
26+
msg << "a list of strings, or a list of lists of strings for 'selector-nest'";
27+
error(msg.str(), pstate, traces);
28+
}
29+
if (String_Constant_Obj str = Cast<String_Constant>(exp)) {
30+
str->quote_mark(0);
31+
}
32+
std::string exp_src = exp->to_string(ctx.c_options);
33+
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
34+
parsedSelectors.push_back(sel);
35+
}
36+
37+
// Nothing to do
38+
if( parsedSelectors.empty() ) {
39+
return SASS_MEMORY_NEW(Null, pstate);
40+
}
41+
42+
// Set the first element as the `result`, keep appending to as we go down the parsedSelector vector.
43+
SelectorStack::iterator itr = parsedSelectors.begin();
44+
Selector_List_Obj result = *itr;
45+
++itr;
46+
47+
for(;itr != parsedSelectors.end(); ++itr) {
48+
Selector_List_Obj child = *itr;
49+
std::vector<Complex_Selector_Obj> exploded;
50+
selector_stack.push_back(result);
51+
Selector_List_Obj rv = child->resolve_parent_refs(selector_stack, traces);
52+
selector_stack.pop_back();
53+
for (size_t m = 0, mLen = rv->length(); m < mLen; ++m) {
54+
exploded.push_back((*rv)[m]);
55+
}
56+
result->elements(exploded);
57+
}
58+
59+
Listize listize;
60+
return Cast<Value>(result->perform(&listize));
61+
}
62+
63+
Signature selector_append_sig = "selector-append($selectors...)";
64+
BUILT_IN(selector_append)
65+
{
66+
List_Ptr arglist = ARG("$selectors", List);
67+
68+
// Not enough parameters
69+
if( arglist->length() == 0 )
70+
error("$selectors: At least one selector must be passed for `selector-append'", pstate, traces);
71+
72+
// Parse args into vector of selectors
73+
SelectorStack parsedSelectors;
74+
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
75+
Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
76+
if (exp->concrete_type() == Expression::NULL_VAL) {
77+
std::stringstream msg;
78+
msg << "$selectors: null is not a valid selector: it must be a string,\n";
79+
msg << "a list of strings, or a list of lists of strings for 'selector-append'";
80+
error(msg.str(), pstate, traces);
81+
}
82+
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
83+
str->quote_mark(0);
84+
}
85+
std::string exp_src = exp->to_string();
86+
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
87+
parsedSelectors.push_back(sel);
88+
}
89+
90+
// Nothing to do
91+
if( parsedSelectors.empty() ) {
92+
return SASS_MEMORY_NEW(Null, pstate);
93+
}
94+
95+
// Set the first element as the `result`, keep appending to as we go down the parsedSelector vector.
96+
SelectorStack::iterator itr = parsedSelectors.begin();
97+
Selector_List_Obj result = *itr;
98+
++itr;
99+
100+
for(;itr != parsedSelectors.end(); ++itr) {
101+
Selector_List_Obj child = *itr;
102+
std::vector<Complex_Selector_Obj> newElements;
103+
104+
// For every COMPLEX_SELECTOR in `result`
105+
// For every COMPLEX_SELECTOR in `child`
106+
// let parentSeqClone equal a copy of result->elements[i]
107+
// let childSeq equal child->elements[j]
108+
// Append all of childSeq head elements into parentSeqClone
109+
// Set the innermost tail of parentSeqClone, to childSeq's tail
110+
// Replace result->elements with newElements
111+
for (size_t i = 0, resultLen = result->length(); i < resultLen; ++i) {
112+
for (size_t j = 0, childLen = child->length(); j < childLen; ++j) {
113+
Complex_Selector_Obj parentSeqClone = SASS_MEMORY_CLONE((*result)[i]);
114+
Complex_Selector_Obj childSeq = (*child)[j];
115+
Complex_Selector_Obj base = childSeq->tail();
116+
117+
// Must be a simple sequence
118+
if( childSeq->combinator() != Complex_Selector::Combinator::ANCESTOR_OF ) {
119+
std::string msg("Can't append \"");
120+
msg += childSeq->to_string();
121+
msg += "\" to \"";
122+
msg += parentSeqClone->to_string();
123+
msg += "\" for `selector-append'";
124+
error(msg, pstate, traces);
125+
}
126+
127+
// Cannot be a Universal selector
128+
Element_Selector_Obj pType = Cast<Element_Selector>(childSeq->head()->first());
129+
if(pType && pType->name() == "*") {
130+
std::string msg("Can't append \"");
131+
msg += childSeq->to_string();
132+
msg += "\" to \"";
133+
msg += parentSeqClone->to_string();
134+
msg += "\" for `selector-append'";
135+
error(msg, pstate, traces);
136+
}
137+
138+
// TODO: Add check for namespace stuff
139+
140+
// append any selectors in childSeq's head
141+
parentSeqClone->innermost()->head()->concat(base->head());
142+
143+
// Set parentSeqClone new tail
144+
parentSeqClone->innermost()->tail( base->tail() );
145+
146+
newElements.push_back(parentSeqClone);
147+
}
148+
}
149+
150+
result->elements(newElements);
151+
}
152+
153+
Listize listize;
154+
return Cast<Value>(result->perform(&listize));
155+
}
156+
157+
Signature selector_unify_sig = "selector-unify($selector1, $selector2)";
158+
BUILT_IN(selector_unify)
159+
{
160+
Selector_List_Obj selector1 = ARGSELS("$selector1");
161+
Selector_List_Obj selector2 = ARGSELS("$selector2");
162+
163+
Selector_List_Obj result = selector1->unify_with(selector2);
164+
Listize listize;
165+
return Cast<Value>(result->perform(&listize));
166+
}
167+
168+
Signature simple_selectors_sig = "simple-selectors($selector)";
169+
BUILT_IN(simple_selectors)
170+
{
171+
Compound_Selector_Obj sel = ARGSEL("$selector");
172+
173+
List_Ptr l = SASS_MEMORY_NEW(List, sel->pstate(), sel->length(), SASS_COMMA);
174+
175+
for (size_t i = 0, L = sel->length(); i < L; ++i) {
176+
Simple_Selector_Obj ss = (*sel)[i];
177+
std::string ss_string = ss->to_string() ;
178+
179+
l->append(SASS_MEMORY_NEW(String_Quoted, ss->pstate(), ss_string));
180+
}
181+
182+
return l;
183+
}
184+
185+
Signature selector_extend_sig = "selector-extend($selector, $extendee, $extender)";
186+
BUILT_IN(selector_extend)
187+
{
188+
Selector_List_Obj selector = ARGSELS("$selector");
189+
Selector_List_Obj extendee = ARGSELS("$extendee");
190+
Selector_List_Obj extender = ARGSELS("$extender");
191+
192+
Subset_Map subset_map;
193+
extender->populate_extends(extendee, subset_map);
194+
Extend extend(subset_map);
195+
196+
Selector_List_Obj result = extend.extendSelectorList(selector, false);
197+
198+
Listize listize;
199+
return Cast<Value>(result->perform(&listize));
200+
}
201+
202+
Signature selector_replace_sig = "selector-replace($selector, $original, $replacement)";
203+
BUILT_IN(selector_replace)
204+
{
205+
Selector_List_Obj selector = ARGSELS("$selector");
206+
Selector_List_Obj original = ARGSELS("$original");
207+
Selector_List_Obj replacement = ARGSELS("$replacement");
208+
Subset_Map subset_map;
209+
replacement->populate_extends(original, subset_map);
210+
Extend extend(subset_map);
211+
212+
Selector_List_Obj result = extend.extendSelectorList(selector, true);
213+
214+
Listize listize;
215+
return Cast<Value>(result->perform(&listize));
216+
}
217+
218+
Signature selector_parse_sig = "selector-parse($selector)";
219+
BUILT_IN(selector_parse)
220+
{
221+
Selector_List_Obj sel = ARGSELS("$selector");
222+
223+
Listize listize;
224+
return Cast<Value>(sel->perform(&listize));
225+
}
226+
227+
Signature is_superselector_sig = "is-superselector($super, $sub)";
228+
BUILT_IN(is_superselector)
229+
{
230+
Selector_List_Obj sel_sup = ARGSELS("$super");
231+
Selector_List_Obj sel_sub = ARGSELS("$sub");
232+
bool result = sel_sup->is_superselector_of(sel_sub);
233+
return SASS_MEMORY_NEW(Boolean, pstate, result);
234+
}
235+
236+
}
237+
238+
}

src/fn_selectors.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#ifndef SASS_FN_SELECTORS_H
2+
#define SASS_FN_SELECTORS_H
3+
4+
#include "fn_utils.hpp"
5+
6+
namespace Sass {
7+
8+
namespace Functions {
9+
10+
#define ARGSEL(argname) get_arg_sel(argname, env, sig, pstate, traces, ctx)
11+
#define ARGSELS(argname) get_arg_sels(argname, env, sig, pstate, traces, ctx)
12+
13+
BUILT_IN(selector_nest);
14+
BUILT_IN(selector_append);
15+
BUILT_IN(selector_extend);
16+
BUILT_IN(selector_replace);
17+
BUILT_IN(selector_unify);
18+
BUILT_IN(is_superselector);
19+
BUILT_IN(simple_selectors);
20+
BUILT_IN(selector_parse);
21+
22+
extern Signature selector_nest_sig;
23+
extern Signature selector_append_sig;
24+
extern Signature selector_extend_sig;
25+
extern Signature selector_replace_sig;
26+
extern Signature selector_unify_sig;
27+
extern Signature is_superselector_sig;
28+
extern Signature simple_selectors_sig;
29+
extern Signature selector_parse_sig;
30+
31+
}
32+
33+
}
34+
35+
#endif

src/fn_utils.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ namespace Sass {
2828
#define COLOR_NUM(argname) color_num(argname, env, sig, pstate, traces) // double
2929
#define ALPHA_NUM(argname) alpha_num(argname, env, sig, pstate, traces) // double
3030

31-
#define ARGSEL(argname) get_arg_sel(argname, env, sig, pstate, traces, ctx)
32-
#define ARGSELS(argname) get_arg_sels(argname, env, sig, pstate, traces, ctx)
33-
3431
typedef const char* Signature;
3532

3633
typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtraces, SelectorStack);

0 commit comments

Comments
 (0)