1+ #include " ast.hpp"
2+ #include " expand.hpp"
3+ #include " fn_utils.hpp"
4+ #include " fn_miscs.hpp"
5+ #include " debugger.hpp"
6+
7+ namespace Sass {
8+
9+ namespace Functions {
10+
11+ // features
12+ static std::set<std::string> features {
13+ " global-variable-shadowing" ,
14+ " extend-selector-pseudoclass" ,
15+ " at-error" ,
16+ " units-level-3" ,
17+ " custom-property"
18+ };
19+
20+ // ////////////////////////
21+ // INTROSPECTION FUNCTIONS
22+ // ////////////////////////
23+
24+ Signature type_of_sig = " type-of($value)" ;
25+ BUILT_IN (type_of)
26+ {
27+ Expression_Ptr v = ARG (" $value" , Expression);
28+ return SASS_MEMORY_NEW (String_Quoted, pstate, v->type ());
29+ }
30+
31+ Signature variable_exists_sig = " variable-exists($name)" ;
32+ BUILT_IN (variable_exists)
33+ {
34+ std::string s = Util::normalize_underscores (unquote (ARG (" $name" , String_Constant)->value ()));
35+
36+ if (d_env.has (" $" +s)) {
37+ return SASS_MEMORY_NEW (Boolean, pstate, true );
38+ }
39+ else {
40+ return SASS_MEMORY_NEW (Boolean, pstate, false );
41+ }
42+ }
43+
44+ Signature global_variable_exists_sig = " global-variable-exists($name)" ;
45+ BUILT_IN (global_variable_exists)
46+ {
47+ std::string s = Util::normalize_underscores (unquote (ARG (" $name" , String_Constant)->value ()));
48+
49+ if (d_env.has_global (" $" +s)) {
50+ return SASS_MEMORY_NEW (Boolean, pstate, true );
51+ }
52+ else {
53+ return SASS_MEMORY_NEW (Boolean, pstate, false );
54+ }
55+ }
56+
57+ Signature function_exists_sig = " function-exists($name)" ;
58+ BUILT_IN (function_exists)
59+ {
60+ String_Constant_Ptr ss = Cast<String_Constant>(env[" $name" ]);
61+ if (!ss) {
62+ error (" $name: " + (env[" $name" ]->to_string ()) + " is not a string for `function-exists'" , pstate, traces);
63+ }
64+
65+ std::string name = Util::normalize_underscores (unquote (ss->value ()));
66+
67+ if (d_env.has_global (name+" [f]" )) {
68+ return SASS_MEMORY_NEW (Boolean, pstate, true );
69+ }
70+ else {
71+ return SASS_MEMORY_NEW (Boolean, pstate, false );
72+ }
73+ }
74+
75+ Signature mixin_exists_sig = " mixin-exists($name)" ;
76+ BUILT_IN (mixin_exists)
77+ {
78+ std::string s = Util::normalize_underscores (unquote (ARG (" $name" , String_Constant)->value ()));
79+
80+ if (d_env.has_global (s+" [m]" )) {
81+ return SASS_MEMORY_NEW (Boolean, pstate, true );
82+ }
83+ else {
84+ return SASS_MEMORY_NEW (Boolean, pstate, false );
85+ }
86+ }
87+
88+ Signature feature_exists_sig = " feature-exists($name)" ;
89+ BUILT_IN (feature_exists)
90+ {
91+ std::string s = unquote (ARG (" $name" , String_Constant)->value ());
92+
93+ if (features.find (s) == features.end ()) {
94+ return SASS_MEMORY_NEW (Boolean, pstate, false );
95+ }
96+ else {
97+ return SASS_MEMORY_NEW (Boolean, pstate, true );
98+ }
99+ }
100+
101+ Signature call_sig = " call($name, $args...)" ;
102+ BUILT_IN (call)
103+ {
104+ std::string name;
105+ Function_Ptr ff = Cast<Function>(env[" $name" ]);
106+ String_Constant_Ptr ss = Cast<String_Constant>(env[" $name" ]);
107+
108+ if (ss) {
109+ name = Util::normalize_underscores (unquote (ss->value ()));
110+ std::cerr << " DEPRECATION WARNING: " ;
111+ std::cerr << " Passing a string to call() is deprecated and will be illegal" << std::endl;
112+ std::cerr << " in Sass 4.0. Use call(get-function(" + quote (name) + " )) instead." << std::endl;
113+ std::cerr << std::endl;
114+ } else if (ff) {
115+ name = ff->name ();
116+ }
117+
118+ List_Obj arglist = SASS_MEMORY_COPY (ARG (" $args" , List));
119+
120+ Arguments_Obj args = SASS_MEMORY_NEW (Arguments, pstate);
121+ // std::string full_name(name + "[f]");
122+ // Definition_Ptr def = d_env.has(full_name) ? Cast<Definition>((d_env)[full_name]) : 0;
123+ // Parameters_Ptr params = def ? def->parameters() : 0;
124+ // size_t param_size = params ? params->length() : 0;
125+ for (size_t i = 0 , L = arglist->length (); i < L; ++i) {
126+ Expression_Obj expr = arglist->value_at_index (i);
127+ // if (params && params->has_rest_parameter()) {
128+ // Parameter_Obj p = param_size > i ? (*params)[i] : 0;
129+ // List_Ptr list = Cast<List>(expr);
130+ // if (list && p && !p->is_rest_parameter()) expr = (*list)[0];
131+ // }
132+ if (arglist->is_arglist ()) {
133+ Expression_Obj obj = arglist->at (i);
134+ Argument_Obj arg = (Argument_Ptr) obj.ptr (); // XXX
135+ args->append (SASS_MEMORY_NEW (Argument,
136+ pstate,
137+ expr,
138+ arg ? arg->name () : " " ,
139+ arg ? arg->is_rest_argument () : false ,
140+ arg ? arg->is_keyword_argument () : false ));
141+ } else {
142+ args->append (SASS_MEMORY_NEW (Argument, pstate, expr));
143+ }
144+ }
145+ Function_Call_Obj func = SASS_MEMORY_NEW (Function_Call, pstate, name, args);
146+ Expand expand (ctx, &d_env, &selector_stack);
147+ func->via_call (true ); // calc invoke is allowed
148+ if (ff) func->func (ff);
149+ return func->perform (&expand.eval );
150+ }
151+
152+ // //////////////////
153+ // BOOLEAN FUNCTIONS
154+ // //////////////////
155+
156+ Signature not_sig = " not($value)" ;
157+ BUILT_IN (sass_not)
158+ {
159+ return SASS_MEMORY_NEW (Boolean, pstate, ARG (" $value" , Expression)->is_false ());
160+ }
161+
162+ Signature if_sig = " if($condition, $if-true, $if-false)" ;
163+ // BUILT_IN(sass_if)
164+ // { return ARG("$condition", Expression)->is_false() ? ARG("$if-false", Expression) : ARG("$if-true", Expression); }
165+ BUILT_IN (sass_if)
166+ {
167+ Expand expand (ctx, &d_env, &selector_stack);
168+ Expression_Obj cond = ARG (" $condition" , Expression)->perform (&expand.eval );
169+ bool is_true = !cond->is_false ();
170+ Expression_Obj res = ARG (is_true ? " $if-true" : " $if-false" , Expression);
171+ Value_Obj qwe = Cast<Value>(res->perform (&expand.eval ));
172+ // if (qwe == 0) debug_ast(res);
173+ // res = res->perform(&expand.eval.val_eval);
174+ qwe->set_delayed (false ); // clone?
175+ return qwe.detach ();
176+ }
177+
178+ // ////////////////////////
179+ // MISCELLANEOUS FUNCTIONS
180+ // ////////////////////////
181+
182+ // value.check_deprecated_interp if value.is_a?(Sass::Script::Value::String)
183+ // unquoted_string(value.to_sass)
184+
185+ Signature inspect_sig = " inspect($value)" ;
186+ BUILT_IN (inspect)
187+ {
188+ Expression_Ptr v = ARG (" $value" , Expression);
189+ if (v->concrete_type () == Expression::NULL_VAL) {
190+ return SASS_MEMORY_NEW (String_Quoted, pstate, " null" );
191+ } else if (v->concrete_type () == Expression::BOOLEAN && v->is_false ()) {
192+ return SASS_MEMORY_NEW (String_Quoted, pstate, " false" );
193+ } else if (v->concrete_type () == Expression::STRING) {
194+ return Cast<String>(v);
195+ } else {
196+ // ToDo: fix to_sass for nested parentheses
197+ Sass_Output_Style old_style;
198+ old_style = ctx.c_options .output_style ;
199+ ctx.c_options .output_style = TO_SASS;
200+ Emitter emitter (ctx.c_options );
201+ Inspect i (emitter);
202+ i.in_declaration = false ;
203+ v->perform (&i);
204+ ctx.c_options .output_style = old_style;
205+ return SASS_MEMORY_NEW (String_Quoted, pstate, i.get_buffer ());
206+ }
207+ // return v;
208+ }
209+
210+ Signature content_exists_sig = " content-exists()" ;
211+ BUILT_IN (content_exists)
212+ {
213+ if (!d_env.has_global (" is_in_mixin" )) {
214+ error (" Cannot call content-exists() except within a mixin." , pstate, traces);
215+ }
216+ return SASS_MEMORY_NEW (Boolean, pstate, d_env.has_lexical (" @content[m]" ));
217+ }
218+
219+ Signature get_function_sig = " get-function($name, $css: false)" ;
220+ BUILT_IN (get_function)
221+ {
222+ String_Constant_Ptr ss = Cast<String_Constant>(env[" $name" ]);
223+ if (!ss) {
224+ error (" $name: " + (env[" $name" ]->to_string ()) + " is not a string for `get-function'" , pstate, traces);
225+ }
226+
227+ std::string name = Util::normalize_underscores (unquote (ss->value ()));
228+ std::string full_name = name + " [f]" ;
229+
230+ Boolean_Obj css = ARG (" $css" , Boolean);
231+ if (!css->is_false ()) {
232+ Definition_Ptr def = SASS_MEMORY_NEW (Definition,
233+ pstate,
234+ name,
235+ SASS_MEMORY_NEW (Parameters, pstate),
236+ SASS_MEMORY_NEW (Block, pstate, 0 , false ),
237+ Definition::FUNCTION);
238+ return SASS_MEMORY_NEW (Function, pstate, def, true );
239+ }
240+
241+
242+ if (!d_env.has_global (full_name)) {
243+ error (" Function not found: " + name, pstate, traces);
244+ }
245+
246+ Definition_Ptr def = Cast<Definition>(d_env[full_name]);
247+ return SASS_MEMORY_NEW (Function, pstate, def, false );
248+ }
249+
250+ }
251+
252+ }
0 commit comments