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