1 | // sass.hpp must go before all system headers to get the |
2 | // __EXTENSIONS__ fix on Solaris. |
3 | #include "sass.hpp" |
4 | |
5 | #include "ast.hpp" |
6 | |
7 | namespace Sass { |
8 | |
9 | static Null sass_null(SourceSpan("null" )); |
10 | |
11 | const char* sass_op_to_name(enum Sass_OP op) { |
12 | switch (op) { |
13 | case AND: return "and" ; |
14 | case OR: return "or" ; |
15 | case EQ: return "eq" ; |
16 | case NEQ: return "neq" ; |
17 | case GT: return "gt" ; |
18 | case GTE: return "gte" ; |
19 | case LT: return "lt" ; |
20 | case LTE: return "lte" ; |
21 | case ADD: return "plus" ; |
22 | case SUB: return "minus" ; |
23 | case MUL: return "times" ; |
24 | case DIV: return "div" ; |
25 | case MOD: return "mod" ; |
26 | // this is only used internally! |
27 | case NUM_OPS: return "[OPS]" ; |
28 | default: return "invalid" ; |
29 | } |
30 | } |
31 | |
32 | const char* sass_op_separator(enum Sass_OP op) { |
33 | switch (op) { |
34 | case AND: return "&&" ; |
35 | case OR: return "||" ; |
36 | case EQ: return "==" ; |
37 | case NEQ: return "!=" ; |
38 | case GT: return ">" ; |
39 | case GTE: return ">=" ; |
40 | case LT: return "<" ; |
41 | case LTE: return "<=" ; |
42 | case ADD: return "+" ; |
43 | case SUB: return "-" ; |
44 | case MUL: return "*" ; |
45 | case DIV: return "/" ; |
46 | case MOD: return "%" ; |
47 | // this is only used internally! |
48 | case NUM_OPS: return "[OPS]" ; |
49 | default: return "invalid" ; |
50 | } |
51 | } |
52 | |
53 | ///////////////////////////////////////////////////////////////////////// |
54 | ///////////////////////////////////////////////////////////////////////// |
55 | |
56 | void AST_Node::update_pstate(const SourceSpan& pstate) |
57 | { |
58 | pstate_.offset += pstate.position - pstate_.position + pstate.offset; |
59 | } |
60 | |
61 | sass::string AST_Node::to_string(Sass_Inspect_Options opt) const |
62 | { |
63 | Sass_Output_Options out(opt); |
64 | Emitter emitter(out); |
65 | Inspect i(emitter); |
66 | i.in_declaration = true; |
67 | // ToDo: inspect should be const |
68 | const_cast<AST_Node*>(this)->perform(op: &i); |
69 | return i.get_buffer(); |
70 | } |
71 | |
72 | sass::string AST_Node::to_css(Sass_Inspect_Options opt) const |
73 | { |
74 | opt.output_style = TO_CSS; |
75 | Sass_Output_Options out(opt); |
76 | Emitter emitter(out); |
77 | Inspect i(emitter); |
78 | i.in_declaration = true; |
79 | // ToDo: inspect should be const |
80 | const_cast<AST_Node*>(this)->perform(op: &i); |
81 | return i.get_buffer(); |
82 | } |
83 | |
84 | sass::string AST_Node::to_string() const |
85 | { |
86 | return to_string(opt: { NESTED, 5 }); |
87 | } |
88 | |
89 | ///////////////////////////////////////////////////////////////////////// |
90 | ///////////////////////////////////////////////////////////////////////// |
91 | |
92 | Statement::Statement(SourceSpan pstate, Type st, size_t t) |
93 | : AST_Node(pstate), statement_type_(st), tabs_(t), group_end_(false) |
94 | { } |
95 | Statement::Statement(const Statement* ptr) |
96 | : AST_Node(ptr), |
97 | statement_type_(ptr->statement_type_), |
98 | tabs_(ptr->tabs_), |
99 | group_end_(ptr->group_end_) |
100 | { } |
101 | |
102 | bool Statement::bubbles() |
103 | { |
104 | return false; |
105 | } |
106 | |
107 | bool Statement::has_content() |
108 | { |
109 | return statement_type_ == CONTENT; |
110 | } |
111 | |
112 | bool Statement::is_invisible() const |
113 | { |
114 | return false; |
115 | } |
116 | |
117 | ///////////////////////////////////////////////////////////////////////// |
118 | ///////////////////////////////////////////////////////////////////////// |
119 | |
120 | Block::Block(SourceSpan pstate, size_t s, bool r) |
121 | : Statement(pstate), |
122 | Vectorized<Statement_Obj>(s), |
123 | is_root_(r) |
124 | { } |
125 | Block::Block(const Block* ptr) |
126 | : Statement(ptr), |
127 | Vectorized<Statement_Obj>(*ptr), |
128 | is_root_(ptr->is_root_) |
129 | { } |
130 | |
131 | bool Block::isInvisible() const |
132 | { |
133 | for (auto& item : elements()) { |
134 | if (!item->is_invisible()) return false; |
135 | } |
136 | return true; |
137 | } |
138 | |
139 | bool Block::has_content() |
140 | { |
141 | for (size_t i = 0, L = elements().size(); i < L; ++i) { |
142 | if (elements()[i]->has_content()) return true; |
143 | } |
144 | return Statement::has_content(); |
145 | } |
146 | |
147 | ///////////////////////////////////////////////////////////////////////// |
148 | ///////////////////////////////////////////////////////////////////////// |
149 | |
150 | ParentStatement::ParentStatement(SourceSpan pstate, Block_Obj b) |
151 | : Statement(pstate), block_(b) |
152 | { } |
153 | ParentStatement::ParentStatement(const ParentStatement* ptr) |
154 | : Statement(ptr), block_(ptr->block_) |
155 | { } |
156 | |
157 | bool ParentStatement::has_content() |
158 | { |
159 | return (block_ && block_->has_content()) || Statement::has_content(); |
160 | } |
161 | |
162 | ///////////////////////////////////////////////////////////////////////// |
163 | ///////////////////////////////////////////////////////////////////////// |
164 | |
165 | StyleRule::StyleRule(SourceSpan pstate, SelectorListObj s, Block_Obj b) |
166 | : ParentStatement(pstate, b), selector_(s), schema_(), is_root_(false) |
167 | { statement_type(statement_type__: RULESET); } |
168 | StyleRule::StyleRule(const StyleRule* ptr) |
169 | : ParentStatement(ptr), |
170 | selector_(ptr->selector_), |
171 | schema_(ptr->schema_), |
172 | is_root_(ptr->is_root_) |
173 | { statement_type(statement_type__: RULESET); } |
174 | |
175 | bool StyleRule::is_invisible() const { |
176 | if (const SelectorList * sl = Cast<SelectorList>(ptr: selector())) { |
177 | for (size_t i = 0, L = sl->length(); i < L; i += 1) |
178 | if (!(*sl)[i]->isInvisible()) return false; |
179 | } |
180 | return true; |
181 | } |
182 | |
183 | ///////////////////////////////////////////////////////////////////////// |
184 | ///////////////////////////////////////////////////////////////////////// |
185 | |
186 | Bubble::Bubble(SourceSpan pstate, Statement_Obj n, Statement_Obj g, size_t t) |
187 | : Statement(pstate, Statement::BUBBLE, t), node_(n), group_end_(g == nullptr) |
188 | { } |
189 | Bubble::Bubble(const Bubble* ptr) |
190 | : Statement(ptr), |
191 | node_(ptr->node_), |
192 | group_end_(ptr->group_end_) |
193 | { } |
194 | |
195 | bool Bubble::bubbles() |
196 | { |
197 | return true; |
198 | } |
199 | |
200 | ///////////////////////////////////////////////////////////////////////// |
201 | ///////////////////////////////////////////////////////////////////////// |
202 | |
203 | Trace::Trace(SourceSpan pstate, sass::string n, Block_Obj b, char type) |
204 | : ParentStatement(pstate, b), type_(type), name_(n) |
205 | { } |
206 | Trace::Trace(const Trace* ptr) |
207 | : ParentStatement(ptr), |
208 | type_(ptr->type_), |
209 | name_(ptr->name_) |
210 | { } |
211 | |
212 | ///////////////////////////////////////////////////////////////////////// |
213 | ///////////////////////////////////////////////////////////////////////// |
214 | |
215 | AtRule::AtRule(SourceSpan pstate, sass::string kwd, SelectorListObj sel, Block_Obj b, ExpressionObj val) |
216 | : ParentStatement(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed |
217 | { statement_type(statement_type__: DIRECTIVE); } |
218 | AtRule::AtRule(const AtRule* ptr) |
219 | : ParentStatement(ptr), |
220 | keyword_(ptr->keyword_), |
221 | selector_(ptr->selector_), |
222 | value_(ptr->value_) // set value manually if needed |
223 | { statement_type(statement_type__: DIRECTIVE); } |
224 | |
225 | bool AtRule::bubbles() { return is_keyframes() || is_media(); } |
226 | |
227 | bool AtRule::is_media() { |
228 | return keyword_.compare(s: "@-webkit-media" ) == 0 || |
229 | keyword_.compare(s: "@-moz-media" ) == 0 || |
230 | keyword_.compare(s: "@-o-media" ) == 0 || |
231 | keyword_.compare(s: "@media" ) == 0; |
232 | } |
233 | bool AtRule::is_keyframes() { |
234 | return keyword_.compare(s: "@-webkit-keyframes" ) == 0 || |
235 | keyword_.compare(s: "@-moz-keyframes" ) == 0 || |
236 | keyword_.compare(s: "@-o-keyframes" ) == 0 || |
237 | keyword_.compare(s: "@keyframes" ) == 0; |
238 | } |
239 | |
240 | ///////////////////////////////////////////////////////////////////////// |
241 | ///////////////////////////////////////////////////////////////////////// |
242 | |
243 | Keyframe_Rule::Keyframe_Rule(SourceSpan pstate, Block_Obj b) |
244 | : ParentStatement(pstate, b), name_() |
245 | { statement_type(statement_type__: KEYFRAMERULE); } |
246 | Keyframe_Rule::Keyframe_Rule(const Keyframe_Rule* ptr) |
247 | : ParentStatement(ptr), name_(ptr->name_) |
248 | { statement_type(statement_type__: KEYFRAMERULE); } |
249 | |
250 | ///////////////////////////////////////////////////////////////////////// |
251 | ///////////////////////////////////////////////////////////////////////// |
252 | |
253 | Declaration::Declaration(SourceSpan pstate, String_Obj prop, ExpressionObj val, bool i, bool c, Block_Obj b) |
254 | : ParentStatement(pstate, b), property_(prop), value_(val), is_important_(i), is_custom_property_(c), is_indented_(false) |
255 | { statement_type(statement_type__: DECLARATION); } |
256 | Declaration::Declaration(const Declaration* ptr) |
257 | : ParentStatement(ptr), |
258 | property_(ptr->property_), |
259 | value_(ptr->value_), |
260 | is_important_(ptr->is_important_), |
261 | is_custom_property_(ptr->is_custom_property_), |
262 | is_indented_(ptr->is_indented_) |
263 | { statement_type(statement_type__: DECLARATION); } |
264 | |
265 | bool Declaration::is_invisible() const |
266 | { |
267 | if (is_custom_property()) return false; |
268 | return !(value_ && !Cast<Null>(ptr: value_)); |
269 | } |
270 | |
271 | ///////////////////////////////////////////////////////////////////////// |
272 | ///////////////////////////////////////////////////////////////////////// |
273 | |
274 | Assignment::Assignment(SourceSpan pstate, sass::string var, ExpressionObj val, bool is_default, bool is_global) |
275 | : Statement(pstate), variable_(var), value_(val), is_default_(is_default), is_global_(is_global) |
276 | { statement_type(statement_type__: ASSIGNMENT); } |
277 | Assignment::Assignment(const Assignment* ptr) |
278 | : Statement(ptr), |
279 | variable_(ptr->variable_), |
280 | value_(ptr->value_), |
281 | is_default_(ptr->is_default_), |
282 | is_global_(ptr->is_global_) |
283 | { statement_type(statement_type__: ASSIGNMENT); } |
284 | |
285 | ///////////////////////////////////////////////////////////////////////// |
286 | ///////////////////////////////////////////////////////////////////////// |
287 | |
288 | Import::Import(SourceSpan pstate) |
289 | : Statement(pstate), |
290 | urls_(sass::vector<ExpressionObj>()), |
291 | incs_(sass::vector<Include>()), |
292 | import_queries_() |
293 | { statement_type(statement_type__: IMPORT); } |
294 | Import::Import(const Import* ptr) |
295 | : Statement(ptr), |
296 | urls_(ptr->urls_), |
297 | incs_(ptr->incs_), |
298 | import_queries_(ptr->import_queries_) |
299 | { statement_type(statement_type__: IMPORT); } |
300 | |
301 | sass::vector<Include>& Import::incs() { return incs_; } |
302 | sass::vector<ExpressionObj>& Import::urls() { return urls_; } |
303 | |
304 | ///////////////////////////////////////////////////////////////////////// |
305 | ///////////////////////////////////////////////////////////////////////// |
306 | |
307 | Import_Stub::Import_Stub(SourceSpan pstate, Include res) |
308 | : Statement(pstate), resource_(res) |
309 | { statement_type(statement_type__: IMPORT_STUB); } |
310 | Import_Stub::Import_Stub(const Import_Stub* ptr) |
311 | : Statement(ptr), resource_(ptr->resource_) |
312 | { statement_type(statement_type__: IMPORT_STUB); } |
313 | Include Import_Stub::resource() { return resource_; }; |
314 | sass::string Import_Stub::imp_path() { return resource_.imp_path; }; |
315 | sass::string Import_Stub::abs_path() { return resource_.abs_path; }; |
316 | |
317 | ///////////////////////////////////////////////////////////////////////// |
318 | ///////////////////////////////////////////////////////////////////////// |
319 | |
320 | WarningRule::WarningRule(SourceSpan pstate, ExpressionObj msg) |
321 | : Statement(pstate), message_(msg) |
322 | { statement_type(statement_type__: WARNING); } |
323 | WarningRule::WarningRule(const WarningRule* ptr) |
324 | : Statement(ptr), message_(ptr->message_) |
325 | { statement_type(statement_type__: WARNING); } |
326 | |
327 | ///////////////////////////////////////////////////////////////////////// |
328 | ///////////////////////////////////////////////////////////////////////// |
329 | |
330 | ErrorRule::ErrorRule(SourceSpan pstate, ExpressionObj msg) |
331 | : Statement(pstate), message_(msg) |
332 | { statement_type(statement_type__: ERROR); } |
333 | ErrorRule::ErrorRule(const ErrorRule* ptr) |
334 | : Statement(ptr), message_(ptr->message_) |
335 | { statement_type(statement_type__: ERROR); } |
336 | |
337 | ///////////////////////////////////////////////////////////////////////// |
338 | ///////////////////////////////////////////////////////////////////////// |
339 | |
340 | DebugRule::DebugRule(SourceSpan pstate, ExpressionObj val) |
341 | : Statement(pstate), value_(val) |
342 | { statement_type(statement_type__: DEBUGSTMT); } |
343 | DebugRule::DebugRule(const DebugRule* ptr) |
344 | : Statement(ptr), value_(ptr->value_) |
345 | { statement_type(statement_type__: DEBUGSTMT); } |
346 | |
347 | ///////////////////////////////////////////////////////////////////////// |
348 | ///////////////////////////////////////////////////////////////////////// |
349 | |
350 | Comment::(SourceSpan pstate, String_Obj txt, bool is_important) |
351 | : Statement(pstate), text_(txt), is_important_(is_important) |
352 | { statement_type(statement_type__: COMMENT); } |
353 | Comment::(const Comment* ptr) |
354 | : Statement(ptr), |
355 | text_(ptr->text_), |
356 | is_important_(ptr->is_important_) |
357 | { statement_type(statement_type__: COMMENT); } |
358 | |
359 | bool Comment::() const |
360 | { |
361 | return false; |
362 | } |
363 | |
364 | ///////////////////////////////////////////////////////////////////////// |
365 | ///////////////////////////////////////////////////////////////////////// |
366 | |
367 | If::If(SourceSpan pstate, ExpressionObj pred, Block_Obj con, Block_Obj alt) |
368 | : ParentStatement(pstate, con), predicate_(pred), alternative_(alt) |
369 | { statement_type(statement_type__: IF); } |
370 | If::If(const If* ptr) |
371 | : ParentStatement(ptr), |
372 | predicate_(ptr->predicate_), |
373 | alternative_(ptr->alternative_) |
374 | { statement_type(statement_type__: IF); } |
375 | |
376 | bool If::has_content() |
377 | { |
378 | return ParentStatement::has_content() || (alternative_ && alternative_->has_content()); |
379 | } |
380 | |
381 | ///////////////////////////////////////////////////////////////////////// |
382 | ///////////////////////////////////////////////////////////////////////// |
383 | |
384 | ForRule::ForRule(SourceSpan pstate, |
385 | sass::string var, ExpressionObj lo, ExpressionObj hi, Block_Obj b, bool inc) |
386 | : ParentStatement(pstate, b), |
387 | variable_(var), lower_bound_(lo), upper_bound_(hi), is_inclusive_(inc) |
388 | { statement_type(statement_type__: FOR); } |
389 | ForRule::ForRule(const ForRule* ptr) |
390 | : ParentStatement(ptr), |
391 | variable_(ptr->variable_), |
392 | lower_bound_(ptr->lower_bound_), |
393 | upper_bound_(ptr->upper_bound_), |
394 | is_inclusive_(ptr->is_inclusive_) |
395 | { statement_type(statement_type__: FOR); } |
396 | |
397 | ///////////////////////////////////////////////////////////////////////// |
398 | ///////////////////////////////////////////////////////////////////////// |
399 | |
400 | EachRule::EachRule(SourceSpan pstate, sass::vector<sass::string> vars, ExpressionObj lst, Block_Obj b) |
401 | : ParentStatement(pstate, b), variables_(vars), list_(lst) |
402 | { statement_type(statement_type__: EACH); } |
403 | EachRule::EachRule(const EachRule* ptr) |
404 | : ParentStatement(ptr), variables_(ptr->variables_), list_(ptr->list_) |
405 | { statement_type(statement_type__: EACH); } |
406 | |
407 | ///////////////////////////////////////////////////////////////////////// |
408 | ///////////////////////////////////////////////////////////////////////// |
409 | |
410 | WhileRule::WhileRule(SourceSpan pstate, ExpressionObj pred, Block_Obj b) |
411 | : ParentStatement(pstate, b), predicate_(pred) |
412 | { statement_type(statement_type__: WHILE); } |
413 | WhileRule::WhileRule(const WhileRule* ptr) |
414 | : ParentStatement(ptr), predicate_(ptr->predicate_) |
415 | { statement_type(statement_type__: WHILE); } |
416 | |
417 | ///////////////////////////////////////////////////////////////////////// |
418 | ///////////////////////////////////////////////////////////////////////// |
419 | |
420 | Return::Return(SourceSpan pstate, ExpressionObj val) |
421 | : Statement(pstate), value_(val) |
422 | { statement_type(statement_type__: RETURN); } |
423 | Return::Return(const Return* ptr) |
424 | : Statement(ptr), value_(ptr->value_) |
425 | { statement_type(statement_type__: RETURN); } |
426 | |
427 | ///////////////////////////////////////////////////////////////////////// |
428 | ///////////////////////////////////////////////////////////////////////// |
429 | |
430 | ExtendRule::ExtendRule(SourceSpan pstate, SelectorListObj s) |
431 | : Statement(pstate), isOptional_(false), selector_(s), schema_() |
432 | { statement_type(statement_type__: EXTEND); } |
433 | ExtendRule::ExtendRule(SourceSpan pstate, Selector_Schema_Obj s) |
434 | : Statement(pstate), isOptional_(false), selector_(), schema_(s) |
435 | { |
436 | statement_type(statement_type__: EXTEND); |
437 | } |
438 | ExtendRule::ExtendRule(const ExtendRule* ptr) |
439 | : Statement(ptr), |
440 | isOptional_(ptr->isOptional_), |
441 | selector_(ptr->selector_), |
442 | schema_(ptr->schema_) |
443 | { statement_type(statement_type__: EXTEND); } |
444 | |
445 | ///////////////////////////////////////////////////////////////////////// |
446 | ///////////////////////////////////////////////////////////////////////// |
447 | |
448 | Definition::Definition(const Definition* ptr) |
449 | : ParentStatement(ptr), |
450 | name_(ptr->name_), |
451 | parameters_(ptr->parameters_), |
452 | environment_(ptr->environment_), |
453 | type_(ptr->type_), |
454 | native_function_(ptr->native_function_), |
455 | c_function_(ptr->c_function_), |
456 | cookie_(ptr->cookie_), |
457 | is_overload_stub_(ptr->is_overload_stub_), |
458 | signature_(ptr->signature_) |
459 | { } |
460 | |
461 | Definition::Definition(SourceSpan pstate, |
462 | sass::string n, |
463 | Parameters_Obj params, |
464 | Block_Obj b, |
465 | Type t) |
466 | : ParentStatement(pstate, b), |
467 | name_(n), |
468 | parameters_(params), |
469 | environment_(0), |
470 | type_(t), |
471 | native_function_(0), |
472 | c_function_(0), |
473 | cookie_(0), |
474 | is_overload_stub_(false), |
475 | signature_(0) |
476 | { } |
477 | |
478 | Definition::Definition(SourceSpan pstate, |
479 | Signature sig, |
480 | sass::string n, |
481 | Parameters_Obj params, |
482 | Native_Function func_ptr, |
483 | bool overload_stub) |
484 | : ParentStatement(pstate, {}), |
485 | name_(n), |
486 | parameters_(params), |
487 | environment_(0), |
488 | type_(FUNCTION), |
489 | native_function_(func_ptr), |
490 | c_function_(0), |
491 | cookie_(0), |
492 | is_overload_stub_(overload_stub), |
493 | signature_(sig) |
494 | { } |
495 | |
496 | Definition::Definition(SourceSpan pstate, |
497 | Signature sig, |
498 | sass::string n, |
499 | Parameters_Obj params, |
500 | Sass_Function_Entry c_func) |
501 | : ParentStatement(pstate, {}), |
502 | name_(n), |
503 | parameters_(params), |
504 | environment_(0), |
505 | type_(FUNCTION), |
506 | native_function_(0), |
507 | c_function_(c_func), |
508 | cookie_(sass_function_get_cookie(cb: c_func)), |
509 | is_overload_stub_(false), |
510 | signature_(sig) |
511 | { } |
512 | |
513 | ///////////////////////////////////////////////////////////////////////// |
514 | ///////////////////////////////////////////////////////////////////////// |
515 | |
516 | Mixin_Call::Mixin_Call(SourceSpan pstate, sass::string n, Arguments_Obj args, Parameters_Obj b_params, Block_Obj b) |
517 | : ParentStatement(pstate, b), name_(n), arguments_(args), block_parameters_(b_params) |
518 | { } |
519 | Mixin_Call::Mixin_Call(const Mixin_Call* ptr) |
520 | : ParentStatement(ptr), |
521 | name_(ptr->name_), |
522 | arguments_(ptr->arguments_), |
523 | block_parameters_(ptr->block_parameters_) |
524 | { } |
525 | |
526 | ///////////////////////////////////////////////////////////////////////// |
527 | ///////////////////////////////////////////////////////////////////////// |
528 | |
529 | Content::Content(SourceSpan pstate, Arguments_Obj args) |
530 | : Statement(pstate), |
531 | arguments_(args) |
532 | { statement_type(statement_type__: CONTENT); } |
533 | Content::Content(const Content* ptr) |
534 | : Statement(ptr), |
535 | arguments_(ptr->arguments_) |
536 | { statement_type(statement_type__: CONTENT); } |
537 | |
538 | ///////////////////////////////////////////////////////////////////////// |
539 | ///////////////////////////////////////////////////////////////////////// |
540 | |
541 | Expression::Expression(SourceSpan pstate, bool d, bool e, bool i, Type ct) |
542 | : AST_Node(pstate), |
543 | is_delayed_(d), |
544 | is_expanded_(e), |
545 | is_interpolant_(i), |
546 | concrete_type_(ct) |
547 | { } |
548 | |
549 | Expression::Expression(const Expression* ptr) |
550 | : AST_Node(ptr), |
551 | is_delayed_(ptr->is_delayed_), |
552 | is_expanded_(ptr->is_expanded_), |
553 | is_interpolant_(ptr->is_interpolant_), |
554 | concrete_type_(ptr->concrete_type_) |
555 | { } |
556 | |
557 | ///////////////////////////////////////////////////////////////////////// |
558 | ///////////////////////////////////////////////////////////////////////// |
559 | |
560 | Unary_Expression::Unary_Expression(SourceSpan pstate, Type t, ExpressionObj o) |
561 | : Expression(pstate), optype_(t), operand_(o), hash_(0) |
562 | { } |
563 | Unary_Expression::Unary_Expression(const Unary_Expression* ptr) |
564 | : Expression(ptr), |
565 | optype_(ptr->optype_), |
566 | operand_(ptr->operand_), |
567 | hash_(ptr->hash_) |
568 | { } |
569 | const sass::string Unary_Expression::type_name() { |
570 | switch (optype_) { |
571 | case PLUS: return "plus" ; |
572 | case MINUS: return "minus" ; |
573 | case SLASH: return "slash" ; |
574 | case NOT: return "not" ; |
575 | default: return "invalid" ; |
576 | } |
577 | } |
578 | bool Unary_Expression::operator==(const Expression& rhs) const |
579 | { |
580 | try |
581 | { |
582 | const Unary_Expression* m = Cast<Unary_Expression>(ptr: &rhs); |
583 | if (m == 0) return false; |
584 | return type() == m->type() && |
585 | *operand() == *m->operand(); |
586 | } |
587 | catch (std::bad_cast&) |
588 | { |
589 | return false; |
590 | } |
591 | catch (...) { throw; } |
592 | } |
593 | size_t Unary_Expression::hash() const |
594 | { |
595 | if (hash_ == 0) { |
596 | hash_ = std::hash<size_t>()(optype_); |
597 | hash_combine(seed&: hash_, val: operand()->hash()); |
598 | }; |
599 | return hash_; |
600 | } |
601 | |
602 | ///////////////////////////////////////////////////////////////////////// |
603 | ///////////////////////////////////////////////////////////////////////// |
604 | |
605 | Argument::Argument(SourceSpan pstate, ExpressionObj val, sass::string n, bool rest, bool keyword) |
606 | : Expression(pstate), value_(val), name_(n), is_rest_argument_(rest), is_keyword_argument_(keyword), hash_(0) |
607 | { |
608 | if (!name_.empty() && is_rest_argument_) { |
609 | coreError(msg: "variable-length argument may not be passed by name" , pstate: pstate_); |
610 | } |
611 | } |
612 | Argument::Argument(const Argument* ptr) |
613 | : Expression(ptr), |
614 | value_(ptr->value_), |
615 | name_(ptr->name_), |
616 | is_rest_argument_(ptr->is_rest_argument_), |
617 | is_keyword_argument_(ptr->is_keyword_argument_), |
618 | hash_(ptr->hash_) |
619 | { |
620 | if (!name_.empty() && is_rest_argument_) { |
621 | coreError(msg: "variable-length argument may not be passed by name" , pstate: pstate_); |
622 | } |
623 | } |
624 | |
625 | void Argument::set_delayed(bool delayed) |
626 | { |
627 | if (value_) value_->set_delayed(delayed); |
628 | is_delayed(is_delayed__: delayed); |
629 | } |
630 | |
631 | bool Argument::operator==(const Expression& rhs) const |
632 | { |
633 | try |
634 | { |
635 | const Argument* m = Cast<Argument>(ptr: &rhs); |
636 | if (!(m && name() == m->name())) return false; |
637 | return *value() == *m->value(); |
638 | } |
639 | catch (std::bad_cast&) |
640 | { |
641 | return false; |
642 | } |
643 | catch (...) { throw; } |
644 | } |
645 | |
646 | size_t Argument::hash() const |
647 | { |
648 | if (hash_ == 0) { |
649 | hash_ = std::hash<sass::string>()(name()); |
650 | hash_combine(seed&: hash_, val: value()->hash()); |
651 | } |
652 | return hash_; |
653 | } |
654 | |
655 | ///////////////////////////////////////////////////////////////////////// |
656 | ///////////////////////////////////////////////////////////////////////// |
657 | |
658 | Arguments::Arguments(SourceSpan pstate) |
659 | : Expression(pstate), |
660 | Vectorized<Argument_Obj>(), |
661 | has_named_arguments_(false), |
662 | has_rest_argument_(false), |
663 | has_keyword_argument_(false) |
664 | { } |
665 | Arguments::Arguments(const Arguments* ptr) |
666 | : Expression(ptr), |
667 | Vectorized<Argument_Obj>(*ptr), |
668 | has_named_arguments_(ptr->has_named_arguments_), |
669 | has_rest_argument_(ptr->has_rest_argument_), |
670 | has_keyword_argument_(ptr->has_keyword_argument_) |
671 | { } |
672 | |
673 | void Arguments::set_delayed(bool delayed) |
674 | { |
675 | for (Argument_Obj arg : elements()) { |
676 | if (arg) arg->set_delayed(delayed); |
677 | } |
678 | is_delayed(is_delayed__: delayed); |
679 | } |
680 | |
681 | Argument_Obj Arguments::get_rest_argument() |
682 | { |
683 | if (this->has_rest_argument()) { |
684 | for (Argument_Obj arg : this->elements()) { |
685 | if (arg->is_rest_argument()) { |
686 | return arg; |
687 | } |
688 | } |
689 | } |
690 | return {}; |
691 | } |
692 | |
693 | Argument_Obj Arguments::get_keyword_argument() |
694 | { |
695 | if (this->has_keyword_argument()) { |
696 | for (Argument_Obj arg : this->elements()) { |
697 | if (arg->is_keyword_argument()) { |
698 | return arg; |
699 | } |
700 | } |
701 | } |
702 | return {}; |
703 | } |
704 | |
705 | void Arguments::adjust_after_pushing(Argument_Obj a) |
706 | { |
707 | if (!a->name().empty()) { |
708 | if (has_keyword_argument()) { |
709 | coreError(msg: "named arguments must precede variable-length argument" , pstate: a->pstate()); |
710 | } |
711 | has_named_arguments(has_named_arguments__: true); |
712 | } |
713 | else if (a->is_rest_argument()) { |
714 | if (has_rest_argument()) { |
715 | coreError(msg: "functions and mixins may only be called with one variable-length argument" , pstate: a->pstate()); |
716 | } |
717 | if (has_keyword_argument_) { |
718 | coreError(msg: "only keyword arguments may follow variable arguments" , pstate: a->pstate()); |
719 | } |
720 | has_rest_argument(has_rest_argument__: true); |
721 | } |
722 | else if (a->is_keyword_argument()) { |
723 | if (has_keyword_argument()) { |
724 | coreError(msg: "functions and mixins may only be called with one keyword argument" , pstate: a->pstate()); |
725 | } |
726 | has_keyword_argument(has_keyword_argument__: true); |
727 | } |
728 | else { |
729 | if (has_rest_argument()) { |
730 | coreError(msg: "ordinal arguments must precede variable-length arguments" , pstate: a->pstate()); |
731 | } |
732 | if (has_named_arguments()) { |
733 | coreError(msg: "ordinal arguments must precede named arguments" , pstate: a->pstate()); |
734 | } |
735 | } |
736 | } |
737 | |
738 | ///////////////////////////////////////////////////////////////////////// |
739 | ///////////////////////////////////////////////////////////////////////// |
740 | |
741 | Media_Query::Media_Query(SourceSpan pstate, String_Obj t, size_t s, bool n, bool r) |
742 | : Expression(pstate), Vectorized<Media_Query_ExpressionObj>(s), |
743 | media_type_(t), is_negated_(n), is_restricted_(r) |
744 | { } |
745 | Media_Query::Media_Query(const Media_Query* ptr) |
746 | : Expression(ptr), |
747 | Vectorized<Media_Query_ExpressionObj>(*ptr), |
748 | media_type_(ptr->media_type_), |
749 | is_negated_(ptr->is_negated_), |
750 | is_restricted_(ptr->is_restricted_) |
751 | { } |
752 | |
753 | ///////////////////////////////////////////////////////////////////////// |
754 | ///////////////////////////////////////////////////////////////////////// |
755 | |
756 | Media_Query_Expression::Media_Query_Expression(SourceSpan pstate, |
757 | ExpressionObj f, ExpressionObj v, bool i) |
758 | : Expression(pstate), feature_(f), value_(v), is_interpolated_(i) |
759 | { } |
760 | Media_Query_Expression::Media_Query_Expression(const Media_Query_Expression* ptr) |
761 | : Expression(ptr), |
762 | feature_(ptr->feature_), |
763 | value_(ptr->value_), |
764 | is_interpolated_(ptr->is_interpolated_) |
765 | { } |
766 | |
767 | ///////////////////////////////////////////////////////////////////////// |
768 | ///////////////////////////////////////////////////////////////////////// |
769 | |
770 | At_Root_Query::At_Root_Query(SourceSpan pstate, ExpressionObj f, ExpressionObj v, bool i) |
771 | : Expression(pstate), feature_(f), value_(v) |
772 | { } |
773 | At_Root_Query::At_Root_Query(const At_Root_Query* ptr) |
774 | : Expression(ptr), |
775 | feature_(ptr->feature_), |
776 | value_(ptr->value_) |
777 | { } |
778 | |
779 | bool At_Root_Query::exclude(sass::string str) |
780 | { |
781 | bool with = feature() && unquote(feature()->to_string()).compare(s: "with" ) == 0; |
782 | List* l = static_cast<List*>(value().ptr()); |
783 | sass::string v; |
784 | |
785 | if (with) |
786 | { |
787 | if (!l || l->length() == 0) return str.compare(s: "rule" ) != 0; |
788 | for (size_t i = 0, L = l->length(); i < L; ++i) |
789 | { |
790 | v = unquote((*l)[i]->to_string()); |
791 | if (v.compare(s: "all" ) == 0 || v == str) return false; |
792 | } |
793 | return true; |
794 | } |
795 | else |
796 | { |
797 | if (!l || !l->length()) return str.compare(s: "rule" ) == 0; |
798 | for (size_t i = 0, L = l->length(); i < L; ++i) |
799 | { |
800 | v = unquote((*l)[i]->to_string()); |
801 | if (v.compare(s: "all" ) == 0 || v == str) return true; |
802 | } |
803 | return false; |
804 | } |
805 | } |
806 | |
807 | ///////////////////////////////////////////////////////////////////////// |
808 | ///////////////////////////////////////////////////////////////////////// |
809 | |
810 | AtRootRule::AtRootRule(SourceSpan pstate, Block_Obj b, At_Root_Query_Obj e) |
811 | : ParentStatement(pstate, b), expression_(e) |
812 | { statement_type(statement_type__: ATROOT); } |
813 | AtRootRule::AtRootRule(const AtRootRule* ptr) |
814 | : ParentStatement(ptr), expression_(ptr->expression_) |
815 | { statement_type(statement_type__: ATROOT); } |
816 | |
817 | bool AtRootRule::bubbles() { |
818 | return true; |
819 | } |
820 | |
821 | bool AtRootRule::exclude_node(Statement_Obj s) { |
822 | if (expression() == nullptr) |
823 | { |
824 | return s->statement_type() == Statement::RULESET; |
825 | } |
826 | |
827 | if (s->statement_type() == Statement::DIRECTIVE) |
828 | { |
829 | if (AtRuleObj dir = Cast<AtRule>(ptr: s)) |
830 | { |
831 | sass::string keyword(dir->keyword()); |
832 | if (keyword.length() > 0) keyword.erase(pos: 0, n: 1); |
833 | return expression()->exclude(str: keyword); |
834 | } |
835 | } |
836 | if (s->statement_type() == Statement::MEDIA) |
837 | { |
838 | return expression()->exclude(str: "media" ); |
839 | } |
840 | if (s->statement_type() == Statement::RULESET) |
841 | { |
842 | return expression()->exclude(str: "rule" ); |
843 | } |
844 | if (s->statement_type() == Statement::SUPPORTS) |
845 | { |
846 | return expression()->exclude(str: "supports" ); |
847 | } |
848 | if (AtRuleObj dir = Cast<AtRule>(ptr: s)) |
849 | { |
850 | if (dir->is_keyframes()) return expression()->exclude(str: "keyframes" ); |
851 | } |
852 | return false; |
853 | } |
854 | |
855 | ///////////////////////////////////////////////////////////////////////// |
856 | ///////////////////////////////////////////////////////////////////////// |
857 | |
858 | Parameter::Parameter(SourceSpan pstate, sass::string n, ExpressionObj def, bool rest) |
859 | : AST_Node(pstate), name_(n), default_value_(def), is_rest_parameter_(rest) |
860 | { } |
861 | Parameter::Parameter(const Parameter* ptr) |
862 | : AST_Node(ptr), |
863 | name_(ptr->name_), |
864 | default_value_(ptr->default_value_), |
865 | is_rest_parameter_(ptr->is_rest_parameter_) |
866 | { } |
867 | |
868 | ///////////////////////////////////////////////////////////////////////// |
869 | ///////////////////////////////////////////////////////////////////////// |
870 | |
871 | Parameters::Parameters(SourceSpan pstate) |
872 | : AST_Node(pstate), |
873 | Vectorized<Parameter_Obj>(), |
874 | has_optional_parameters_(false), |
875 | has_rest_parameter_(false) |
876 | { } |
877 | Parameters::Parameters(const Parameters* ptr) |
878 | : AST_Node(ptr), |
879 | Vectorized<Parameter_Obj>(*ptr), |
880 | has_optional_parameters_(ptr->has_optional_parameters_), |
881 | has_rest_parameter_(ptr->has_rest_parameter_) |
882 | { } |
883 | |
884 | void Parameters::adjust_after_pushing(Parameter_Obj p) |
885 | { |
886 | if (p->default_value()) { |
887 | if (has_rest_parameter()) { |
888 | coreError(msg: "optional parameters may not be combined with variable-length parameters" , pstate: p->pstate()); |
889 | } |
890 | has_optional_parameters(has_optional_parameters__: true); |
891 | } |
892 | else if (p->is_rest_parameter()) { |
893 | if (has_rest_parameter()) { |
894 | coreError(msg: "functions and mixins cannot have more than one variable-length parameter" , pstate: p->pstate()); |
895 | } |
896 | has_rest_parameter(has_rest_parameter__: true); |
897 | } |
898 | else { |
899 | if (has_rest_parameter()) { |
900 | coreError(msg: "required parameters must precede variable-length parameters" , pstate: p->pstate()); |
901 | } |
902 | if (has_optional_parameters()) { |
903 | coreError(msg: "required parameters must precede optional parameters" , pstate: p->pstate()); |
904 | } |
905 | } |
906 | } |
907 | |
908 | ///////////////////////////////////////////////////////////////////////// |
909 | ///////////////////////////////////////////////////////////////////////// |
910 | |
911 | // If you forget to add a class here you will get |
912 | // undefined reference to `vtable for Sass::Class' |
913 | |
914 | IMPLEMENT_AST_OPERATORS(StyleRule); |
915 | IMPLEMENT_AST_OPERATORS(MediaRule); |
916 | IMPLEMENT_AST_OPERATORS(CssMediaRule); |
917 | IMPLEMENT_AST_OPERATORS(CssMediaQuery); |
918 | IMPLEMENT_AST_OPERATORS(Import); |
919 | IMPLEMENT_AST_OPERATORS(Import_Stub); |
920 | IMPLEMENT_AST_OPERATORS(AtRule); |
921 | IMPLEMENT_AST_OPERATORS(AtRootRule); |
922 | IMPLEMENT_AST_OPERATORS(WhileRule); |
923 | IMPLEMENT_AST_OPERATORS(EachRule); |
924 | IMPLEMENT_AST_OPERATORS(ForRule); |
925 | IMPLEMENT_AST_OPERATORS(If); |
926 | IMPLEMENT_AST_OPERATORS(Mixin_Call); |
927 | IMPLEMENT_AST_OPERATORS(ExtendRule); |
928 | IMPLEMENT_AST_OPERATORS(Media_Query); |
929 | IMPLEMENT_AST_OPERATORS(Media_Query_Expression); |
930 | IMPLEMENT_AST_OPERATORS(DebugRule); |
931 | IMPLEMENT_AST_OPERATORS(ErrorRule); |
932 | IMPLEMENT_AST_OPERATORS(WarningRule); |
933 | IMPLEMENT_AST_OPERATORS(Assignment); |
934 | IMPLEMENT_AST_OPERATORS(Return); |
935 | IMPLEMENT_AST_OPERATORS(At_Root_Query); |
936 | IMPLEMENT_AST_OPERATORS(Comment); |
937 | IMPLEMENT_AST_OPERATORS(Parameters); |
938 | IMPLEMENT_AST_OPERATORS(Parameter); |
939 | IMPLEMENT_AST_OPERATORS(Arguments); |
940 | IMPLEMENT_AST_OPERATORS(Argument); |
941 | IMPLEMENT_AST_OPERATORS(Unary_Expression); |
942 | IMPLEMENT_AST_OPERATORS(Block); |
943 | IMPLEMENT_AST_OPERATORS(Content); |
944 | IMPLEMENT_AST_OPERATORS(Trace); |
945 | IMPLEMENT_AST_OPERATORS(Keyframe_Rule); |
946 | IMPLEMENT_AST_OPERATORS(Bubble); |
947 | IMPLEMENT_AST_OPERATORS(Definition); |
948 | IMPLEMENT_AST_OPERATORS(Declaration); |
949 | |
950 | ///////////////////////////////////////////////////////////////////////// |
951 | ///////////////////////////////////////////////////////////////////////// |
952 | |
953 | } |
954 | |