sassc 1.7.1 → 1.8.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/ext/libsass/.gitignore +10 -6
  4. data/ext/libsass/.travis.yml +4 -1
  5. data/ext/libsass/GNUmakefile.am +88 -0
  6. data/ext/libsass/Makefile +157 -76
  7. data/ext/libsass/Makefile.conf +47 -0
  8. data/ext/libsass/Readme.md +13 -14
  9. data/ext/libsass/appveyor.yml +25 -41
  10. data/ext/libsass/configure.ac +20 -7
  11. data/ext/libsass/contrib/plugin.cpp +1 -1
  12. data/ext/libsass/include/sass.h +15 -0
  13. data/ext/libsass/{sass.h → include/sass/base.h} +17 -9
  14. data/ext/libsass/{sass_context.h → include/sass/context.h} +3 -1
  15. data/ext/libsass/{sass_functions.h → include/sass/functions.h} +4 -4
  16. data/ext/libsass/{sass_interface.h → include/sass/interface.h} +5 -2
  17. data/ext/libsass/{sass_values.h → include/sass/values.h} +15 -1
  18. data/ext/libsass/{sass_version.h → include/sass/version.h} +0 -0
  19. data/ext/libsass/{sass_version.h.in → include/sass/version.h.in} +0 -0
  20. data/ext/libsass/{sass2scss.h → include/sass2scss.h} +6 -7
  21. data/ext/libsass/m4/m4-ax_cxx_compile_stdcxx_11.m4 +167 -0
  22. data/ext/libsass/script/ci-build-libsass +67 -23
  23. data/ext/libsass/src/GNUmakefile.am +54 -0
  24. data/ext/libsass/src/ast.cpp +2029 -0
  25. data/ext/libsass/{ast.hpp → src/ast.hpp} +832 -660
  26. data/ext/libsass/src/ast_def_macros.hpp +47 -0
  27. data/ext/libsass/src/ast_factory.hpp +93 -0
  28. data/ext/libsass/{ast_fwd_decl.hpp → src/ast_fwd_decl.hpp} +9 -4
  29. data/ext/libsass/{b64 → src/b64}/cencode.h +1 -1
  30. data/ext/libsass/{b64 → src/b64}/encode.h +0 -0
  31. data/ext/libsass/{backtrace.hpp → src/backtrace.hpp} +9 -10
  32. data/ext/libsass/{base64vlq.cpp → src/base64vlq.cpp} +2 -2
  33. data/ext/libsass/{base64vlq.hpp → src/base64vlq.hpp} +1 -2
  34. data/ext/libsass/{bind.cpp → src/bind.cpp} +96 -59
  35. data/ext/libsass/{bind.hpp → src/bind.hpp} +1 -1
  36. data/ext/libsass/src/c99func.c +54 -0
  37. data/ext/libsass/{cencode.c → src/cencode.c} +5 -5
  38. data/ext/libsass/src/color_maps.cpp +643 -0
  39. data/ext/libsass/src/color_maps.hpp +333 -0
  40. data/ext/libsass/{constants.cpp → src/constants.cpp} +10 -1
  41. data/ext/libsass/{constants.hpp → src/constants.hpp} +7 -0
  42. data/ext/libsass/{context.cpp → src/context.cpp} +152 -122
  43. data/ext/libsass/src/context.hpp +150 -0
  44. data/ext/libsass/{cssize.cpp → src/cssize.cpp} +123 -109
  45. data/ext/libsass/{cssize.hpp → src/cssize.hpp} +9 -13
  46. data/ext/libsass/{debug.hpp → src/debug.hpp} +9 -9
  47. data/ext/libsass/src/debugger.hpp +683 -0
  48. data/ext/libsass/{emitter.cpp → src/emitter.cpp} +13 -13
  49. data/ext/libsass/{emitter.hpp → src/emitter.hpp} +10 -11
  50. data/ext/libsass/src/environment.cpp +184 -0
  51. data/ext/libsass/src/environment.hpp +92 -0
  52. data/ext/libsass/src/error_handling.cpp +46 -0
  53. data/ext/libsass/src/error_handling.hpp +34 -0
  54. data/ext/libsass/src/eval.cpp +1462 -0
  55. data/ext/libsass/src/eval.hpp +107 -0
  56. data/ext/libsass/src/expand.cpp +653 -0
  57. data/ext/libsass/{expand.hpp → src/expand.hpp} +17 -16
  58. data/ext/libsass/{extend.cpp → src/extend.cpp} +198 -139
  59. data/ext/libsass/{extend.hpp → src/extend.hpp} +7 -8
  60. data/ext/libsass/{file.cpp → src/file.cpp} +103 -57
  61. data/ext/libsass/{file.hpp → src/file.hpp} +23 -14
  62. data/ext/libsass/{functions.cpp → src/functions.cpp} +642 -333
  63. data/ext/libsass/{functions.hpp → src/functions.hpp} +17 -4
  64. data/ext/libsass/{inspect.cpp → src/inspect.cpp} +147 -260
  65. data/ext/libsass/{inspect.hpp → src/inspect.hpp} +7 -7
  66. data/ext/libsass/{json.cpp → src/json.cpp} +33 -43
  67. data/ext/libsass/{json.hpp → src/json.hpp} +1 -1
  68. data/ext/libsass/{kwd_arg_macros.hpp → src/kwd_arg_macros.hpp} +0 -0
  69. data/ext/libsass/{lexer.cpp → src/lexer.cpp} +28 -0
  70. data/ext/libsass/{lexer.hpp → src/lexer.hpp} +25 -10
  71. data/ext/libsass/{listize.cpp → src/listize.cpp} +17 -13
  72. data/ext/libsass/{listize.hpp → src/listize.hpp} +0 -2
  73. data/ext/libsass/{mapping.hpp → src/mapping.hpp} +0 -0
  74. data/ext/libsass/src/memory_manager.cpp +76 -0
  75. data/ext/libsass/src/memory_manager.hpp +48 -0
  76. data/ext/libsass/{node.cpp → src/node.cpp} +89 -18
  77. data/ext/libsass/{node.hpp → src/node.hpp} +5 -6
  78. data/ext/libsass/{operation.hpp → src/operation.hpp} +18 -12
  79. data/ext/libsass/{output.cpp → src/output.cpp} +47 -55
  80. data/ext/libsass/{output.hpp → src/output.hpp} +5 -4
  81. data/ext/libsass/src/parser.cpp +2529 -0
  82. data/ext/libsass/{parser.hpp → src/parser.hpp} +84 -60
  83. data/ext/libsass/{paths.hpp → src/paths.hpp} +10 -13
  84. data/ext/libsass/{plugins.cpp → src/plugins.cpp} +14 -17
  85. data/ext/libsass/{plugins.hpp → src/plugins.hpp} +10 -11
  86. data/ext/libsass/{position.cpp → src/position.cpp} +5 -6
  87. data/ext/libsass/{position.hpp → src/position.hpp} +19 -22
  88. data/ext/libsass/{prelexer.cpp → src/prelexer.cpp} +401 -53
  89. data/ext/libsass/{prelexer.hpp → src/prelexer.hpp} +50 -10
  90. data/ext/libsass/{remove_placeholders.cpp → src/remove_placeholders.cpp} +12 -16
  91. data/ext/libsass/{remove_placeholders.hpp → src/remove_placeholders.hpp} +1 -7
  92. data/ext/libsass/{sass.cpp → src/sass.cpp} +3 -5
  93. data/ext/libsass/{sass2scss.cpp → src/sass2scss.cpp} +51 -46
  94. data/ext/libsass/{sass_context.cpp → src/sass_context.cpp} +114 -112
  95. data/ext/libsass/{sass_functions.cpp → src/sass_functions.cpp} +11 -18
  96. data/ext/libsass/{sass_interface.cpp → src/sass_interface.cpp} +44 -81
  97. data/ext/libsass/{sass_util.cpp → src/sass_util.cpp} +26 -8
  98. data/ext/libsass/{sass_util.hpp → src/sass_util.hpp} +14 -18
  99. data/ext/libsass/{sass_values.cpp → src/sass_values.cpp} +91 -20
  100. data/ext/libsass/{source_map.cpp → src/source_map.cpp} +13 -13
  101. data/ext/libsass/{source_map.hpp → src/source_map.hpp} +9 -9
  102. data/ext/libsass/{subset_map.hpp → src/subset_map.hpp} +29 -31
  103. data/ext/libsass/{support → src/support}/libsass.pc.in +0 -0
  104. data/ext/libsass/src/to_c.cpp +73 -0
  105. data/ext/libsass/src/to_c.hpp +41 -0
  106. data/ext/libsass/src/to_string.cpp +47 -0
  107. data/ext/libsass/{to_string.hpp → src/to_string.hpp} +9 -7
  108. data/ext/libsass/src/to_value.cpp +109 -0
  109. data/ext/libsass/src/to_value.hpp +50 -0
  110. data/ext/libsass/{units.cpp → src/units.cpp} +56 -51
  111. data/ext/libsass/{units.hpp → src/units.hpp} +8 -9
  112. data/ext/libsass/{utf8.h → src/utf8.h} +0 -0
  113. data/ext/libsass/{utf8 → src/utf8}/checked.h +0 -0
  114. data/ext/libsass/{utf8 → src/utf8}/core.h +12 -12
  115. data/ext/libsass/{utf8 → src/utf8}/unchecked.h +0 -0
  116. data/ext/libsass/{utf8_string.cpp → src/utf8_string.cpp} +0 -0
  117. data/ext/libsass/{utf8_string.hpp → src/utf8_string.hpp} +6 -6
  118. data/ext/libsass/{util.cpp → src/util.cpp} +144 -86
  119. data/ext/libsass/src/util.hpp +59 -0
  120. data/ext/libsass/src/values.cpp +137 -0
  121. data/ext/libsass/src/values.hpp +12 -0
  122. data/ext/libsass/test/test_node.cpp +33 -33
  123. data/ext/libsass/test/test_paths.cpp +5 -6
  124. data/ext/libsass/test/test_selector_difference.cpp +4 -5
  125. data/ext/libsass/test/test_specificity.cpp +4 -5
  126. data/ext/libsass/test/test_subset_map.cpp +91 -91
  127. data/ext/libsass/test/test_superselector.cpp +11 -11
  128. data/ext/libsass/test/test_unification.cpp +4 -4
  129. data/ext/libsass/win/libsass.targets +101 -0
  130. data/ext/libsass/win/libsass.vcxproj +45 -127
  131. data/ext/libsass/win/libsass.vcxproj.filters +303 -0
  132. data/lib/sassc/import_handler.rb +1 -1
  133. data/lib/sassc/native/native_functions_api.rb +3 -3
  134. data/lib/sassc/version.rb +1 -1
  135. data/test/custom_importer_test.rb +1 -4
  136. data/test/functions_test.rb +3 -2
  137. data/test/native_test.rb +4 -3
  138. metadata +117 -110
  139. data/ext/libsass/Makefile.am +0 -146
  140. data/ext/libsass/ast.cpp +0 -945
  141. data/ext/libsass/ast_def_macros.hpp +0 -21
  142. data/ext/libsass/ast_factory.hpp +0 -92
  143. data/ext/libsass/color_names.hpp +0 -327
  144. data/ext/libsass/context.hpp +0 -157
  145. data/ext/libsass/contextualize.cpp +0 -148
  146. data/ext/libsass/contextualize.hpp +0 -46
  147. data/ext/libsass/contextualize_eval.cpp +0 -93
  148. data/ext/libsass/contextualize_eval.hpp +0 -44
  149. data/ext/libsass/debugger.hpp +0 -558
  150. data/ext/libsass/environment.hpp +0 -163
  151. data/ext/libsass/error_handling.cpp +0 -35
  152. data/ext/libsass/error_handling.hpp +0 -32
  153. data/ext/libsass/eval.cpp +0 -1392
  154. data/ext/libsass/eval.hpp +0 -88
  155. data/ext/libsass/expand.cpp +0 -575
  156. data/ext/libsass/memory_manager.hpp +0 -57
  157. data/ext/libsass/parser.cpp +0 -2403
  158. data/ext/libsass/posix/getopt.c +0 -562
  159. data/ext/libsass/posix/getopt.h +0 -95
  160. data/ext/libsass/to_c.cpp +0 -61
  161. data/ext/libsass/to_c.hpp +0 -44
  162. data/ext/libsass/to_string.cpp +0 -34
  163. data/ext/libsass/util.hpp +0 -54
  164. data/ext/libsass/win/libsass.filters +0 -312
@@ -0,0 +1,107 @@
1
+ #ifndef SASS_EVAL_H
2
+ #define SASS_EVAL_H
3
+
4
+ #include "context.hpp"
5
+ #include "listize.hpp"
6
+ #include "operation.hpp"
7
+
8
+ namespace Sass {
9
+
10
+ class Expand;
11
+ class Context;
12
+ class Listize;
13
+
14
+ class Eval : public Operation_CRTP<Expression*, Eval> {
15
+
16
+ private:
17
+ Expression* fallback_impl(AST_Node* n);
18
+
19
+ public:
20
+ Expand& exp;
21
+ Context& ctx;
22
+ Listize listize;
23
+ Eval(Expand& exp);
24
+ virtual ~Eval();
25
+
26
+ Env* environment();
27
+ Context& context();
28
+ Selector_List* selector();
29
+ Backtrace* backtrace();
30
+
31
+ using Operation<Expression*>::operator();
32
+
33
+ // for evaluating function bodies
34
+ Expression* operator()(Block*);
35
+ Expression* operator()(Assignment*);
36
+ Expression* operator()(If*);
37
+ Expression* operator()(For*);
38
+ Expression* operator()(Each*);
39
+ Expression* operator()(While*);
40
+ Expression* operator()(Return*);
41
+ Expression* operator()(Warning*);
42
+ Expression* operator()(Error*);
43
+ Expression* operator()(Debug*);
44
+
45
+ Expression* operator()(List*);
46
+ Expression* operator()(Map*);
47
+ Expression* operator()(Binary_Expression*);
48
+ Expression* operator()(Unary_Expression*);
49
+ Expression* operator()(Function_Call*);
50
+ Expression* operator()(Function_Call_Schema*);
51
+ Expression* operator()(Variable*);
52
+ Expression* operator()(Textual*);
53
+ Expression* operator()(Number*);
54
+ Expression* operator()(Boolean*);
55
+ Expression* operator()(String_Schema*);
56
+ Expression* operator()(String_Quoted*);
57
+ Expression* operator()(String_Constant*);
58
+ // Expression* operator()(Selector_List*);
59
+ Expression* operator()(Media_Query*);
60
+ Expression* operator()(Media_Query_Expression*);
61
+ Expression* operator()(At_Root_Expression*);
62
+ Expression* operator()(Supports_Operator*);
63
+ Expression* operator()(Supports_Negation*);
64
+ Expression* operator()(Supports_Declaration*);
65
+ Expression* operator()(Supports_Interpolation*);
66
+ Expression* operator()(Null*);
67
+ Expression* operator()(Argument*);
68
+ Expression* operator()(Arguments*);
69
+ Expression* operator()(Comment*);
70
+
71
+ // these will return selectors
72
+ Selector_List* operator()(Selector_List*);
73
+ Selector_List* operator()(Complex_Selector*);
74
+ Attribute_Selector* operator()(Attribute_Selector*);
75
+ // they don't have any specific implementatio (yet)
76
+ Type_Selector* operator()(Type_Selector* s) { return s; };
77
+ Pseudo_Selector* operator()(Pseudo_Selector* s) { return s; };
78
+ Wrapped_Selector* operator()(Wrapped_Selector* s) { return s; };
79
+ Selector_Qualifier* operator()(Selector_Qualifier* s) { return s; };
80
+ Selector_Placeholder* operator()(Selector_Placeholder* s) { return s; };
81
+ // actual evaluated selectors
82
+ Selector_List* operator()(Selector_Schema*);
83
+ Expression* operator()(Parent_Selector*);
84
+
85
+ template <typename U>
86
+ Expression* fallback(U x) { return fallback_impl(x); }
87
+
88
+ // -- only need to define two comparisons, and the rest can be implemented in terms of them
89
+ static bool eq(Expression*, Expression*);
90
+ static bool lt(Expression*, Expression*);
91
+ // -- arithmetic on the combinations that matter
92
+ static Value* op_numbers(Memory_Manager&, enum Sass_OP, const Number&, const Number&, bool compressed = false, int precision = 5);
93
+ static Value* op_number_color(Memory_Manager&, enum Sass_OP, const Number&, const Color&, bool compressed = false, int precision = 5);
94
+ static Value* op_color_number(Memory_Manager&, enum Sass_OP, const Color&, const Number&, bool compressed = false, int precision = 5);
95
+ static Value* op_colors(Memory_Manager&, enum Sass_OP, const Color&, const Color&, bool compressed = false, int precision = 5);
96
+ static Value* op_strings(Memory_Manager&, enum Sass_OP, Value&, Value&, bool compressed = false, int precision = 5);
97
+
98
+ private:
99
+ std::string interpolation(Expression* s, bool into_quotes = false);
100
+
101
+ };
102
+
103
+ Expression* cval_to_astnode(Memory_Manager& mem, union Sass_Value* v, Context& ctx, Backtrace* backtrace, ParserState pstate = ParserState("[AST]"));
104
+
105
+ }
106
+
107
+ #endif
@@ -0,0 +1,653 @@
1
+ #ifdef _MSC_VER
2
+ #pragma warning(disable : 4503)
3
+ #endif
4
+
5
+ #include <iostream>
6
+ #include <typeinfo>
7
+
8
+ #include "expand.hpp"
9
+ #include "bind.hpp"
10
+ #include "eval.hpp"
11
+ #include "to_string.hpp"
12
+ #include "backtrace.hpp"
13
+ #include "context.hpp"
14
+ #include "parser.hpp"
15
+
16
+ namespace Sass {
17
+
18
+ Expand::Expand(Context& ctx, Env* env, Backtrace* bt)
19
+ : ctx(ctx),
20
+ eval(Eval(*this)),
21
+ env_stack(std::vector<Env*>()),
22
+ block_stack(std::vector<Block*>()),
23
+ property_stack(std::vector<String*>()),
24
+ selector_stack(std::vector<Selector_List*>()),
25
+ backtrace_stack(std::vector<Backtrace*>()),
26
+ in_keyframes(false)
27
+ {
28
+ env_stack.push_back(0);
29
+ env_stack.push_back(env);
30
+ block_stack.push_back(0);
31
+ property_stack.push_back(0);
32
+ selector_stack.push_back(0);
33
+ backtrace_stack.push_back(0);
34
+ backtrace_stack.push_back(bt);
35
+ }
36
+
37
+ Context& Expand::context()
38
+ {
39
+ return ctx;
40
+ }
41
+
42
+ Env* Expand::environment()
43
+ {
44
+ if (env_stack.size() > 0)
45
+ return env_stack.back();
46
+ return 0;
47
+ }
48
+
49
+ Selector_List* Expand::selector()
50
+ {
51
+ if (selector_stack.size() > 0)
52
+ return selector_stack.back();
53
+ return 0;
54
+ }
55
+
56
+ Backtrace* Expand::backtrace()
57
+ {
58
+ if (backtrace_stack.size() > 0)
59
+ return backtrace_stack.back();
60
+ return 0;
61
+ }
62
+
63
+ // blocks create new variable scopes
64
+ Statement* Expand::operator()(Block* b)
65
+ {
66
+ // create new local environment
67
+ // set the current env as parent
68
+ Env env(environment());
69
+ // copy the block object (add items later)
70
+ Block* bb = SASS_MEMORY_NEW(ctx.mem, Block,
71
+ b->pstate(),
72
+ b->length(),
73
+ b->is_root());
74
+ // setup block and env stack
75
+ this->block_stack.push_back(bb);
76
+ this->env_stack.push_back(&env);
77
+ // operate on block
78
+ this->append_block(b);
79
+ // revert block and env stack
80
+ this->block_stack.pop_back();
81
+ this->env_stack.pop_back();
82
+ // return copy
83
+ return bb;
84
+ }
85
+
86
+ Statement* Expand::operator()(Ruleset* r)
87
+ {
88
+ // reset when leaving scope
89
+
90
+ if (in_keyframes) {
91
+ Keyframe_Rule* k = SASS_MEMORY_NEW(ctx.mem, Keyframe_Rule, r->pstate(), r->block()->perform(this)->block());
92
+ if (r->selector()) {
93
+ selector_stack.push_back(0);
94
+ k->selector(static_cast<Selector_List*>(r->selector()->perform(&eval)));
95
+ selector_stack.pop_back();
96
+ }
97
+ return k;
98
+ }
99
+
100
+ // do some special checks for the base level rules
101
+ if (r->is_root()) {
102
+ if (Selector_List* selector_list = dynamic_cast<Selector_List*>(r->selector())) {
103
+ for (Complex_Selector* complex_selector : selector_list->elements()) {
104
+ Complex_Selector* tail = complex_selector;
105
+ while (tail) {
106
+ if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
107
+ if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
108
+ To_String to_string(&ctx); std::string sel_str(complex_selector->perform(&to_string));
109
+ error("Base-level rules cannot contain the parent-selector-referencing character '&'.", header->pstate(), backtrace());
110
+ }
111
+ tail = tail->tail();
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ Expression* ex = r->selector()->perform(&eval);
118
+ Selector_List* sel = dynamic_cast<Selector_List*>(ex);
119
+ if (sel == 0) throw std::runtime_error("Expanded null selector");
120
+
121
+ selector_stack.push_back(sel);
122
+ Block* blk = r->block()->perform(this)->block();
123
+ Ruleset* rr = SASS_MEMORY_NEW(ctx.mem, Ruleset,
124
+ r->pstate(),
125
+ sel,
126
+ blk);
127
+ selector_stack.pop_back();
128
+ rr->tabs(r->tabs());
129
+
130
+ return rr;
131
+ }
132
+
133
+ Statement* Expand::operator()(Propset* p)
134
+ {
135
+ property_stack.push_back(p->property_fragment());
136
+ Block* expanded_block = p->block()->perform(this)->block();
137
+
138
+ for (size_t i = 0, L = expanded_block->length(); i < L; ++i) {
139
+ Statement* stm = (*expanded_block)[i];
140
+ if (Declaration* dec = static_cast<Declaration*>(stm)) {
141
+ String_Schema* combined_prop = SASS_MEMORY_NEW(ctx.mem, String_Schema, p->pstate());
142
+ if (!property_stack.empty()) {
143
+ *combined_prop << property_stack.back()->perform(&eval)
144
+ << SASS_MEMORY_NEW(ctx.mem, String_Quoted,
145
+ p->pstate(), "-")
146
+ << dec->property(); // TODO: eval the prop into a string constant
147
+ }
148
+ else {
149
+ *combined_prop << dec->property();
150
+ }
151
+ dec->property(combined_prop);
152
+ *block_stack.back() << dec;
153
+ }
154
+ else if (typeid(*stm) == typeid(Comment)) {
155
+ // drop comments in propsets
156
+ }
157
+ else {
158
+ error("contents of namespaced properties must result in style declarations only", stm->pstate(), backtrace());
159
+ }
160
+ }
161
+
162
+ property_stack.pop_back();
163
+
164
+ return 0;
165
+ }
166
+
167
+ Statement* Expand::operator()(Supports_Block* f)
168
+ {
169
+ Expression* condition = f->condition()->perform(&eval);
170
+ Supports_Block* ff = SASS_MEMORY_NEW(ctx.mem, Supports_Block,
171
+ f->pstate(),
172
+ static_cast<Supports_Condition*>(condition),
173
+ f->block()->perform(this)->block());
174
+ return ff;
175
+ }
176
+
177
+ Statement* Expand::operator()(Media_Block* m)
178
+ {
179
+ To_String to_string(&ctx);
180
+ Expression* mq = m->media_queries()->perform(&eval);
181
+ mq = Parser::from_c_str(mq->perform(&to_string).c_str(), ctx, mq->pstate()).parse_media_queries();
182
+ Media_Block* mm = SASS_MEMORY_NEW(ctx.mem, Media_Block,
183
+ m->pstate(),
184
+ static_cast<List*>(mq),
185
+ m->block()->perform(this)->block(),
186
+ 0);
187
+ mm->tabs(m->tabs());
188
+ return mm;
189
+ }
190
+
191
+ Statement* Expand::operator()(At_Root_Block* a)
192
+ {
193
+ Block* ab = a->block();
194
+ // if (ab) ab->is_root(true);
195
+ Expression* ae = a->expression();
196
+ if (ae) ae = ae->perform(&eval);
197
+ else ae = SASS_MEMORY_NEW(ctx.mem, At_Root_Expression, a->pstate());
198
+ Block* bb = ab ? ab->perform(this)->block() : 0;
199
+ At_Root_Block* aa = SASS_MEMORY_NEW(ctx.mem, At_Root_Block,
200
+ a->pstate(),
201
+ bb,
202
+ static_cast<At_Root_Expression*>(ae));
203
+ // aa->block()->is_root(true);
204
+ return aa;
205
+ }
206
+
207
+ Statement* Expand::operator()(At_Rule* a)
208
+ {
209
+ LOCAL_FLAG(in_keyframes, a->is_keyframes());
210
+ Block* ab = a->block();
211
+ Selector* as = a->selector();
212
+ Expression* av = a->value();
213
+ selector_stack.push_back(0);
214
+ if (av) av = av->perform(&eval);
215
+ if (as) as = dynamic_cast<Selector*>(as->perform(&eval));
216
+ selector_stack.pop_back();
217
+ Block* bb = ab ? ab->perform(this)->block() : 0;
218
+ At_Rule* aa = SASS_MEMORY_NEW(ctx.mem, At_Rule,
219
+ a->pstate(),
220
+ a->keyword(),
221
+ as,
222
+ bb,
223
+ av);
224
+ return aa;
225
+ }
226
+
227
+ Statement* Expand::operator()(Declaration* d)
228
+ {
229
+ String* old_p = d->property();
230
+ String* new_p = static_cast<String*>(old_p->perform(&eval));
231
+ Expression* value = d->value()->perform(&eval);
232
+ if (!value || (value->is_invisible() && !d->is_important())) return 0;
233
+ Declaration* decl = SASS_MEMORY_NEW(ctx.mem, Declaration,
234
+ d->pstate(),
235
+ new_p,
236
+ value,
237
+ d->is_important());
238
+ decl->tabs(d->tabs());
239
+ return decl;
240
+ }
241
+
242
+ Statement* Expand::operator()(Assignment* a)
243
+ {
244
+ Env* env = environment();
245
+ std::string var(a->variable());
246
+ if (a->is_global()) {
247
+ if (a->is_default()) {
248
+ if (env->has_global(var)) {
249
+ Expression* e = dynamic_cast<Expression*>(env->get_global(var));
250
+ if (!e || e->concrete_type() == Expression::NULL_VAL) {
251
+ env->set_global(var, a->value()->perform(&eval));
252
+ }
253
+ }
254
+ else {
255
+ env->set_global(var, a->value()->perform(&eval));
256
+ }
257
+ }
258
+ else {
259
+ env->set_global(var, a->value()->perform(&eval));
260
+ }
261
+ }
262
+ else if (a->is_default()) {
263
+ if (env->has_lexical(var)) {
264
+ auto cur = env;
265
+ while (cur && cur->is_lexical()) {
266
+ if (cur->has_local(var)) {
267
+ if (AST_Node* node = cur->get_local(var)) {
268
+ Expression* e = dynamic_cast<Expression*>(node);
269
+ if (!e || e->concrete_type() == Expression::NULL_VAL) {
270
+ cur->set_local(var, a->value()->perform(&eval));
271
+ }
272
+ }
273
+ else {
274
+ throw std::runtime_error("Env not in sync");
275
+ }
276
+ return 0;
277
+ }
278
+ cur = cur->parent();
279
+ }
280
+ throw std::runtime_error("Env not in sync");
281
+ }
282
+ else if (env->has_global(var)) {
283
+ if (AST_Node* node = env->get_global(var)) {
284
+ Expression* e = dynamic_cast<Expression*>(node);
285
+ if (!e || e->concrete_type() == Expression::NULL_VAL) {
286
+ env->set_global(var, a->value()->perform(&eval));
287
+ }
288
+ }
289
+ }
290
+ else if (env->is_lexical()) {
291
+ env->set_local(var, a->value()->perform(&eval));
292
+ }
293
+ else {
294
+ env->set_local(var, a->value()->perform(&eval));
295
+ }
296
+ }
297
+ else {
298
+ env->set_lexical(var, a->value()->perform(&eval));
299
+ }
300
+ return 0;
301
+ }
302
+
303
+ Statement* Expand::operator()(Import* imp)
304
+ {
305
+ Import* result = SASS_MEMORY_NEW(ctx.mem, Import, imp->pstate());
306
+ if (imp->media_queries()) {
307
+ Expression* ex = imp->media_queries()->perform(&eval);
308
+ result->media_queries(dynamic_cast<List*>(ex));
309
+ }
310
+ for ( size_t i = 0, S = imp->urls().size(); i < S; ++i) {
311
+ result->urls().push_back(imp->urls()[i]->perform(&eval));
312
+ }
313
+ return result;
314
+ }
315
+
316
+ Statement* Expand::operator()(Import_Stub* i)
317
+ {
318
+ append_block(ctx.style_sheets[i->file_name()]);
319
+ return 0;
320
+ }
321
+
322
+ Statement* Expand::operator()(Warning* w)
323
+ {
324
+ // eval handles this too, because warnings may occur in functions
325
+ w->perform(&eval);
326
+ return 0;
327
+ }
328
+
329
+ Statement* Expand::operator()(Error* e)
330
+ {
331
+ // eval handles this too, because errors may occur in functions
332
+ e->perform(&eval);
333
+ return 0;
334
+ }
335
+
336
+ Statement* Expand::operator()(Debug* d)
337
+ {
338
+ // eval handles this too, because warnings may occur in functions
339
+ d->perform(&eval);
340
+ return 0;
341
+ }
342
+
343
+ Statement* Expand::operator()(Comment* c)
344
+ {
345
+ // TODO: eval the text, once we're parsing/storing it as a String_Schema
346
+ return SASS_MEMORY_NEW(ctx.mem, Comment, c->pstate(), static_cast<String*>(c->text()->perform(&eval)), c->is_important());
347
+ }
348
+
349
+ Statement* Expand::operator()(If* i)
350
+ {
351
+ if (*i->predicate()->perform(&eval)) {
352
+ append_block(i->block());
353
+ }
354
+ else {
355
+ Block* alt = i->alternative();
356
+ if (alt) append_block(alt);
357
+ }
358
+ return 0;
359
+ }
360
+
361
+ // For does not create a new env scope
362
+ // But iteration vars are reset afterwards
363
+ Statement* Expand::operator()(For* f)
364
+ {
365
+ std::string variable(f->variable());
366
+ Expression* low = f->lower_bound()->perform(&eval);
367
+ if (low->concrete_type() != Expression::NUMBER) {
368
+ error("lower bound of `@for` directive must be numeric", low->pstate(), backtrace());
369
+ }
370
+ Expression* high = f->upper_bound()->perform(&eval);
371
+ if (high->concrete_type() != Expression::NUMBER) {
372
+ error("upper bound of `@for` directive must be numeric", high->pstate(), backtrace());
373
+ }
374
+ Number* sass_start = static_cast<Number*>(low);
375
+ Number* sass_end = static_cast<Number*>(high);
376
+ // check if units are valid for sequence
377
+ if (sass_start->unit() != sass_end->unit()) {
378
+ std::stringstream msg; msg << "Incompatible units: '"
379
+ << sass_start->unit() << "' and '"
380
+ << sass_end->unit() << "'.";
381
+ error(msg.str(), low->pstate(), backtrace());
382
+ }
383
+ double start = sass_start->value();
384
+ double end = sass_end->value();
385
+ // only create iterator once in this environment
386
+ Env* env = environment();
387
+ Number* it = SASS_MEMORY_NEW(env->mem, Number, low->pstate(), start, sass_end->unit());
388
+ AST_Node* old_var = env->has_local(variable) ? env->get_local(variable) : 0;
389
+ env->set_local(variable, it);
390
+ Block* body = f->block();
391
+ if (start < end) {
392
+ if (f->is_inclusive()) ++end;
393
+ for (double i = start;
394
+ i < end;
395
+ ++i) {
396
+ it->value(i);
397
+ env->set_local(variable, it);
398
+ append_block(body);
399
+ }
400
+ } else {
401
+ if (f->is_inclusive()) --end;
402
+ for (double i = start;
403
+ i > end;
404
+ --i) {
405
+ it->value(i);
406
+ env->set_local(variable, it);
407
+ append_block(body);
408
+ }
409
+ }
410
+ // restore original environment
411
+ if (!old_var) env->del_local(variable);
412
+ else env->set_local(variable, old_var);
413
+ return 0;
414
+ }
415
+
416
+ // Eval does not create a new env scope
417
+ // But iteration vars are reset afterwards
418
+ Statement* Expand::operator()(Each* e)
419
+ {
420
+ std::vector<std::string> variables(e->variables());
421
+ Expression* expr = e->list()->perform(&eval);
422
+ List* list = 0;
423
+ Map* map = 0;
424
+ if (expr->concrete_type() == Expression::MAP) {
425
+ map = static_cast<Map*>(expr);
426
+ }
427
+ else if (expr->concrete_type() != Expression::LIST) {
428
+ list = SASS_MEMORY_NEW(ctx.mem, List, expr->pstate(), 1, SASS_COMMA);
429
+ *list << expr;
430
+ }
431
+ else {
432
+ list = static_cast<List*>(expr);
433
+ }
434
+ // remember variables and then reset them
435
+ Env* env = environment();
436
+ std::vector<AST_Node*> old_vars(variables.size());
437
+ for (size_t i = 0, L = variables.size(); i < L; ++i) {
438
+ old_vars[i] = env->has_local(variables[i]) ? env->get_local(variables[i]) : 0;
439
+ env->set_local(variables[i], 0);
440
+ }
441
+ Block* body = e->block();
442
+
443
+ if (map) {
444
+ for (auto key : map->keys()) {
445
+ Expression* k = key->perform(&eval);
446
+ Expression* v = map->at(key)->perform(&eval);
447
+
448
+ if (variables.size() == 1) {
449
+ List* variable = SASS_MEMORY_NEW(ctx.mem, List, map->pstate(), 2, SASS_SPACE);
450
+ *variable << k;
451
+ *variable << v;
452
+ env->set_local(variables[0], variable);
453
+ } else {
454
+ env->set_local(variables[0], k);
455
+ env->set_local(variables[1], v);
456
+ }
457
+ append_block(body);
458
+ }
459
+ }
460
+ else {
461
+ bool arglist = list->is_arglist();
462
+ for (size_t i = 0, L = list->length(); i < L; ++i) {
463
+ Expression* e = (*list)[i];
464
+ // unwrap value if the expression is an argument
465
+ if (Argument* arg = dynamic_cast<Argument*>(e)) e = arg->value();
466
+ // check if we got passed a list of args (investigate)
467
+ if (List* scalars = dynamic_cast<List*>(e)) {
468
+ if (variables.size() == 1) {
469
+ Expression* var = scalars;
470
+ if (arglist) var = (*scalars)[0];
471
+ env->set_local(variables[0], var);
472
+ } else {
473
+ for (size_t j = 0, K = variables.size(); j < K; ++j) {
474
+ Expression* res = j >= scalars->length()
475
+ ? SASS_MEMORY_NEW(ctx.mem, Null, expr->pstate())
476
+ : (*scalars)[j]->perform(&eval);
477
+ env->set_local(variables[j], res);
478
+ }
479
+ }
480
+ } else {
481
+ if (variables.size() > 0) {
482
+ env->set_local(variables[0], e);
483
+ for (size_t j = 1, K = variables.size(); j < K; ++j) {
484
+ Expression* res = SASS_MEMORY_NEW(ctx.mem, Null, expr->pstate());
485
+ env->set_local(variables[j], res);
486
+ }
487
+ }
488
+ }
489
+ append_block(body);
490
+ }
491
+ }
492
+ // restore original environment
493
+ for (size_t j = 0, K = variables.size(); j < K; ++j) {
494
+ if(!old_vars[j]) env->del_local(variables[j]);
495
+ else env->set_local(variables[j], old_vars[j]);
496
+ }
497
+ return 0;
498
+ }
499
+
500
+ Statement* Expand::operator()(While* w)
501
+ {
502
+ Expression* pred = w->predicate();
503
+ Block* body = w->block();
504
+ while (*pred->perform(&eval)) {
505
+ append_block(body);
506
+ }
507
+ return 0;
508
+ }
509
+
510
+ Statement* Expand::operator()(Return* r)
511
+ {
512
+ error("@return may only be used within a function", r->pstate(), backtrace());
513
+ return 0;
514
+ }
515
+
516
+ Statement* Expand::operator()(Extension* e)
517
+ {
518
+ To_String to_string(&ctx);
519
+ Selector_List* extender = dynamic_cast<Selector_List*>(selector());
520
+ if (!extender) return 0;
521
+ selector_stack.push_back(0);
522
+
523
+ if (Selector_List* selector_list = dynamic_cast<Selector_List*>(e->selector())) {
524
+ for (Complex_Selector* complex_selector : selector_list->elements()) {
525
+ Complex_Selector* tail = complex_selector;
526
+ while (tail) {
527
+ if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
528
+ if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
529
+ To_String to_string(&ctx); std::string sel_str(complex_selector->perform(&to_string));
530
+ error("Can't extend " + sel_str + ": can't extend parent selectors", header->pstate(), backtrace());
531
+ }
532
+ tail = tail->tail();
533
+ }
534
+ }
535
+ }
536
+
537
+ Selector_List* contextualized = dynamic_cast<Selector_List*>(e->selector()->perform(&eval));
538
+ if (contextualized == NULL) return 0;
539
+ for (auto complex_sel : contextualized->elements()) {
540
+ Complex_Selector* c = complex_sel;
541
+ if (!c->head() || c->tail()) {
542
+ To_String to_string(&ctx); std::string sel_str(contextualized->perform(&to_string));
543
+ error("Can't extend " + sel_str + ": can't extend nested selectors", c->pstate(), backtrace());
544
+ }
545
+ Compound_Selector* placeholder = c->head();
546
+ placeholder->is_optional(e->selector()->is_optional());
547
+ for (size_t i = 0, L = extender->length(); i < L; ++i) {
548
+ Complex_Selector* sel = (*extender)[i];
549
+ if (!(sel->head() && sel->head()->length() > 0 &&
550
+ dynamic_cast<Parent_Selector*>((*sel->head())[0])))
551
+ {
552
+ Compound_Selector* hh = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, (*extender)[i]->pstate());
553
+ hh->media_block((*extender)[i]->media_block());
554
+ Complex_Selector* ssel = SASS_MEMORY_NEW(ctx.mem, Complex_Selector, (*extender)[i]->pstate());
555
+ ssel->media_block((*extender)[i]->media_block());
556
+ if (sel->has_line_feed()) ssel->has_line_feed(true);
557
+ Parent_Selector* ps = SASS_MEMORY_NEW(ctx.mem, Parent_Selector, (*extender)[i]->pstate());
558
+ ps->media_block((*extender)[i]->media_block());
559
+ *hh << ps;
560
+ ssel->tail(sel);
561
+ ssel->head(hh);
562
+ sel = ssel;
563
+ }
564
+ // if (c->has_line_feed()) sel->has_line_feed(true);
565
+ ctx.subset_map.put(placeholder->to_str_vec(), std::make_pair(sel, placeholder));
566
+ }
567
+ }
568
+
569
+ selector_stack.pop_back();
570
+
571
+ return 0;
572
+ }
573
+
574
+ Statement* Expand::operator()(Definition* d)
575
+ {
576
+ Env* env = environment();
577
+ Definition* dd = SASS_MEMORY_NEW(ctx.mem, Definition, *d);
578
+ env->local_frame()[d->name() +
579
+ (d->type() == Definition::MIXIN ? "[m]" : "[f]")] = dd;
580
+ // set the static link so we can have lexical scoping
581
+ dd->environment(env);
582
+ return 0;
583
+ }
584
+
585
+ Statement* Expand::operator()(Mixin_Call* c)
586
+ {
587
+ Env* env = environment();
588
+ std::string full_name(c->name() + "[m]");
589
+ if (!env->has(full_name)) {
590
+ error("no mixin named " + c->name(), c->pstate(), backtrace());
591
+ }
592
+ Definition* def = static_cast<Definition*>((*env)[full_name]);
593
+ Block* body = def->block();
594
+ Parameters* params = def->parameters();
595
+
596
+ if (c->block() && c->name() != "@content" && !body->has_content()) {
597
+ error("Mixin \"" + c->name() + "\" does not accept a content block.", c->pstate(), backtrace());
598
+ }
599
+ Arguments* args = static_cast<Arguments*>(c->arguments()
600
+ ->perform(&eval));
601
+ Backtrace new_bt(backtrace(), c->pstate(), ", in mixin `" + c->name() + "`");
602
+ backtrace_stack.push_back(&new_bt);
603
+ Env new_env(def->environment());
604
+ env_stack.push_back(&new_env);
605
+ if (c->block()) {
606
+ // represent mixin content blocks as thunks/closures
607
+ Definition* thunk = SASS_MEMORY_NEW(ctx.mem, Definition,
608
+ c->pstate(),
609
+ "@content",
610
+ SASS_MEMORY_NEW(ctx.mem, Parameters, c->pstate()),
611
+ c->block(),
612
+ Definition::MIXIN);
613
+ thunk->environment(env);
614
+ new_env.local_frame()["@content[m]"] = thunk;
615
+ }
616
+ bind("mixin " + c->name(), params, args, ctx, &new_env, &eval);
617
+ append_block(body);
618
+ backtrace_stack.pop_back();
619
+ env_stack.pop_back();
620
+ return 0;
621
+ }
622
+
623
+ Statement* Expand::operator()(Content* c)
624
+ {
625
+ Env* env = environment();
626
+ // convert @content directives into mixin calls to the underlying thunk
627
+ if (!env->has("@content[m]")) return 0;
628
+ Mixin_Call* call = SASS_MEMORY_NEW(ctx.mem, Mixin_Call,
629
+ c->pstate(),
630
+ "@content",
631
+ SASS_MEMORY_NEW(ctx.mem, Arguments, c->pstate()));
632
+ return call->perform(this);
633
+ }
634
+
635
+ // produce an error if something is not implemented
636
+ inline Statement* Expand::fallback_impl(AST_Node* n)
637
+ {
638
+ std::string err =std:: string("`Expand` doesn't handle ") + typeid(*n).name();
639
+ String_Quoted* msg = SASS_MEMORY_NEW(ctx.mem, String_Quoted, ParserState("[WARN]"), err);
640
+ error("unknown internal error; please contact the LibSass maintainers", n->pstate(), backtrace());
641
+ return SASS_MEMORY_NEW(ctx.mem, Warning, ParserState("[WARN]"), msg);
642
+ }
643
+
644
+ // process and add to last block on stack
645
+ inline void Expand::append_block(Block* b)
646
+ {
647
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
648
+ Statement* ith = (*b)[i]->perform(this);
649
+ if (ith) *block_stack.back() << ith;
650
+ }
651
+ }
652
+
653
+ }