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
@@ -1,163 +0,0 @@
1
- #ifndef SASS_ENVIRONMENT_H
2
- #define SASS_ENVIRONMENT_H
3
-
4
- #include <map>
5
- #include <string>
6
- #include <iostream>
7
-
8
- #include "ast_fwd_decl.hpp"
9
- #include "ast_def_macros.hpp"
10
- #include "memory_manager.hpp"
11
-
12
- namespace Sass {
13
- using std::string;
14
- using std::map;
15
- using std::cerr;
16
- using std::endl;
17
-
18
- template <typename T>
19
- class Environment {
20
- // TODO: test with unordered_map
21
- map<string, T> local_frame_;
22
- ADD_PROPERTY(Environment*, parent);
23
-
24
- public:
25
- Memory_Manager<AST_Node> mem;
26
- Environment() : local_frame_(map<string, T>()), parent_(0) { }
27
-
28
- // link parent to create a stack
29
- void link(Environment& env) { parent_ = &env; }
30
- void link(Environment* env) { parent_ = env; }
31
-
32
- // this is used to find the global frame
33
- // which is the second last on the stack
34
- bool is_lexical() const
35
- {
36
- return !! parent_ && parent_->parent_;
37
- }
38
-
39
- // only match the real root scope
40
- // there is still a parent around
41
- // not sure what it is actually use for
42
- // I guess we store functions etc. there
43
- bool is_root_scope() const
44
- {
45
- return parent_ && ! parent_->parent_;
46
- }
47
-
48
- // scope operates on the current frame
49
-
50
- map<string, T>& local_frame() {
51
- return local_frame_;
52
- }
53
-
54
- bool has_local(const string& key) const
55
- { return local_frame_.count(key); }
56
-
57
- T& get_local(const string& key)
58
- { return local_frame_[key]; }
59
-
60
- void set_local(const string& key, T val)
61
- { local_frame_[key] = val; }
62
-
63
- void del_local(const string& key)
64
- { local_frame_.erase(key); }
65
-
66
-
67
- // global operates on the global frame
68
- // which is the second last on the stack
69
-
70
- Environment* global_env()
71
- {
72
- Environment* cur = this;
73
- while (cur->is_lexical()) {
74
- cur = cur->parent_;
75
- }
76
- return cur;
77
- }
78
-
79
- bool has_global(const string& key)
80
- { return global_env()->has(key); }
81
-
82
- T& get_global(const string& key)
83
- { return (*global_env())[key]; }
84
-
85
- void set_global(const string& key, T val)
86
- { global_env()->local_frame_[key] = val; }
87
-
88
- void del_global(const string& key)
89
- { global_env()->local_frame_.erase(key); }
90
-
91
- // see if we have a lexical variable
92
- // move down the stack but stop before we
93
- // reach the global frame (is not included)
94
- bool has_lexical(const string& key) const
95
- {
96
- auto cur = this;
97
- while (cur->is_lexical()) {
98
- if (cur->has_local(key)) return true;
99
- cur = cur->parent_;
100
- }
101
- return false;
102
- }
103
-
104
- // see if we have a lexical we could update
105
- // either update already existing lexical value
106
- // or if flag is set, we create one if no lexical found
107
- void set_lexical(const string& key, T val)
108
- {
109
- auto cur = this;
110
- while (cur->is_lexical()) {
111
- if (cur->has_local(key)) {
112
- cur->set_local(key, val);
113
- return;
114
- }
115
- cur = cur->parent_;
116
- }
117
- set_local(key, val);
118
- }
119
-
120
- // look on the full stack for key
121
- // include all scopes available
122
- bool has(const string& key) const
123
- {
124
- auto cur = this;
125
- while (cur) {
126
- if (cur->has_local(key)) {
127
- return true;
128
- }
129
- cur = cur->parent_;
130
- }
131
- return false;
132
- }
133
-
134
- // use array access for getter and setter functions
135
- T& operator[](const string& key)
136
- {
137
- auto cur = this;
138
- while (cur) {
139
- if (cur->has_local(key)) {
140
- return cur->get_local(key);
141
- }
142
- cur = cur->parent_;
143
- }
144
- return get_local(key);
145
- }
146
-
147
- #ifdef DEBUG
148
- void print()
149
- {
150
- for (typename map<string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
151
- cerr << i->first << endl;
152
- }
153
- if (parent_) {
154
- cerr << "---" << endl;
155
- parent_->print();
156
- }
157
- }
158
- #endif
159
-
160
- };
161
- }
162
-
163
- #endif
@@ -1,35 +0,0 @@
1
- #include "prelexer.hpp"
2
- #include "backtrace.hpp"
3
- #include "error_handling.hpp"
4
-
5
- namespace Sass {
6
-
7
- Sass_Error::Sass_Error(Type type, ParserState pstate, string message)
8
- : type(type), pstate(pstate), message(message)
9
- { }
10
-
11
- void warn(string msg, ParserState pstate)
12
- {
13
- cerr << "Warning: " << msg<< endl;
14
- }
15
-
16
- void warn(string msg, ParserState pstate, Backtrace* bt)
17
- {
18
- Backtrace top(bt, pstate, "");
19
- msg += top.to_string();
20
- warn(msg, pstate);
21
- }
22
-
23
- void error(string msg, ParserState pstate)
24
- {
25
- throw Sass_Error(Sass_Error::syntax, pstate, msg);
26
- }
27
-
28
- void error(string msg, ParserState pstate, Backtrace* bt)
29
- {
30
- Backtrace top(bt, pstate, "");
31
- msg += "\n" + top.to_string();
32
- error(msg, pstate);
33
- }
34
-
35
- }
@@ -1,32 +0,0 @@
1
- #ifndef SASS_ERROR_HANDLING_H
2
- #define SASS_ERROR_HANDLING_H
3
-
4
- #include <string>
5
-
6
- #include "position.hpp"
7
-
8
- namespace Sass {
9
- using namespace std;
10
-
11
- struct Backtrace;
12
-
13
- struct Sass_Error {
14
- enum Type { read, write, syntax, evaluation };
15
-
16
- Type type;
17
- ParserState pstate;
18
- string message;
19
-
20
- Sass_Error(Type type, ParserState pstate, string message);
21
-
22
- };
23
-
24
- void warn(string msg, ParserState pstate);
25
- void warn(string msg, ParserState pstate, Backtrace* bt);
26
-
27
- void error(string msg, ParserState pstate);
28
- void error(string msg, ParserState pstate, Backtrace* bt);
29
-
30
- }
31
-
32
- #endif
@@ -1,1392 +0,0 @@
1
- #include <cstdlib>
2
- #include <cmath>
3
- #include <iostream>
4
- #include <sstream>
5
- #include <iomanip>
6
- #include <typeinfo>
7
-
8
- #include "file.hpp"
9
- #include "eval.hpp"
10
- #include "ast.hpp"
11
- #include "bind.hpp"
12
- #include "util.hpp"
13
- #include "to_string.hpp"
14
- #include "inspect.hpp"
15
- #include "to_c.hpp"
16
- #include "context.hpp"
17
- #include "backtrace.hpp"
18
- #include "prelexer.hpp"
19
- #include "parser.hpp"
20
-
21
- namespace Sass {
22
- using namespace std;
23
-
24
- inline double add(double x, double y) { return x + y; }
25
- inline double sub(double x, double y) { return x - y; }
26
- inline double mul(double x, double y) { return x * y; }
27
- inline double div(double x, double y) { return x / y; } // x/0 checked by caller
28
- typedef double (*bop)(double, double);
29
- bop ops[Binary_Expression::NUM_OPS] = {
30
- 0, 0, // and, or
31
- 0, 0, 0, 0, 0, 0, // eq, neq, gt, gte, lt, lte
32
- add, sub, mul, div, fmod
33
- };
34
-
35
- Eval::Eval(Context& ctx, Contextualize* contextualize, Listize* listize, Env* env, Backtrace* bt)
36
- : ctx(ctx), contextualize(contextualize), listize(listize), env(env), backtrace(bt) { }
37
- Eval::~Eval() { }
38
-
39
- Eval* Eval::with(Env* e, Backtrace* bt) // for setting the env before eval'ing an expression
40
- {
41
- contextualize = contextualize->with(0, e, bt);
42
- env = e;
43
- backtrace = bt;
44
- return this;
45
- }
46
-
47
- Eval* Eval::with(Selector* c, Env* e, Backtrace* bt, Selector* p, Selector* ex) // for setting the env before eval'ing an expression
48
- {
49
- contextualize = contextualize->with(c, e, bt, p, ex);
50
- env = e;
51
- backtrace = bt;
52
- return this;
53
- }
54
-
55
- Expression* Eval::operator()(Block* b)
56
- {
57
- Expression* val = 0;
58
- for (size_t i = 0, L = b->length(); i < L; ++i) {
59
- val = (*b)[i]->perform(this);
60
- if (val) return val;
61
- }
62
- return val;
63
- }
64
-
65
- Expression* Eval::operator()(Assignment* a)
66
- {
67
- string var(a->variable());
68
- if (a->is_global()) {
69
- if (a->is_default()) {
70
- if (env->has_global(var)) {
71
- Expression* e = dynamic_cast<Expression*>(env->get_global(var));
72
- if (!e || e->concrete_type() == Expression::NULL_VAL) {
73
- env->set_global(var, a->value()->perform(this));
74
- }
75
- }
76
- else {
77
- env->set_global(var, a->value()->perform(this));
78
- }
79
- }
80
- else {
81
- env->set_global(var, a->value()->perform(this));
82
- }
83
- }
84
- else if (a->is_default()) {
85
- if (env->has_lexical(var)) {
86
- auto cur = env;
87
- while (cur && cur->is_lexical()) {
88
- if (cur->has_local(var)) {
89
- if (AST_Node* node = cur->get_local(var)) {
90
- Expression* e = dynamic_cast<Expression*>(node);
91
- if (!e || e->concrete_type() == Expression::NULL_VAL) {
92
- cur->set_local(var, a->value()->perform(this));
93
- }
94
- }
95
- else {
96
- throw runtime_error("Env not in sync");
97
- }
98
- return 0;
99
- }
100
- cur = cur->parent();
101
- }
102
- throw runtime_error("Env not in sync");
103
- }
104
- else if (env->has_global(var)) {
105
- if (AST_Node* node = env->get_global(var)) {
106
- Expression* e = dynamic_cast<Expression*>(node);
107
- if (!e || e->concrete_type() == Expression::NULL_VAL) {
108
- env->set_global(var, a->value()->perform(this));
109
- }
110
- }
111
- }
112
- else if (env->is_lexical()) {
113
- env->set_local(var, a->value()->perform(this));
114
- }
115
- else {
116
- env->set_local(var, a->value()->perform(this));
117
- }
118
- }
119
- else {
120
- env->set_lexical(var, a->value()->perform(this));
121
- }
122
- return 0;
123
- }
124
-
125
- Expression* Eval::operator()(If* i)
126
- {
127
- if (*i->predicate()->perform(this)) {
128
- return i->consequent()->perform(this);
129
- }
130
- else {
131
- Block* alt = i->alternative();
132
- if (alt) return alt->perform(this);
133
- }
134
- return 0;
135
- }
136
-
137
- // For does not create a new env scope
138
- // But iteration vars are reset afterwards
139
- Expression* Eval::operator()(For* f)
140
- {
141
- string variable(f->variable());
142
- Expression* low = f->lower_bound()->perform(this);
143
- if (low->concrete_type() != Expression::NUMBER) {
144
- error("lower bound of `@for` directive must be numeric", low->pstate());
145
- }
146
- Expression* high = f->upper_bound()->perform(this);
147
- if (high->concrete_type() != Expression::NUMBER) {
148
- error("upper bound of `@for` directive must be numeric", high->pstate());
149
- }
150
- Number* sass_start = static_cast<Number*>(low);
151
- Number* sass_end = static_cast<Number*>(high);
152
- // check if units are valid for sequence
153
- if (sass_start->unit() != sass_end->unit()) {
154
- stringstream msg; msg << "Incompatible units: '"
155
- << sass_start->unit() << "' and '"
156
- << sass_end->unit() << "'.";
157
- error(msg.str(), low->pstate(), backtrace);
158
- }
159
- double start = sass_start->value();
160
- double end = sass_end->value();
161
- // only create iterator once in this environment
162
- Number* it = new (env->mem) Number(low->pstate(), start, sass_end->unit());
163
- AST_Node* old_var = env->has_local(variable) ? env->get_local(variable) : 0;
164
- env->set_local(variable, it);
165
- Block* body = f->block();
166
- Expression* val = 0;
167
- if (start < end) {
168
- if (f->is_inclusive()) ++end;
169
- for (double i = start;
170
- i < end;
171
- ++i) {
172
- it->value(i);
173
- env->set_local(variable, it);
174
- val = body->perform(this);
175
- if (val) break;
176
- }
177
- } else {
178
- if (f->is_inclusive()) --end;
179
- for (double i = start;
180
- i > end;
181
- --i) {
182
- it->value(i);
183
- env->set_local(variable, it);
184
- val = body->perform(this);
185
- if (val) break;
186
- }
187
- }
188
- // restore original environment
189
- if (!old_var) env->del_local(variable);
190
- else env->set_local(variable, old_var);
191
- return val;
192
- }
193
-
194
- // Eval does not create a new env scope
195
- // But iteration vars are reset afterwards
196
- Expression* Eval::operator()(Each* e)
197
- {
198
- vector<string> variables(e->variables());
199
- Expression* expr = e->list()->perform(this);
200
- List* list = 0;
201
- Map* map = 0;
202
- if (expr->concrete_type() == Expression::MAP) {
203
- map = static_cast<Map*>(expr);
204
- }
205
- else if (expr->concrete_type() != Expression::LIST) {
206
- list = new (ctx.mem) List(expr->pstate(), 1, List::COMMA);
207
- *list << expr;
208
- }
209
- else {
210
- list = static_cast<List*>(expr);
211
- }
212
- // remember variables and then reset them
213
- vector<AST_Node*> old_vars(variables.size());
214
- for (size_t i = 0, L = variables.size(); i < L; ++i) {
215
- old_vars[i] = env->has_local(variables[i]) ? env->get_local(variables[i]) : 0;
216
- env->set_local(variables[i], 0);
217
- }
218
- Block* body = e->block();
219
- Expression* val = 0;
220
-
221
- if (map) {
222
- for (auto key : map->keys()) {
223
- Expression* value = map->at(key);
224
-
225
- if (variables.size() == 1) {
226
- List* variable = new (ctx.mem) List(map->pstate(), 2, List::SPACE);
227
- *variable << key;
228
- *variable << value;
229
- env->set_local(variables[0], variable);
230
- } else {
231
- env->set_local(variables[0], key);
232
- env->set_local(variables[1], value);
233
- }
234
-
235
- val = body->perform(this);
236
- if (val) break;
237
- }
238
- }
239
- else {
240
- for (size_t i = 0, L = list->length(); i < L; ++i) {
241
- List* variable = 0;
242
- if ((*list)[i]->concrete_type() != Expression::LIST || variables.size() == 1) {
243
- variable = new (ctx.mem) List((*list)[i]->pstate(), 1, List::COMMA);
244
- *variable << (*list)[i];
245
- }
246
- else {
247
- variable = static_cast<List*>((*list)[i]);
248
- }
249
- for (size_t j = 0, K = variables.size(); j < K; ++j) {
250
- if (j < variable->length()) {
251
- env->set_local(variables[j], (*variable)[j]);
252
- }
253
- else {
254
- env->set_local(variables[j], new (ctx.mem) Null(expr->pstate()));
255
- }
256
- val = body->perform(this);
257
- if (val) break;
258
- }
259
- if (val) break;
260
- }
261
- }
262
- // restore original environment
263
- for (size_t j = 0, K = variables.size(); j < K; ++j) {
264
- if(!old_vars[j]) env->del_local(variables[j]);
265
- else env->set_local(variables[j], old_vars[j]);
266
- }
267
- return val;
268
- }
269
-
270
- Expression* Eval::operator()(While* w)
271
- {
272
- Expression* pred = w->predicate();
273
- Block* body = w->block();
274
- while (*pred->perform(this)) {
275
- Expression* val = body->perform(this);
276
- if (val) return val;
277
- }
278
- return 0;
279
- }
280
-
281
- Expression* Eval::operator()(Return* r)
282
- {
283
- return r->value()->perform(this);
284
- }
285
-
286
- Expression* Eval::operator()(Warning* w)
287
- {
288
- Expression* message = w->message()->perform(this);
289
- To_String to_string(&ctx);
290
-
291
- // try to use generic function
292
- if (env->has("@warn[f]")) {
293
-
294
- Definition* def = static_cast<Definition*>((*env)["@warn[f]"]);
295
- // Block* body = def->block();
296
- // Native_Function func = def->native_function();
297
- Sass_Function_Entry c_function = def->c_function();
298
- Sass_Function_Fn c_func = sass_function_get_function(c_function);
299
-
300
- To_C to_c;
301
- union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
302
- sass_list_set_value(c_args, 0, message->perform(&to_c));
303
- Sass_Value* c_val = c_func(c_args, c_function, ctx.c_options);
304
- sass_delete_value(c_args);
305
- sass_delete_value(c_val);
306
- return 0;
307
-
308
- }
309
-
310
- string result(unquote(message->perform(&to_string)));
311
- Backtrace top(backtrace, w->pstate(), "");
312
- cerr << "WARNING: " << result;
313
- cerr << top.to_string(true);
314
- cerr << endl << endl;
315
- return 0;
316
- }
317
-
318
- Expression* Eval::operator()(Error* e)
319
- {
320
- Expression* message = e->message()->perform(this);
321
- To_String to_string(&ctx);
322
-
323
- // try to use generic function
324
- if (env->has("@error[f]")) {
325
-
326
- Definition* def = static_cast<Definition*>((*env)["@error[f]"]);
327
- // Block* body = def->block();
328
- // Native_Function func = def->native_function();
329
- Sass_Function_Entry c_function = def->c_function();
330
- Sass_Function_Fn c_func = sass_function_get_function(c_function);
331
-
332
- To_C to_c;
333
- union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
334
- sass_list_set_value(c_args, 0, message->perform(&to_c));
335
- Sass_Value* c_val = c_func(c_args, c_function, ctx.c_options);
336
- sass_delete_value(c_args);
337
- sass_delete_value(c_val);
338
- return 0;
339
-
340
- }
341
-
342
- string result(unquote(message->perform(&to_string)));
343
- error(result, e->pstate());
344
- return 0;
345
- }
346
-
347
- Expression* Eval::operator()(Debug* d)
348
- {
349
- Expression* message = d->value()->perform(this);
350
- To_String to_string(&ctx);
351
-
352
- // try to use generic function
353
- if (env->has("@debug[f]")) {
354
-
355
- Definition* def = static_cast<Definition*>((*env)["@debug[f]"]);
356
- // Block* body = def->block();
357
- // Native_Function func = def->native_function();
358
- Sass_Function_Entry c_function = def->c_function();
359
- Sass_Function_Fn c_func = sass_function_get_function(c_function);
360
-
361
- To_C to_c;
362
- union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
363
- sass_list_set_value(c_args, 0, message->perform(&to_c));
364
- Sass_Value* c_val = c_func(c_args, c_function, ctx.c_options);
365
- sass_delete_value(c_args);
366
- sass_delete_value(c_val);
367
- return 0;
368
-
369
- }
370
-
371
- string cwd(ctx.get_cwd());
372
- string result(unquote(message->perform(&to_string)));
373
- string rel_path(Sass::File::resolve_relative_path(d->pstate().path, cwd, cwd));
374
- cerr << rel_path << ":" << d->pstate().line << ":" << " DEBUG: " << result;
375
- cerr << endl;
376
- return 0;
377
- }
378
-
379
- Expression* Eval::operator()(List* l)
380
- {
381
- if (l->is_expanded()) return l;
382
- List* ll = new (ctx.mem) List(l->pstate(),
383
- l->length(),
384
- l->separator(),
385
- l->is_arglist());
386
- for (size_t i = 0, L = l->length(); i < L; ++i) {
387
- *ll << (*l)[i]->perform(this);
388
- }
389
- ll->is_expanded(true);
390
- return ll;
391
- }
392
-
393
- Expression* Eval::operator()(Map* m)
394
- {
395
- if (m->is_expanded()) return m;
396
-
397
- // make sure we're not starting with duplicate keys.
398
- // the duplicate key state will have been set in the parser phase.
399
- if (m->has_duplicate_key()) {
400
- To_String to_string(&ctx);
401
- error("Duplicate key \"" + m->get_duplicate_key()->perform(&to_string) + "\" in map " + m->perform(&to_string) + ".", m->pstate());
402
- }
403
-
404
- Map* mm = new (ctx.mem) Map(m->pstate(),
405
- m->length());
406
- for (auto key : m->keys()) {
407
- *mm << std::make_pair(key->perform(this), m->at(key)->perform(this));;
408
- }
409
-
410
- // check the evaluated keys aren't duplicates.
411
- if (mm->has_duplicate_key()) {
412
- To_String to_string(&ctx);
413
- error("Duplicate key \"" + mm->get_duplicate_key()->perform(&to_string) + "\" in map " + mm->perform(&to_string) + ".", mm->pstate());
414
- }
415
-
416
- mm->is_expanded(true);
417
- return mm;
418
- }
419
-
420
- // -- only need to define two comparisons, and the rest can be implemented in terms of them
421
- bool eq(Expression*, Expression*, Context&, Eval*);
422
- bool lt(Expression*, Expression*, Context&);
423
- // -- arithmetic on the combinations that matter
424
- Expression* op_numbers(Context&, Binary_Expression*, Expression*, Expression*);
425
- Expression* op_number_color(Context&, Binary_Expression::Type, Expression*, Expression*);
426
- Expression* op_color_number(Context&, Binary_Expression::Type, Expression*, Expression*);
427
- Expression* op_colors(Context&, Binary_Expression::Type, Expression*, Expression*);
428
- Expression* op_strings(Context&, Binary_Expression::Type, Expression*, Expression*);
429
-
430
- Expression* Eval::operator()(Binary_Expression* b)
431
- {
432
- Binary_Expression::Type op_type = b->type();
433
- // don't eval delayed expressions (the '/' when used as a separator)
434
- if (op_type == Binary_Expression::DIV && b->is_delayed()) return b;
435
- // if one of the operands is a '/' then make sure it's evaluated
436
- Expression* lhs = b->left()->perform(this);
437
- lhs->is_delayed(false);
438
- while (typeid(*lhs) == typeid(Binary_Expression)) lhs = lhs->perform(this);
439
-
440
- switch (op_type) {
441
- case Binary_Expression::AND:
442
- return *lhs ? b->right()->perform(this) : lhs;
443
- break;
444
-
445
- case Binary_Expression::OR:
446
- return *lhs ? lhs : b->right()->perform(this);
447
- break;
448
-
449
- default:
450
- break;
451
- }
452
- // not a logical connective, so go ahead and eval the rhs
453
- Expression* rhs = b->right()->perform(this);
454
- // maybe fully evaluate structure
455
- if (op_type == Binary_Expression::EQ ||
456
- op_type == Binary_Expression::NEQ ||
457
- op_type == Binary_Expression::GT ||
458
- op_type == Binary_Expression::GTE ||
459
- op_type == Binary_Expression::LT ||
460
- op_type == Binary_Expression::LTE)
461
- {
462
- rhs->is_expanded(false);
463
- rhs->set_delayed(false);
464
- rhs = rhs->perform(this);
465
- }
466
- else
467
- {
468
- rhs->is_delayed(false);
469
- rhs = rhs->perform(this);
470
- }
471
-
472
- // see if it's a relational expression
473
- switch(op_type) {
474
- case Binary_Expression::EQ: return new (ctx.mem) Boolean(b->pstate(), eq(lhs, rhs, ctx));
475
- case Binary_Expression::NEQ: return new (ctx.mem) Boolean(b->pstate(), !eq(lhs, rhs, ctx));
476
- case Binary_Expression::GT: return new (ctx.mem) Boolean(b->pstate(), !lt(lhs, rhs, ctx) && !eq(lhs, rhs, ctx));
477
- case Binary_Expression::GTE: return new (ctx.mem) Boolean(b->pstate(), !lt(lhs, rhs, ctx));
478
- case Binary_Expression::LT: return new (ctx.mem) Boolean(b->pstate(), lt(lhs, rhs, ctx));
479
- case Binary_Expression::LTE: return new (ctx.mem) Boolean(b->pstate(), lt(lhs, rhs, ctx) || eq(lhs, rhs, ctx));
480
-
481
- default: break;
482
- }
483
-
484
- Expression::Concrete_Type l_type = lhs->concrete_type();
485
- Expression::Concrete_Type r_type = rhs->concrete_type();
486
-
487
- if (l_type == Expression::NUMBER && r_type == Expression::NUMBER) {
488
- return op_numbers(ctx, b, lhs, rhs);
489
- }
490
- if (l_type == Expression::NUMBER && r_type == Expression::COLOR) {
491
- return op_number_color(ctx, op_type, lhs, rhs);
492
- }
493
- if (l_type == Expression::COLOR && r_type == Expression::NUMBER) {
494
- return op_color_number(ctx, op_type, lhs, rhs);
495
- }
496
- if (l_type == Expression::COLOR && r_type == Expression::COLOR) {
497
- return op_colors(ctx, op_type, lhs, rhs);
498
- }
499
-
500
- Expression* ex = op_strings(ctx, op_type, lhs, rhs);
501
- if (String_Constant* str = (String_Constant*) ex)
502
- {
503
- if (str->concrete_type() != Expression::STRING) return ex;
504
- String_Constant* lstr = dynamic_cast<String_Constant*>(lhs);
505
- String_Constant* rstr = dynamic_cast<String_Constant*>(rhs);
506
- if (String_Constant* org = lstr ? lstr : rstr)
507
- { str->quote_mark(org->quote_mark()); }
508
- }
509
- return ex;
510
-
511
- }
512
-
513
- Expression* Eval::operator()(Unary_Expression* u)
514
- {
515
- Expression* operand = u->operand()->perform(this);
516
- if (u->type() == Unary_Expression::NOT) {
517
- Boolean* result = new (ctx.mem) Boolean(u->pstate(), (bool)*operand);
518
- result->value(!result->value());
519
- return result;
520
- }
521
- else if (operand->concrete_type() == Expression::NUMBER) {
522
- Number* result = new (ctx.mem) Number(*static_cast<Number*>(operand));
523
- result->value(u->type() == Unary_Expression::MINUS
524
- ? -result->value()
525
- : result->value());
526
- return result;
527
- }
528
- else {
529
- To_String to_string(&ctx);
530
- // Special cases: +/- variables which evaluate to null ouput just +/-,
531
- // but +/- null itself outputs the string
532
- if (operand->concrete_type() == Expression::NULL_VAL && typeid(*(u->operand())) == typeid(Variable)) {
533
- u->operand(new (ctx.mem) String_Constant(u->pstate(), ""));
534
- }
535
- else u->operand(operand);
536
- String_Constant* result = new (ctx.mem) String_Constant(u->pstate(),
537
- u->perform(&to_string));
538
- return result;
539
- }
540
- // unreachable
541
- return u;
542
- }
543
-
544
- Expression* Eval::operator()(Function_Call* c)
545
- {
546
- if (backtrace->parent != NULL && backtrace->depth() > Constants::MaxCallStack) {
547
- ostringstream stm;
548
- stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
549
- error(stm.str(), c->pstate(), backtrace);
550
- }
551
- string name(Util::normalize_underscores(c->name()));
552
- string full_name(name + "[f]");
553
- Arguments* args = c->arguments();
554
- if (full_name != "if[f]") {
555
- args = static_cast<Arguments*>(args->perform(this));
556
- }
557
-
558
- // try to use generic function
559
- if (!env->has(full_name)) {
560
- if (env->has("*[f]")) {
561
- full_name = "*[f]";
562
- }
563
- }
564
-
565
- // if it doesn't exist, just pass it through as a literal
566
- if (!env->has(full_name)) {
567
- Function_Call* lit = new (ctx.mem) Function_Call(c->pstate(),
568
- c->name(),
569
- args);
570
- To_String to_string(&ctx);
571
- return new (ctx.mem) String_Constant(c->pstate(),
572
- lit->perform(&to_string));
573
- }
574
-
575
- Expression* result = c;
576
- Definition* def = static_cast<Definition*>((*env)[full_name]);
577
- Block* body = def->block();
578
- Native_Function func = def->native_function();
579
- Sass_Function_Entry c_function = def->c_function();
580
-
581
- if (full_name != "if[f]") {
582
- for (size_t i = 0, L = args->length(); i < L; ++i) {
583
- (*args)[i]->value((*args)[i]->value()->perform(this));
584
- }
585
- }
586
-
587
- Parameters* params = def->parameters();
588
- Env new_env;
589
- new_env.link(def->environment());
590
- // bind("function " + c->name(), params, args, ctx, &new_env, this);
591
- // Env* old_env = env;
592
- // env = &new_env;
593
-
594
- // Backtrace here(backtrace, c->path(), c->line(), ", in function `" + c->name() + "`");
595
- // backtrace = &here;
596
-
597
- // if it's user-defined, eval the body
598
- if (body) {
599
-
600
- bind("function " + c->name(), params, args, ctx, &new_env, this);
601
- Env* old_env = env;
602
- env = &new_env;
603
-
604
- Backtrace here(backtrace, c->pstate(), ", in function `" + c->name() + "`");
605
- backtrace = &here;
606
-
607
- result = body->perform(this);
608
- if (!result) {
609
- error(string("function ") + c->name() + " did not return a value", c->pstate());
610
- }
611
- backtrace = here.parent;
612
- env = old_env;
613
- }
614
- // if it's native, invoke the underlying CPP function
615
- else if (func) {
616
-
617
- bind("function " + c->name(), params, args, ctx, &new_env, this);
618
- Env* old_env = env;
619
- env = &new_env;
620
-
621
- Backtrace here(backtrace, c->pstate(), ", in function `" + c->name() + "`");
622
- backtrace = &here;
623
-
624
- result = func(*env, *old_env, ctx, def->signature(), c->pstate(), backtrace);
625
-
626
- backtrace = here.parent;
627
- env = old_env;
628
- }
629
- // else if it's a user-defined c function
630
- else if (c_function) {
631
-
632
- Sass_Function_Fn c_func = sass_function_get_function(c_function);
633
- if (full_name == "*[f]") {
634
- String_Constant *str = new (ctx.mem) String_Constant(c->pstate(), c->name());
635
- Arguments* new_args = new (ctx.mem) Arguments(c->pstate());
636
- *new_args << new (ctx.mem) Argument(c->pstate(), str);
637
- *new_args += args;
638
- args = new_args;
639
- }
640
-
641
- // populates env with default values for params
642
- bind("function " + c->name(), params, args, ctx, &new_env, this);
643
- Env* old_env = env;
644
- env = &new_env;
645
-
646
- Backtrace here(backtrace, c->pstate(), ", in function `" + c->name() + "`");
647
- backtrace = &here;
648
-
649
- To_C to_c;
650
- union Sass_Value* c_args = sass_make_list(env->local_frame().size(), SASS_COMMA);
651
- for(size_t i = 0; i < params[0].length(); i++) {
652
- string key = params[0][i]->name();
653
- AST_Node* node = env->local_frame().at(key);
654
- Expression* arg = static_cast<Expression*>(node);
655
- sass_list_set_value(c_args, i, arg->perform(&to_c));
656
- }
657
- Sass_Value* c_val = c_func(c_args, c_function, ctx.c_options);
658
- if (sass_value_get_tag(c_val) == SASS_ERROR) {
659
- error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), backtrace);
660
- } else if (sass_value_get_tag(c_val) == SASS_WARNING) {
661
- error("warning in C function " + c->name() + ": " + sass_warning_get_message(c_val), c->pstate(), backtrace);
662
- }
663
- result = cval_to_astnode(c_val, ctx, backtrace, c->pstate());
664
-
665
- backtrace = here.parent;
666
- sass_delete_value(c_args);
667
- if (c_val != c_args)
668
- sass_delete_value(c_val);
669
- env = old_env;
670
- }
671
- // else it's an overloaded native function; resolve it
672
- else if (def->is_overload_stub()) {
673
- size_t arity = args->length();
674
- stringstream ss;
675
- ss << full_name << arity;
676
- string resolved_name(ss.str());
677
- if (!env->has(resolved_name)) error("overloaded function `" + string(c->name()) + "` given wrong number of arguments", c->pstate());
678
- Definition* resolved_def = static_cast<Definition*>((*env)[resolved_name]);
679
- params = resolved_def->parameters();
680
- Env newer_env;
681
- newer_env.link(resolved_def->environment());
682
- bind("function " + c->name(), params, args, ctx, &newer_env, this);
683
- Env* old_env = env;
684
- env = &newer_env;
685
-
686
- Backtrace here(backtrace, c->pstate(), ", in function `" + c->name() + "`");
687
- backtrace = &here;
688
-
689
- result = resolved_def->native_function()(*env, *old_env, ctx, resolved_def->signature(), c->pstate(), backtrace);
690
-
691
- backtrace = here.parent;
692
- env = old_env;
693
- }
694
-
695
- // backtrace = here.parent;
696
- // env = old_env;
697
-
698
-
699
- // link back to function definition
700
- // only do this for custom functions
701
- if (result->pstate().file == string::npos)
702
- result->pstate(c->pstate());
703
-
704
- do {
705
- result->is_delayed(result->concrete_type() == Expression::STRING);
706
- result = result->perform(this);
707
- } while (result->concrete_type() == Expression::NONE);
708
- return result;
709
- }
710
-
711
- Expression* Eval::operator()(Function_Call_Schema* s)
712
- {
713
- Expression* evaluated_name = s->name()->perform(this);
714
- Expression* evaluated_args = s->arguments()->perform(this);
715
- String_Schema* ss = new (ctx.mem) String_Schema(s->pstate(), 2);
716
- (*ss) << evaluated_name << evaluated_args;
717
- return ss->perform(this);
718
- }
719
-
720
- Expression* Eval::operator()(Variable* v)
721
- {
722
- To_String to_string(&ctx);
723
- string name(v->name());
724
- Expression* value = 0;
725
- if (env->has(name)) value = static_cast<Expression*>((*env)[name]);
726
- else error("Undefined variable: \"" + v->name() + "\".", v->pstate());
727
- // cerr << "name: " << v->name() << "; type: " << typeid(*value).name() << "; value: " << value->perform(&to_string) << endl;
728
- if (typeid(*value) == typeid(Argument)) value = static_cast<Argument*>(value)->value();
729
-
730
- // behave according to as ruby sass (add leading zero)
731
- if (value->concrete_type() == Expression::NUMBER) {
732
- value = new (ctx.mem) Number(*static_cast<Number*>(value));
733
- static_cast<Number*>(value)->zero(true);
734
- }
735
- else if (value->concrete_type() == Expression::STRING) {
736
- if (auto str = dynamic_cast<String_Quoted*>(value)) {
737
- value = new (ctx.mem) String_Quoted(*str);
738
- } else if (auto str = dynamic_cast<String_Constant*>(value)) {
739
- if (str->quote_mark()) {
740
- value = new (ctx.mem) String_Quoted(str->pstate(), str->perform(&to_string));
741
- } else {
742
- value = new (ctx.mem) String_Constant(str->pstate(), unquote(str->value()));
743
- }
744
- }
745
- }
746
- else if (value->concrete_type() == Expression::LIST) {
747
- value = new (ctx.mem) List(*static_cast<List*>(value));
748
- }
749
- else if (value->concrete_type() == Expression::MAP) {
750
- value = new (ctx.mem) Map(*static_cast<Map*>(value));
751
- }
752
- else if (value->concrete_type() == Expression::BOOLEAN) {
753
- value = new (ctx.mem) Boolean(*static_cast<Boolean*>(value));
754
- }
755
- else if (value->concrete_type() == Expression::COLOR) {
756
- value = new (ctx.mem) Color(*static_cast<Color*>(value));
757
- }
758
- else if (value->concrete_type() == Expression::NULL_VAL) {
759
- value = new (ctx.mem) Null(value->pstate());
760
- }
761
-
762
- // cerr << "\ttype is now: " << typeid(*value).name() << endl << endl;
763
- return value;
764
- }
765
-
766
- Expression* Eval::operator()(Textual* t)
767
- {
768
- using Prelexer::number;
769
- Expression* result = 0;
770
- bool zero = !( t->value().substr(0, 1) == "." ||
771
- t->value().substr(0, 2) == "-." );
772
-
773
- const string& text = t->value();
774
- size_t num_pos = text.find_first_not_of(" \n\r\t");
775
- if (num_pos == string::npos) num_pos = text.length();
776
- size_t unit_pos = text.find_first_not_of("-+0123456789.", num_pos);
777
- if (unit_pos == string::npos) unit_pos = text.length();
778
- const string& num = text.substr(num_pos, unit_pos - num_pos);
779
-
780
- switch (t->type())
781
- {
782
- case Textual::NUMBER:
783
- result = new (ctx.mem) Number(t->pstate(),
784
- sass_atof(num.c_str()),
785
- "",
786
- zero);
787
- break;
788
- case Textual::PERCENTAGE:
789
- result = new (ctx.mem) Number(t->pstate(),
790
- sass_atof(num.c_str()),
791
- "%",
792
- zero);
793
- break;
794
- case Textual::DIMENSION:
795
- result = new (ctx.mem) Number(t->pstate(),
796
- sass_atof(num.c_str()),
797
- Token(number(text.c_str())),
798
- zero);
799
- break;
800
- case Textual::HEX: {
801
- if (t->value().substr(0, 1) != "#") {
802
- result = new (ctx.mem) String_Constant(t->pstate(), t->value());
803
- break;
804
- }
805
- string hext(t->value().substr(1)); // chop off the '#'
806
- if (hext.length() == 6) {
807
- string r(hext.substr(0,2));
808
- string g(hext.substr(2,2));
809
- string b(hext.substr(4,2));
810
- result = new (ctx.mem) Color(t->pstate(),
811
- static_cast<double>(strtol(r.c_str(), NULL, 16)),
812
- static_cast<double>(strtol(g.c_str(), NULL, 16)),
813
- static_cast<double>(strtol(b.c_str(), NULL, 16)),
814
- 1, true,
815
- t->value());
816
- }
817
- else {
818
- result = new (ctx.mem) Color(t->pstate(),
819
- static_cast<double>(strtol(string(2,hext[0]).c_str(), NULL, 16)),
820
- static_cast<double>(strtol(string(2,hext[1]).c_str(), NULL, 16)),
821
- static_cast<double>(strtol(string(2,hext[2]).c_str(), NULL, 16)),
822
- 1, false,
823
- t->value());
824
- }
825
- } break;
826
- }
827
- return result;
828
- }
829
-
830
- Expression* Eval::operator()(Number* n)
831
- {
832
- n->normalize();
833
- // behave according to as ruby sass (add leading zero)
834
- return new (ctx.mem) Number(n->pstate(),
835
- n->value(),
836
- n->unit(),
837
- true);
838
- }
839
-
840
- Expression* Eval::operator()(Boolean* b)
841
- {
842
- return b;
843
- }
844
-
845
- char is_quoted(string str)
846
- {
847
- size_t len = str.length();
848
- if (len < 2) return 0;
849
- if ((str[0] == '"' && str[len-1] == '"') || (str[0] == '\'' && str[len-1] == '\'')) {
850
- return str[0];
851
- }
852
- else {
853
- return 0;
854
- }
855
- }
856
-
857
- string Eval::interpolation(Expression* s) {
858
- if (String_Quoted* str_quoted = dynamic_cast<String_Quoted*>(s)) {
859
- if (str_quoted->quote_mark()) {
860
- if (str_quoted->quote_mark() == '*' || str_quoted->is_delayed()) {
861
- return interpolation(new (ctx.mem) String_Constant(*str_quoted));
862
- } else {
863
- return string_escape(quote(str_quoted->value(), str_quoted->quote_mark()));
864
- }
865
- } else {
866
- return evacuate_escapes(str_quoted->value());
867
- }
868
- } else if (String_Constant* str_constant = dynamic_cast<String_Constant*>(s)) {
869
- string str = str_constant->value();
870
- if (!str_constant->quote_mark()) str = unquote(str);
871
- return evacuate_escapes(str);
872
- } else if (String_Schema* str_schema = dynamic_cast<String_Schema*>(s)) {
873
- string res = "";
874
- for(auto i : str_schema->elements())
875
- res += (interpolation(i));
876
- //ToDo: do this in one step
877
- auto esc = evacuate_escapes(res);
878
- auto unq = unquote(esc);
879
- if (unq == esc) {
880
- return string_to_output(res);
881
- } else {
882
- return evacuate_quotes(unq);
883
- }
884
- } else if (List* list = dynamic_cast<List*>(s)) {
885
- string acc = ""; // ToDo: different output styles
886
- string sep = list->separator() == List::Separator::COMMA ? "," : " ";
887
- if (ctx.output_style != COMPRESSED && sep == ",") sep += " ";
888
- bool initial = false;
889
- for(auto item : list->elements()) {
890
- if (initial) acc += sep;
891
- acc += interpolation(item);
892
- initial = true;
893
- }
894
- return evacuate_quotes(acc);
895
- } else if (Variable* var = dynamic_cast<Variable*>(s)) {
896
- string name(var->name());
897
- if (!env->has(name)) error("Undefined variable: \"" + var->name() + "\".", var->pstate());
898
- Expression* value = static_cast<Expression*>((*env)[name]);
899
- return evacuate_quotes(interpolation(value));
900
- } else if (Binary_Expression* var = dynamic_cast<Binary_Expression*>(s)) {
901
- var->is_delayed(false);
902
- Expression* ex = var->perform(this);
903
- return evacuate_quotes(interpolation(ex));
904
- } else if (Function_Call* var = dynamic_cast<Function_Call*>(s)) {
905
- Expression* ex = var->perform(this);
906
- return evacuate_quotes(interpolation(ex));
907
- } else if (Parent_Selector* var = dynamic_cast<Parent_Selector*>(s)) {
908
- Expression* ex = var->perform(this);
909
- return evacuate_quotes(interpolation(ex));
910
- } else if (Unary_Expression* var = dynamic_cast<Unary_Expression*>(s)) {
911
- Expression* ex = var->perform(this);
912
- return evacuate_quotes(interpolation(ex));
913
- } else if (Selector* var = dynamic_cast<Selector*>(s)) {
914
- Expression* ex = var->perform(this);
915
- return evacuate_quotes(interpolation(ex));
916
- } else {
917
- To_String to_string(&ctx);
918
- // to_string.in_decl_list = true;
919
- return evacuate_quotes(s->perform(&to_string));
920
- }
921
- }
922
-
923
- Expression* Eval::operator()(String_Schema* s)
924
- {
925
- string acc;
926
- for (size_t i = 0, L = s->length(); i < L; ++i) {
927
- // if (String_Quoted* str_quoted = dynamic_cast<String_Quoted*>((*s)[i])) {
928
- // if (!str_quoted->is_delayed()) str_quoted->value(string_eval_escapes(str_quoted->value()));
929
- // }
930
- acc += interpolation((*s)[i]);
931
- }
932
- String_Quoted* str = new (ctx.mem) String_Quoted(s->pstate(), acc);
933
- if (!str->quote_mark()) {
934
- str->value(string_unescape(str->value()));
935
- } else if (str->quote_mark()) {
936
- str->quote_mark('*');
937
- }
938
- str->is_delayed(true);
939
- return str;
940
- }
941
-
942
- Expression* Eval::operator()(String_Constant* s)
943
- {
944
- if (!s->quote_mark() && !s->is_delayed() && ctx.names_to_colors.count(s->value())) {
945
- Color* c = new (ctx.mem) Color(*ctx.names_to_colors[s->value()]);
946
- c->pstate(s->pstate());
947
- c->disp(s->value());
948
- return c;
949
- }
950
- return s;
951
- }
952
-
953
- Expression* Eval::operator()(Feature_Query* q)
954
- {
955
- Feature_Query* qq = new (ctx.mem) Feature_Query(q->pstate(),
956
- q->length());
957
- for (size_t i = 0, L = q->length(); i < L; ++i) {
958
- *qq << static_cast<Feature_Query_Condition*>((*q)[i]->perform(this));
959
- }
960
- return qq;
961
- }
962
-
963
- Expression* Eval::operator()(Feature_Query_Condition* c)
964
- {
965
- String* feature = c->feature();
966
- Expression* value = c->value();
967
- value = (value ? value->perform(this) : 0);
968
- Feature_Query_Condition* cc = new (ctx.mem) Feature_Query_Condition(c->pstate(),
969
- c->length(),
970
- feature,
971
- value,
972
- c->operand(),
973
- c->is_root());
974
- for (size_t i = 0, L = c->length(); i < L; ++i) {
975
- *cc << static_cast<Feature_Query_Condition*>((*c)[i]->perform(this));
976
- }
977
- return cc;
978
- }
979
-
980
- Expression* Eval::operator()(At_Root_Expression* e)
981
- {
982
- Expression* feature = e->feature();
983
- feature = (feature ? feature->perform(this) : 0);
984
- Expression* value = e->value();
985
- value = (value ? value->perform(this) : 0);
986
- Expression* ee = new (ctx.mem) At_Root_Expression(e->pstate(),
987
- static_cast<String*>(feature),
988
- value,
989
- e->is_interpolated());
990
- return ee;
991
- }
992
-
993
- Expression* Eval::operator()(Media_Query* q)
994
- {
995
- To_String to_string(&ctx);
996
- String* t = q->media_type();
997
- t = static_cast<String*>(t ? t->perform(this) : 0);
998
- Media_Query* qq = new (ctx.mem) Media_Query(q->pstate(),
999
- t,
1000
- q->length(),
1001
- q->is_negated(),
1002
- q->is_restricted());
1003
- for (size_t i = 0, L = q->length(); i < L; ++i) {
1004
- *qq << static_cast<Media_Query_Expression*>((*q)[i]->perform(this));
1005
- }
1006
- return qq;
1007
- }
1008
-
1009
- Expression* Eval::operator()(Media_Query_Expression* e)
1010
- {
1011
- Expression* feature = e->feature();
1012
- feature = (feature ? feature->perform(this) : 0);
1013
- if (feature && dynamic_cast<String_Quoted*>(feature)) {
1014
- feature = new (ctx.mem) String_Constant(feature->pstate(),
1015
- dynamic_cast<String_Quoted*>(feature)->value());
1016
- }
1017
- Expression* value = e->value();
1018
- value = (value ? value->perform(this) : 0);
1019
- if (value && dynamic_cast<String_Quoted*>(value)) {
1020
- value = new (ctx.mem) String_Constant(value->pstate(),
1021
- dynamic_cast<String_Quoted*>(value)->value());
1022
- }
1023
- return new (ctx.mem) Media_Query_Expression(e->pstate(),
1024
- feature,
1025
- value,
1026
- e->is_interpolated());
1027
- }
1028
-
1029
- Expression* Eval::operator()(Null* n)
1030
- {
1031
- return n;
1032
- }
1033
-
1034
- Expression* Eval::operator()(Argument* a)
1035
- {
1036
- Expression* val = a->value();
1037
- val->is_delayed(false);
1038
- val = val->perform(this);
1039
- val->is_delayed(false);
1040
-
1041
- bool is_rest_argument = a->is_rest_argument();
1042
- bool is_keyword_argument = a->is_keyword_argument();
1043
-
1044
- if (a->is_rest_argument()) {
1045
- if (val->concrete_type() == Expression::MAP) {
1046
- is_rest_argument = false;
1047
- is_keyword_argument = true;
1048
- }
1049
- else if(val->concrete_type() != Expression::LIST) {
1050
- List* wrapper = new (ctx.mem) List(val->pstate(),
1051
- 0,
1052
- List::COMMA,
1053
- true);
1054
- *wrapper << val;
1055
- val = wrapper;
1056
- }
1057
- }
1058
- return new (ctx.mem) Argument(a->pstate(),
1059
- val,
1060
- a->name(),
1061
- is_rest_argument,
1062
- is_keyword_argument);
1063
- }
1064
-
1065
- Expression* Eval::operator()(Arguments* a)
1066
- {
1067
- Arguments* aa = new (ctx.mem) Arguments(a->pstate());
1068
- for (size_t i = 0, L = a->length(); i < L; ++i) {
1069
- *aa << static_cast<Argument*>((*a)[i]->perform(this));
1070
- }
1071
- return aa;
1072
- }
1073
-
1074
- Expression* Eval::operator()(Comment* c)
1075
- {
1076
- return 0;
1077
- }
1078
-
1079
- Expression* Eval::operator()(Parent_Selector* p)
1080
- {
1081
- // no idea why both calls are needed
1082
- Selector* s = p->perform(contextualize);
1083
- if (!s) s = p->selector()->perform(contextualize);
1084
- // access to parent selector may return 0
1085
- Selector_List* l = static_cast<Selector_List*>(s);
1086
- // some spec tests cause this (might be a valid case!)
1087
- // if (!s) { cerr << "Parent Selector eval error" << endl; }
1088
- if (!s) { l = new (ctx.mem) Selector_List(p->pstate()); }
1089
- return l->perform(listize);
1090
- }
1091
-
1092
- inline Expression* Eval::fallback_impl(AST_Node* n)
1093
- {
1094
- return static_cast<Expression*>(n);
1095
- }
1096
-
1097
- // All the binary helpers.
1098
-
1099
- bool eq(Expression* lhs, Expression* rhs, Context& ctx)
1100
- {
1101
- Expression::Concrete_Type ltype = lhs->concrete_type();
1102
- Expression::Concrete_Type rtype = rhs->concrete_type();
1103
- if (ltype != rtype) return false;
1104
- switch (ltype) {
1105
-
1106
- case Expression::BOOLEAN: {
1107
- return static_cast<Boolean*>(lhs)->value() ==
1108
- static_cast<Boolean*>(rhs)->value();
1109
- } break;
1110
-
1111
- case Expression::NUMBER: {
1112
- return *static_cast<Number*>(lhs) ==
1113
- *static_cast<Number*>(rhs);
1114
- } break;
1115
-
1116
- case Expression::COLOR: {
1117
- Color* l = static_cast<Color*>(lhs);
1118
- Color* r = static_cast<Color*>(rhs);
1119
- return l->r() == r->r() &&
1120
- l->g() == r->g() &&
1121
- l->b() == r->b() &&
1122
- l->a() == r->a();
1123
- } break;
1124
-
1125
- case Expression::STRING: {
1126
- string slhs = static_cast<String_Quoted*>(lhs)->value();
1127
- string srhs = static_cast<String_Quoted*>(rhs)->value();
1128
- return unquote(slhs) == unquote(srhs) &&
1129
- (!(is_quoted(slhs) || is_quoted(srhs)) || slhs[0] == srhs[0]);
1130
- } break;
1131
-
1132
- case Expression::LIST: {
1133
- List* l = static_cast<List*>(lhs);
1134
- List* r = static_cast<List*>(rhs);
1135
- if (l->length() != r->length()) return false;
1136
- if (l->separator() != r->separator()) return false;
1137
- for (size_t i = 0, L = l->length(); i < L; ++i) {
1138
- if (!eq((*l)[i], (*r)[i], ctx)) return false;
1139
- }
1140
- return true;
1141
- } break;
1142
-
1143
- case Expression::MAP: {
1144
- Map* l = static_cast<Map*>(lhs);
1145
- Map* r = static_cast<Map*>(rhs);
1146
- if (l->length() != r->length()) return false;
1147
- for (auto key : l->keys())
1148
- if (!eq(l->at(key), r->at(key), ctx)) return false;
1149
- return true;
1150
- } break;
1151
- case Expression::NULL_VAL: {
1152
- return true;
1153
- } break;
1154
-
1155
- default: break;
1156
- }
1157
- return false;
1158
- }
1159
-
1160
- bool lt(Expression* lhs, Expression* rhs, Context& ctx)
1161
- {
1162
- if (lhs->concrete_type() != Expression::NUMBER ||
1163
- rhs->concrete_type() != Expression::NUMBER)
1164
- error("may only compare numbers", lhs->pstate());
1165
- Number* l = static_cast<Number*>(lhs);
1166
- Number* r = static_cast<Number*>(rhs);
1167
- Number tmp_r(*r);
1168
- tmp_r.normalize(l->find_convertible_unit());
1169
- string l_unit(l->unit());
1170
- string r_unit(tmp_r.unit());
1171
- if (!l_unit.empty() && !r_unit.empty() && l->unit() != tmp_r.unit()) {
1172
- error("cannot compare numbers with incompatible units", l->pstate());
1173
- }
1174
- return l->value() < tmp_r.value();
1175
- }
1176
-
1177
- Expression* op_numbers(Context& ctx, Binary_Expression* b, Expression* lhs, Expression* rhs)
1178
- {
1179
- Number* l = static_cast<Number*>(lhs);
1180
- Number* r = static_cast<Number*>(rhs);
1181
- double lv = l->value();
1182
- double rv = r->value();
1183
- Binary_Expression::Type op = b->type();
1184
- if (op == Binary_Expression::DIV && !rv) {
1185
- return new (ctx.mem) String_Constant(l->pstate(), "Infinity");
1186
- }
1187
- if (op == Binary_Expression::MOD && !rv) {
1188
- error("division by zero", r->pstate());
1189
- }
1190
-
1191
- Number tmp(*r);
1192
- tmp.normalize(l->find_convertible_unit());
1193
- string l_unit(l->unit());
1194
- string r_unit(tmp.unit());
1195
- if (l_unit != r_unit && !l_unit.empty() && !r_unit.empty() &&
1196
- (op == Binary_Expression::ADD || op == Binary_Expression::SUB)) {
1197
- error("Incompatible units: '"+r_unit+"' and '"+l_unit+"'.", l->pstate());
1198
- }
1199
- Number* v = new (ctx.mem) Number(*l);
1200
- v->pstate(b->pstate());
1201
- if (l_unit.empty() && (op == Binary_Expression::ADD || op == Binary_Expression::SUB || op == Binary_Expression::MOD)) {
1202
- v->numerator_units() = r->numerator_units();
1203
- v->denominator_units() = r->denominator_units();
1204
- }
1205
-
1206
- if (op == Binary_Expression::MUL) {
1207
- v->value(ops[op](lv, rv));
1208
- for (size_t i = 0, S = r->numerator_units().size(); i < S; ++i) {
1209
- v->numerator_units().push_back(r->numerator_units()[i]);
1210
- }
1211
- for (size_t i = 0, S = r->denominator_units().size(); i < S; ++i) {
1212
- v->denominator_units().push_back(r->denominator_units()[i]);
1213
- }
1214
- }
1215
- else if (op == Binary_Expression::DIV) {
1216
- v->value(ops[op](lv, rv));
1217
- for (size_t i = 0, S = r->numerator_units().size(); i < S; ++i) {
1218
- v->denominator_units().push_back(r->numerator_units()[i]);
1219
- }
1220
- for (size_t i = 0, S = r->denominator_units().size(); i < S; ++i) {
1221
- v->numerator_units().push_back(r->denominator_units()[i]);
1222
- }
1223
- } else {
1224
- v->value(ops[op](lv, tmp.value()));
1225
- }
1226
- v->normalize();
1227
- return v;
1228
- }
1229
-
1230
- Expression* op_number_color(Context& ctx, Binary_Expression::Type op, Expression* lhs, Expression* rhs)
1231
- {
1232
- Number* l = static_cast<Number*>(lhs);
1233
- Color* r = static_cast<Color*>(rhs);
1234
- // TODO: currently SASS converts colors to standard form when adding to strings;
1235
- // when https://github.com/nex3/sass/issues/363 is added this can be removed to
1236
- // preserve the original value
1237
- r->disp("");
1238
- double lv = l->value();
1239
- switch (op) {
1240
- case Binary_Expression::ADD:
1241
- case Binary_Expression::MUL: {
1242
- return new (ctx.mem) Color(l->pstate(),
1243
- ops[op](lv, r->r()),
1244
- ops[op](lv, r->g()),
1245
- ops[op](lv, r->b()),
1246
- r->a());
1247
- } break;
1248
- case Binary_Expression::SUB:
1249
- case Binary_Expression::DIV: {
1250
- string sep(op == Binary_Expression::SUB ? "-" : "/");
1251
- To_String to_string(&ctx);
1252
- string color(r->sixtuplet() && (ctx.output_style != COMPRESSED) ?
1253
- r->perform(&to_string) :
1254
- Util::normalize_sixtuplet(r->perform(&to_string)));
1255
- return new (ctx.mem) String_Constant(l->pstate(),
1256
- l->perform(&to_string)
1257
- + sep
1258
- + color);
1259
- } break;
1260
- case Binary_Expression::MOD: {
1261
- error("cannot divide a number by a color", r->pstate());
1262
- } break;
1263
- default: break; // caller should ensure that we don't get here
1264
- }
1265
- // unreachable
1266
- return l;
1267
- }
1268
-
1269
- Expression* op_color_number(Context& ctx, Binary_Expression::Type op, Expression* lhs, Expression* rhs)
1270
- {
1271
- Color* l = static_cast<Color*>(lhs);
1272
- Number* r = static_cast<Number*>(rhs);
1273
- double rv = r->value();
1274
- if (op == Binary_Expression::DIV && !rv) error("division by zero", r->pstate());
1275
- return new (ctx.mem) Color(l->pstate(),
1276
- ops[op](l->r(), rv),
1277
- ops[op](l->g(), rv),
1278
- ops[op](l->b(), rv),
1279
- l->a());
1280
- }
1281
-
1282
- Expression* op_colors(Context& ctx, Binary_Expression::Type op, Expression* lhs, Expression* rhs)
1283
- {
1284
- Color* l = static_cast<Color*>(lhs);
1285
- Color* r = static_cast<Color*>(rhs);
1286
- if (l->a() != r->a()) {
1287
- error("alpha channels must be equal when combining colors", r->pstate());
1288
- }
1289
- if ((op == Binary_Expression::DIV || op == Binary_Expression::MOD) &&
1290
- (!r->r() || !r->g() ||!r->b())) {
1291
- error("division by zero", r->pstate());
1292
- }
1293
- return new (ctx.mem) Color(l->pstate(),
1294
- ops[op](l->r(), r->r()),
1295
- ops[op](l->g(), r->g()),
1296
- ops[op](l->b(), r->b()),
1297
- l->a());
1298
- }
1299
-
1300
- Expression* op_strings(Context& ctx, Binary_Expression::Type op, Expression* lhs, Expression*rhs)
1301
- {
1302
- To_String to_string(&ctx);
1303
- Expression::Concrete_Type ltype = lhs->concrete_type();
1304
- Expression::Concrete_Type rtype = rhs->concrete_type();
1305
-
1306
- string lstr(lhs->perform(&to_string));
1307
- string rstr(rhs->perform(&to_string));
1308
-
1309
- bool l_str_quoted = ((Sass::String*)lhs) && ((Sass::String*)lhs)->sass_fix_1291();
1310
- bool r_str_quoted = ((Sass::String*)rhs) && ((Sass::String*)rhs)->sass_fix_1291();
1311
- bool l_str_color = ltype == Expression::STRING && ctx.names_to_colors.count(lstr) && !l_str_quoted;
1312
- bool r_str_color = rtype == Expression::STRING && ctx.names_to_colors.count(rstr) && !r_str_quoted;
1313
-
1314
- if (l_str_color && r_str_color) {
1315
- return op_colors(ctx, op, ctx.names_to_colors[lstr], ctx.names_to_colors[rstr]);
1316
- }
1317
- else if (l_str_color && rtype == Expression::COLOR) {
1318
- return op_colors(ctx, op, ctx.names_to_colors[lstr], rhs);
1319
- }
1320
- else if (l_str_color && rtype == Expression::NUMBER) {
1321
- return op_color_number(ctx, op, ctx.names_to_colors[lstr], rhs);
1322
- }
1323
- else if (ltype == Expression::COLOR && r_str_color) {
1324
- return op_number_color(ctx, op, lhs, ctx.names_to_colors[rstr]);
1325
- }
1326
- else if (ltype == Expression::NUMBER && r_str_color) {
1327
- return op_number_color(ctx, op, lhs, ctx.names_to_colors[rstr]);
1328
- }
1329
- if (op == Binary_Expression::MUL) error("invalid operands for multiplication", lhs->pstate());
1330
- if (op == Binary_Expression::MOD) error("invalid operands for modulo", lhs->pstate());
1331
- string sep;
1332
- switch (op) {
1333
- case Binary_Expression::SUB: sep = "-"; break;
1334
- case Binary_Expression::DIV: sep = "/"; break;
1335
- default: break;
1336
- }
1337
- if (ltype == Expression::NULL_VAL) error("invalid null operation: \"null plus "+quote(unquote(rstr), '"')+"\".", lhs->pstate());
1338
- if (rtype == Expression::NULL_VAL) error("invalid null operation: \""+quote(unquote(lstr), '"')+" plus null\".", lhs->pstate());
1339
- string result((lstr) + sep + (rstr));
1340
- String_Quoted* str = new (ctx.mem) String_Quoted(lhs->pstate(), result);
1341
- str->quote_mark(0);
1342
- return str;
1343
- }
1344
-
1345
- Expression* cval_to_astnode(Sass_Value* v, Context& ctx, Backtrace* backtrace, ParserState pstate)
1346
- {
1347
- using std::strlen;
1348
- using std::strcpy;
1349
- Expression* e = 0;
1350
- switch (sass_value_get_tag(v)) {
1351
- case SASS_BOOLEAN: {
1352
- e = new (ctx.mem) Boolean(pstate, !!sass_boolean_get_value(v));
1353
- } break;
1354
- case SASS_NUMBER: {
1355
- e = new (ctx.mem) Number(pstate, sass_number_get_value(v), sass_number_get_unit(v));
1356
- } break;
1357
- case SASS_COLOR: {
1358
- e = new (ctx.mem) Color(pstate, sass_color_get_r(v), sass_color_get_g(v), sass_color_get_b(v), sass_color_get_a(v));
1359
- } break;
1360
- case SASS_STRING: {
1361
- e = new (ctx.mem) String_Constant(pstate, sass_string_get_value(v));
1362
- } break;
1363
- case SASS_LIST: {
1364
- List* l = new (ctx.mem) List(pstate, sass_list_get_length(v), sass_list_get_separator(v) == SASS_COMMA ? List::COMMA : List::SPACE);
1365
- for (size_t i = 0, L = sass_list_get_length(v); i < L; ++i) {
1366
- *l << cval_to_astnode(sass_list_get_value(v, i), ctx, backtrace, pstate);
1367
- }
1368
- e = l;
1369
- } break;
1370
- case SASS_MAP: {
1371
- Map* m = new (ctx.mem) Map(pstate);
1372
- for (size_t i = 0, L = sass_map_get_length(v); i < L; ++i) {
1373
- *m << std::make_pair(
1374
- cval_to_astnode(sass_map_get_key(v, i), ctx, backtrace, pstate),
1375
- cval_to_astnode(sass_map_get_value(v, i), ctx, backtrace, pstate));
1376
- }
1377
- e = m;
1378
- } break;
1379
- case SASS_NULL: {
1380
- e = new (ctx.mem) Null(pstate);
1381
- } break;
1382
- case SASS_ERROR: {
1383
- error("Error in C function: " + string(sass_error_get_message(v)), pstate, backtrace);
1384
- } break;
1385
- case SASS_WARNING: {
1386
- error("Warning in C function: " + string(sass_warning_get_message(v)), pstate, backtrace);
1387
- } break;
1388
- }
1389
- return e;
1390
- }
1391
-
1392
- }