sassc 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/libsass/.gitignore +6 -0
- data/ext/libsass/.travis.yml +5 -1
- data/ext/libsass/Makefile +12 -3
- data/ext/libsass/Makefile.am +16 -28
- data/ext/libsass/Readme.md +1 -0
- data/ext/libsass/appveyor.yml +1 -2
- data/ext/libsass/ast.cpp +9 -0
- data/ext/libsass/ast.hpp +152 -55
- data/ext/libsass/ast_factory.hpp +2 -0
- data/ext/libsass/ast_fwd_decl.hpp +1 -0
- data/ext/libsass/backtrace.hpp +2 -2
- data/ext/libsass/bind.cpp +15 -13
- data/ext/libsass/configure.ac +17 -5
- data/ext/libsass/constants.cpp +22 -2
- data/ext/libsass/constants.hpp +21 -2
- data/ext/libsass/context.cpp +79 -57
- data/ext/libsass/context.hpp +23 -9
- data/ext/libsass/contextualize.cpp +2 -28
- data/ext/libsass/contextualize.hpp +6 -10
- data/ext/libsass/contextualize_eval.cpp +93 -0
- data/ext/libsass/contextualize_eval.hpp +44 -0
- data/ext/libsass/contrib/plugin.cpp +57 -0
- data/ext/libsass/cssize.cpp +3 -1
- data/ext/libsass/debugger.hpp +242 -83
- data/ext/libsass/emitter.cpp +1 -1
- data/ext/libsass/emitter.hpp +1 -1
- data/ext/libsass/environment.hpp +109 -25
- data/ext/libsass/error_handling.cpp +3 -3
- data/ext/libsass/error_handling.hpp +0 -1
- data/ext/libsass/eval.cpp +145 -61
- data/ext/libsass/eval.hpp +9 -1
- data/ext/libsass/expand.cpp +134 -60
- data/ext/libsass/expand.hpp +5 -2
- data/ext/libsass/extend.cpp +7 -5
- data/ext/libsass/file.cpp +176 -123
- data/ext/libsass/file.hpp +44 -7
- data/ext/libsass/functions.cpp +36 -17
- data/ext/libsass/functions.hpp +2 -2
- data/ext/libsass/inspect.cpp +23 -14
- data/ext/libsass/inspect.hpp +1 -0
- data/ext/libsass/json.cpp +132 -135
- data/ext/libsass/lexer.cpp +133 -0
- data/ext/libsass/lexer.hpp +239 -0
- data/ext/libsass/listize.cpp +83 -0
- data/ext/libsass/listize.hpp +41 -0
- data/ext/libsass/operation.hpp +2 -0
- data/ext/libsass/output.cpp +5 -6
- data/ext/libsass/parser.cpp +426 -388
- data/ext/libsass/parser.hpp +97 -109
- data/ext/libsass/plugins.cpp +15 -2
- data/ext/libsass/plugins.hpp +6 -4
- data/ext/libsass/position.cpp +52 -17
- data/ext/libsass/position.hpp +19 -17
- data/ext/libsass/prelexer.cpp +202 -235
- data/ext/libsass/prelexer.hpp +73 -333
- data/ext/libsass/sass.cpp +21 -11
- data/ext/libsass/sass.h +6 -6
- data/ext/libsass/sass_context.cpp +167 -81
- data/ext/libsass/sass_context.h +26 -6
- data/ext/libsass/sass_functions.cpp +49 -40
- data/ext/libsass/sass_functions.h +55 -43
- data/ext/libsass/sass_interface.cpp +9 -8
- data/ext/libsass/sass_interface.h +3 -3
- data/ext/libsass/sass_version.h +8 -0
- data/ext/libsass/sass_version.h.in +8 -0
- data/ext/libsass/script/ci-build-libsass +3 -3
- data/ext/libsass/script/ci-report-coverage +2 -1
- data/ext/libsass/source_map.cpp +2 -2
- data/ext/libsass/util.cpp +60 -11
- data/ext/libsass/util.hpp +6 -1
- data/ext/libsass/win/libsass.filters +12 -0
- data/ext/libsass/win/libsass.vcxproj +10 -0
- data/lib/sassc.rb +3 -1
- data/lib/sassc/cache_stores/base.rb +2 -0
- data/lib/sassc/dependency.rb +3 -1
- data/lib/sassc/engine.rb +31 -16
- data/lib/sassc/error.rb +3 -2
- data/lib/sassc/functions_handler.rb +54 -0
- data/lib/sassc/import_handler.rb +41 -0
- data/lib/sassc/importer.rb +4 -31
- data/lib/sassc/native.rb +1 -1
- data/lib/sassc/native/native_context_api.rb +3 -2
- data/lib/sassc/script.rb +0 -51
- data/lib/sassc/version.rb +1 -1
- data/sassc.gemspec +1 -0
- data/test/custom_importer_test.rb +72 -69
- data/test/engine_test.rb +53 -54
- data/test/functions_test.rb +40 -39
- data/test/native_test.rb +145 -149
- data/test/output_style_test.rb +98 -0
- data/test/test_helper.rb +21 -7
- metadata +28 -2
data/ext/libsass/emitter.cpp
CHANGED
data/ext/libsass/emitter.hpp
CHANGED
data/ext/libsass/environment.hpp
CHANGED
@@ -5,7 +5,9 @@
|
|
5
5
|
#include <string>
|
6
6
|
#include <iostream>
|
7
7
|
|
8
|
+
#include "ast_fwd_decl.hpp"
|
8
9
|
#include "ast_def_macros.hpp"
|
10
|
+
#include "memory_manager.hpp"
|
9
11
|
|
10
12
|
namespace Sass {
|
11
13
|
using std::string;
|
@@ -16,56 +18,136 @@ namespace Sass {
|
|
16
18
|
template <typename T>
|
17
19
|
class Environment {
|
18
20
|
// TODO: test with unordered_map
|
19
|
-
map<string, T>
|
21
|
+
map<string, T> local_frame_;
|
20
22
|
ADD_PROPERTY(Environment*, parent);
|
21
23
|
|
22
24
|
public:
|
23
|
-
|
24
|
-
|
25
|
-
map<string, T>& current_frame() { return current_frame_; }
|
25
|
+
Memory_Manager<AST_Node> mem;
|
26
|
+
Environment() : local_frame_(map<string, T>()), parent_(0) { }
|
26
27
|
|
28
|
+
// link parent to create a stack
|
27
29
|
void link(Environment& env) { parent_ = &env; }
|
28
30
|
void link(Environment* env) { parent_ = env; }
|
29
31
|
|
30
|
-
|
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
|
31
44
|
{
|
32
|
-
|
33
|
-
|
34
|
-
|
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_;
|
35
52
|
}
|
36
53
|
|
37
|
-
bool
|
38
|
-
{ return
|
54
|
+
bool has_local(const string& key) const
|
55
|
+
{ return local_frame_.count(key); }
|
39
56
|
|
40
|
-
|
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()
|
41
71
|
{
|
42
|
-
|
43
|
-
|
72
|
+
Environment* cur = this;
|
73
|
+
while (cur->is_lexical()) {
|
74
|
+
cur = cur->parent_;
|
75
|
+
}
|
76
|
+
return cur;
|
44
77
|
}
|
45
78
|
|
46
|
-
bool
|
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
|
47
95
|
{
|
48
|
-
|
49
|
-
|
96
|
+
auto cur = this;
|
97
|
+
while (cur->is_lexical()) {
|
98
|
+
if (cur->has_local(key)) return true;
|
99
|
+
cur = cur->parent_;
|
50
100
|
}
|
51
|
-
|
52
|
-
|
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_;
|
53
116
|
}
|
54
|
-
|
55
|
-
|
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_;
|
56
130
|
}
|
131
|
+
return false;
|
57
132
|
}
|
58
133
|
|
59
|
-
|
134
|
+
// use array access for getter and setter functions
|
135
|
+
T& operator[](const string& key)
|
60
136
|
{
|
61
|
-
|
62
|
-
|
63
|
-
|
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);
|
64
145
|
}
|
65
146
|
|
147
|
+
#ifdef DEBUG
|
66
148
|
void print()
|
67
149
|
{
|
68
|
-
for (typename map<string, T>::iterator i =
|
150
|
+
for (typename map<string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
|
69
151
|
cerr << i->first << endl;
|
70
152
|
}
|
71
153
|
if (parent_) {
|
@@ -73,6 +155,8 @@ namespace Sass {
|
|
73
155
|
parent_->print();
|
74
156
|
}
|
75
157
|
}
|
158
|
+
#endif
|
159
|
+
|
76
160
|
};
|
77
161
|
}
|
78
162
|
|
@@ -9,12 +9,12 @@ namespace Sass {
|
|
9
9
|
{ }
|
10
10
|
|
11
11
|
void error(string msg, ParserState pstate)
|
12
|
-
{
|
12
|
+
{
|
13
|
+
throw Sass_Error(Sass_Error::syntax, pstate, msg);
|
14
|
+
}
|
13
15
|
|
14
16
|
void error(string msg, ParserState pstate, Backtrace* bt)
|
15
17
|
{
|
16
|
-
if (!pstate.path.empty() && Prelexer::quoted_string(pstate.path.c_str()))
|
17
|
-
pstate.path = pstate.path.substr(1, pstate.path.size() - 1);
|
18
18
|
|
19
19
|
Backtrace top(bt, pstate, "");
|
20
20
|
msg += top.to_string();
|
data/ext/libsass/eval.cpp
CHANGED
@@ -31,12 +31,21 @@ namespace Sass {
|
|
31
31
|
add, sub, mul, div, fmod
|
32
32
|
};
|
33
33
|
|
34
|
-
Eval::Eval(Context& ctx, Env* env, Backtrace* bt)
|
35
|
-
: ctx(ctx), env(env), backtrace(bt) { }
|
34
|
+
Eval::Eval(Context& ctx, Contextualize* contextualize, Listize* listize, Env* env, Backtrace* bt)
|
35
|
+
: ctx(ctx), contextualize(contextualize), listize(listize), env(env), backtrace(bt) { }
|
36
36
|
Eval::~Eval() { }
|
37
37
|
|
38
38
|
Eval* Eval::with(Env* e, Backtrace* bt) // for setting the env before eval'ing an expression
|
39
39
|
{
|
40
|
+
contextualize = contextualize->with(0, e, bt);
|
41
|
+
env = e;
|
42
|
+
backtrace = bt;
|
43
|
+
return this;
|
44
|
+
}
|
45
|
+
|
46
|
+
Eval* Eval::with(Selector* c, Env* e, Backtrace* bt, Selector* p, Selector* ex) // for setting the env before eval'ing an expression
|
47
|
+
{
|
48
|
+
contextualize = contextualize->with(c, e, bt, p, ex);
|
40
49
|
env = e;
|
41
50
|
backtrace = bt;
|
42
51
|
return this;
|
@@ -55,12 +64,59 @@ namespace Sass {
|
|
55
64
|
Expression* Eval::operator()(Assignment* a)
|
56
65
|
{
|
57
66
|
string var(a->variable());
|
58
|
-
if (
|
59
|
-
|
60
|
-
|
67
|
+
if (a->is_global()) {
|
68
|
+
if (a->is_default()) {
|
69
|
+
if (env->has_global(var)) {
|
70
|
+
Expression* e = dynamic_cast<Expression*>(env->get_global(var));
|
71
|
+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
72
|
+
env->set_global(var, a->value()->perform(this));
|
73
|
+
}
|
74
|
+
}
|
75
|
+
else {
|
76
|
+
env->set_global(var, a->value()->perform(this));
|
77
|
+
}
|
78
|
+
}
|
79
|
+
else {
|
80
|
+
env->set_global(var, a->value()->perform(this));
|
81
|
+
}
|
82
|
+
}
|
83
|
+
else if (a->is_default()) {
|
84
|
+
if (env->has_lexical(var)) {
|
85
|
+
auto cur = env;
|
86
|
+
while (cur && cur->is_lexical()) {
|
87
|
+
if (cur->has_local(var)) {
|
88
|
+
if (AST_Node* node = cur->get_local(var)) {
|
89
|
+
Expression* e = dynamic_cast<Expression*>(node);
|
90
|
+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
91
|
+
cur->set_local(var, a->value()->perform(this));
|
92
|
+
}
|
93
|
+
}
|
94
|
+
else {
|
95
|
+
throw runtime_error("Env not in sync");
|
96
|
+
}
|
97
|
+
return 0;
|
98
|
+
}
|
99
|
+
cur = cur->parent();
|
100
|
+
}
|
101
|
+
throw runtime_error("Env not in sync");
|
102
|
+
}
|
103
|
+
else if (env->has_global(var)) {
|
104
|
+
if (AST_Node* node = env->get_global(var)) {
|
105
|
+
Expression* e = dynamic_cast<Expression*>(node);
|
106
|
+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
107
|
+
env->set_global(var, a->value()->perform(this));
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}
|
111
|
+
else if (env->is_lexical()) {
|
112
|
+
env->set_local(var, a->value()->perform(this));
|
113
|
+
}
|
114
|
+
else {
|
115
|
+
env->set_local(var, a->value()->perform(this));
|
116
|
+
}
|
61
117
|
}
|
62
118
|
else {
|
63
|
-
env->
|
119
|
+
env->set_lexical(var, a->value()->perform(this));
|
64
120
|
}
|
65
121
|
return 0;
|
66
122
|
}
|
@@ -77,6 +133,8 @@ namespace Sass {
|
|
77
133
|
return 0;
|
78
134
|
}
|
79
135
|
|
136
|
+
// For does not create a new env scope
|
137
|
+
// But iteration vars are reset afterwards
|
80
138
|
Expression* Eval::operator()(For* f)
|
81
139
|
{
|
82
140
|
string variable(f->variable());
|
@@ -88,19 +146,30 @@ namespace Sass {
|
|
88
146
|
if (high->concrete_type() != Expression::NUMBER) {
|
89
147
|
error("upper bound of `@for` directive must be numeric", high->pstate());
|
90
148
|
}
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
149
|
+
Number* sass_start = static_cast<Number*>(low);
|
150
|
+
Number* sass_end = static_cast<Number*>(high);
|
151
|
+
// check if units are valid for sequence
|
152
|
+
if (sass_start->unit() != sass_end->unit()) {
|
153
|
+
stringstream msg; msg << "Incompatible units: '"
|
154
|
+
<< sass_start->unit() << "' and '"
|
155
|
+
<< sass_end->unit() << "'.";
|
156
|
+
error(msg.str(), low->pstate(), backtrace);
|
157
|
+
}
|
158
|
+
double start = sass_start->value();
|
159
|
+
double end = sass_end->value();
|
160
|
+
// only create iterator once in this environment
|
161
|
+
Number* it = new (env->mem) Number(low->pstate(), start, sass_end->unit());
|
162
|
+
AST_Node* old_var = env->has_local(variable) ? env->get_local(variable) : 0;
|
163
|
+
env->set_local(variable, it);
|
97
164
|
Block* body = f->block();
|
98
165
|
Expression* val = 0;
|
99
166
|
if (start < end) {
|
100
167
|
if (f->is_inclusive()) ++end;
|
101
168
|
for (double i = start;
|
102
169
|
i < end;
|
103
|
-
|
170
|
+
++i) {
|
171
|
+
it->value(i);
|
172
|
+
env->set_local(variable, it);
|
104
173
|
val = body->perform(this);
|
105
174
|
if (val) break;
|
106
175
|
}
|
@@ -108,15 +177,21 @@ namespace Sass {
|
|
108
177
|
if (f->is_inclusive()) --end;
|
109
178
|
for (double i = start;
|
110
179
|
i > end;
|
111
|
-
|
180
|
+
--i) {
|
181
|
+
it->value(i);
|
182
|
+
env->set_local(variable, it);
|
112
183
|
val = body->perform(this);
|
113
184
|
if (val) break;
|
114
185
|
}
|
115
186
|
}
|
116
|
-
|
187
|
+
// restore original environment
|
188
|
+
if (!old_var) env->del_local(variable);
|
189
|
+
else env->set_local(variable, old_var);
|
117
190
|
return val;
|
118
191
|
}
|
119
192
|
|
193
|
+
// Eval does not create a new env scope
|
194
|
+
// But iteration vars are reset afterwards
|
120
195
|
Expression* Eval::operator()(Each* e)
|
121
196
|
{
|
122
197
|
vector<string> variables(e->variables());
|
@@ -133,10 +208,12 @@ namespace Sass {
|
|
133
208
|
else {
|
134
209
|
list = static_cast<List*>(expr);
|
135
210
|
}
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
211
|
+
// remember variables and then reset them
|
212
|
+
vector<AST_Node*> old_vars(variables.size());
|
213
|
+
for (size_t i = 0, L = variables.size(); i < L; ++i) {
|
214
|
+
old_vars[i] = env->has_local(variables[i]) ? env->get_local(variables[i]) : 0;
|
215
|
+
env->set_local(variables[i], 0);
|
216
|
+
}
|
140
217
|
Block* body = e->block();
|
141
218
|
Expression* val = 0;
|
142
219
|
|
@@ -148,10 +225,10 @@ namespace Sass {
|
|
148
225
|
List* variable = new (ctx.mem) List(map->pstate(), 2, List::SPACE);
|
149
226
|
*variable << key;
|
150
227
|
*variable << value;
|
151
|
-
(
|
228
|
+
env->set_local(variables[0], variable);
|
152
229
|
} else {
|
153
|
-
(
|
154
|
-
(
|
230
|
+
env->set_local(variables[0], key);
|
231
|
+
env->set_local(variables[1], value);
|
155
232
|
}
|
156
233
|
|
157
234
|
val = body->perform(this);
|
@@ -170,10 +247,10 @@ namespace Sass {
|
|
170
247
|
}
|
171
248
|
for (size_t j = 0, K = variables.size(); j < K; ++j) {
|
172
249
|
if (j < variable->length()) {
|
173
|
-
(
|
250
|
+
env->set_local(variables[j], (*variable)[j]);
|
174
251
|
}
|
175
252
|
else {
|
176
|
-
(
|
253
|
+
env->set_local(variables[j], new (ctx.mem) Null(expr->pstate()));
|
177
254
|
}
|
178
255
|
val = body->perform(this);
|
179
256
|
if (val) break;
|
@@ -181,7 +258,11 @@ namespace Sass {
|
|
181
258
|
if (val) break;
|
182
259
|
}
|
183
260
|
}
|
184
|
-
|
261
|
+
// restore original environment
|
262
|
+
for (size_t j = 0, K = variables.size(); j < K; ++j) {
|
263
|
+
if(!old_vars[j]) env->del_local(variables[j]);
|
264
|
+
else env->set_local(variables[j], old_vars[j]);
|
265
|
+
}
|
185
266
|
return val;
|
186
267
|
}
|
187
268
|
|
@@ -212,12 +293,13 @@ namespace Sass {
|
|
212
293
|
Definition* def = static_cast<Definition*>((*env)["@warn[f]"]);
|
213
294
|
// Block* body = def->block();
|
214
295
|
// Native_Function func = def->native_function();
|
215
|
-
|
296
|
+
Sass_Function_Entry c_function = def->c_function();
|
297
|
+
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
216
298
|
|
217
299
|
To_C to_c;
|
218
300
|
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
|
219
301
|
sass_list_set_value(c_args, 0, message->perform(&to_c));
|
220
|
-
Sass_Value* c_val = c_func(c_args,
|
302
|
+
Sass_Value* c_val = c_func(c_args, c_function, ctx.c_options);
|
221
303
|
sass_delete_value(c_args);
|
222
304
|
sass_delete_value(c_val);
|
223
305
|
return 0;
|
@@ -243,12 +325,13 @@ namespace Sass {
|
|
243
325
|
Definition* def = static_cast<Definition*>((*env)["@error[f]"]);
|
244
326
|
// Block* body = def->block();
|
245
327
|
// Native_Function func = def->native_function();
|
246
|
-
|
328
|
+
Sass_Function_Entry c_function = def->c_function();
|
329
|
+
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
247
330
|
|
248
331
|
To_C to_c;
|
249
332
|
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
|
250
333
|
sass_list_set_value(c_args, 0, message->perform(&to_c));
|
251
|
-
Sass_Value* c_val = c_func(c_args,
|
334
|
+
Sass_Value* c_val = c_func(c_args, c_function, ctx.c_options);
|
252
335
|
sass_delete_value(c_args);
|
253
336
|
sass_delete_value(c_val);
|
254
337
|
return 0;
|
@@ -256,10 +339,7 @@ namespace Sass {
|
|
256
339
|
}
|
257
340
|
|
258
341
|
string result(unquote(message->perform(&to_string)));
|
259
|
-
|
260
|
-
cerr << "Error: " << result;
|
261
|
-
cerr << top.to_string(true);
|
262
|
-
cerr << endl << endl;
|
342
|
+
error(result, e->pstate());
|
263
343
|
return 0;
|
264
344
|
}
|
265
345
|
|
@@ -274,12 +354,13 @@ namespace Sass {
|
|
274
354
|
Definition* def = static_cast<Definition*>((*env)["@debug[f]"]);
|
275
355
|
// Block* body = def->block();
|
276
356
|
// Native_Function func = def->native_function();
|
277
|
-
|
357
|
+
Sass_Function_Entry c_function = def->c_function();
|
358
|
+
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
278
359
|
|
279
360
|
To_C to_c;
|
280
361
|
union Sass_Value* c_args = sass_make_list(1, SASS_COMMA);
|
281
362
|
sass_list_set_value(c_args, 0, message->perform(&to_c));
|
282
|
-
Sass_Value* c_val = c_func(c_args,
|
363
|
+
Sass_Value* c_val = c_func(c_args, c_function, ctx.c_options);
|
283
364
|
sass_delete_value(c_args);
|
284
365
|
sass_delete_value(c_val);
|
285
366
|
return 0;
|
@@ -431,7 +512,8 @@ namespace Sass {
|
|
431
512
|
|
432
513
|
Expression* Eval::operator()(Function_Call* c)
|
433
514
|
{
|
434
|
-
string
|
515
|
+
string name(Util::normalize_underscores(c->name()));
|
516
|
+
string full_name(name + "[f]");
|
435
517
|
Arguments* args = c->arguments();
|
436
518
|
if (full_name != "if[f]") {
|
437
519
|
args = static_cast<Arguments*>(args->perform(this));
|
@@ -458,7 +540,7 @@ namespace Sass {
|
|
458
540
|
Definition* def = static_cast<Definition*>((*env)[full_name]);
|
459
541
|
Block* body = def->block();
|
460
542
|
Native_Function func = def->native_function();
|
461
|
-
|
543
|
+
Sass_Function_Entry c_function = def->c_function();
|
462
544
|
|
463
545
|
if (full_name != "if[f]") {
|
464
546
|
for (size_t i = 0, L = args->length(); i < L; ++i) {
|
@@ -509,8 +591,9 @@ namespace Sass {
|
|
509
591
|
env = old_env;
|
510
592
|
}
|
511
593
|
// else if it's a user-defined c function
|
512
|
-
else if (
|
594
|
+
else if (c_function) {
|
513
595
|
|
596
|
+
Sass_Function_Fn c_func = sass_function_get_function(c_function);
|
514
597
|
if (full_name == "*[f]") {
|
515
598
|
String_Constant *str = new (ctx.mem) String_Constant(c->pstate(), c->name());
|
516
599
|
Arguments* new_args = new (ctx.mem) Arguments(c->pstate());
|
@@ -528,14 +611,14 @@ namespace Sass {
|
|
528
611
|
backtrace = &here;
|
529
612
|
|
530
613
|
To_C to_c;
|
531
|
-
union Sass_Value* c_args = sass_make_list(env->
|
614
|
+
union Sass_Value* c_args = sass_make_list(env->local_frame().size(), SASS_COMMA);
|
532
615
|
for(size_t i = 0; i < params[0].length(); i++) {
|
533
616
|
string key = params[0][i]->name();
|
534
|
-
AST_Node* node = env->
|
617
|
+
AST_Node* node = env->local_frame().at(key);
|
535
618
|
Expression* arg = static_cast<Expression*>(node);
|
536
619
|
sass_list_set_value(c_args, i, arg->perform(&to_c));
|
537
620
|
}
|
538
|
-
Sass_Value* c_val = c_func(c_args,
|
621
|
+
Sass_Value* c_val = c_func(c_args, c_function, ctx.c_options);
|
539
622
|
if (sass_value_get_tag(c_val) == SASS_ERROR) {
|
540
623
|
error("error in C function " + c->name() + ": " + sass_error_get_message(c_val), c->pstate(), backtrace);
|
541
624
|
} else if (sass_value_get_tag(c_val) == SASS_WARNING) {
|
@@ -671,7 +754,7 @@ namespace Sass {
|
|
671
754
|
case Textual::DIMENSION:
|
672
755
|
result = new (ctx.mem) Number(t->pstate(),
|
673
756
|
sass_atof(num.c_str()),
|
674
|
-
Token(number(text.c_str())
|
757
|
+
Token(number(text.c_str())),
|
675
758
|
zero);
|
676
759
|
break;
|
677
760
|
case Textual::HEX: {
|
@@ -727,21 +810,15 @@ namespace Sass {
|
|
727
810
|
}
|
728
811
|
|
729
812
|
string Eval::interpolation(Expression* s) {
|
730
|
-
|
731
813
|
if (String_Quoted* str_quoted = dynamic_cast<String_Quoted*>(s)) {
|
732
|
-
|
733
814
|
if (str_quoted->quote_mark()) {
|
734
815
|
return string_escape(str_quoted->value());
|
735
816
|
} else {
|
736
817
|
return evacuate_escapes(str_quoted->value());
|
737
818
|
}
|
738
|
-
|
739
819
|
} else if (String_Constant* str_constant = dynamic_cast<String_Constant*>(s)) {
|
740
|
-
|
741
820
|
return evacuate_escapes(str_constant->value());
|
742
|
-
|
743
821
|
} else if (String_Schema* str_schema = dynamic_cast<String_Schema*>(s)) {
|
744
|
-
|
745
822
|
string res = "";
|
746
823
|
for(auto i : str_schema->elements())
|
747
824
|
res += (interpolation(i));
|
@@ -753,9 +830,7 @@ namespace Sass {
|
|
753
830
|
} else {
|
754
831
|
return evacuate_quotes(unq);
|
755
832
|
}
|
756
|
-
|
757
833
|
} else if (List* list = dynamic_cast<List*>(s)) {
|
758
|
-
|
759
834
|
string acc = ""; // ToDo: different output styles
|
760
835
|
string sep = list->separator() == List::Separator::COMMA ? "," : " ";
|
761
836
|
if (ctx.output_style != COMPRESSED && sep == ",") sep += " ";
|
@@ -766,30 +841,30 @@ namespace Sass {
|
|
766
841
|
initial = true;
|
767
842
|
}
|
768
843
|
return evacuate_quotes(acc);
|
769
|
-
|
770
844
|
} else if (Variable* var = dynamic_cast<Variable*>(s)) {
|
771
|
-
|
772
845
|
string name(var->name());
|
773
846
|
if (!env->has(name)) error("Undefined variable: \"" + var->name() + "\".", var->pstate());
|
774
847
|
Expression* value = static_cast<Expression*>((*env)[name]);
|
775
848
|
return evacuate_quotes(interpolation(value));
|
776
|
-
|
777
849
|
} else if (Binary_Expression* var = dynamic_cast<Binary_Expression*>(s)) {
|
778
|
-
|
779
|
-
Expression* ex = operator()(var);
|
850
|
+
Expression* ex = var->perform(this);
|
780
851
|
return evacuate_quotes(interpolation(ex));
|
781
|
-
|
782
852
|
} else if (Function_Call* var = dynamic_cast<Function_Call*>(s)) {
|
783
|
-
|
784
|
-
|
853
|
+
Expression* ex = var->perform(this);
|
854
|
+
return evacuate_quotes(interpolation(ex));
|
855
|
+
} else if (Parent_Selector* var = dynamic_cast<Parent_Selector*>(s)) {
|
856
|
+
Expression* ex = var->perform(this);
|
857
|
+
return evacuate_quotes(interpolation(ex));
|
858
|
+
} else if (Unary_Expression* var = dynamic_cast<Unary_Expression*>(s)) {
|
859
|
+
Expression* ex = var->perform(this);
|
860
|
+
return evacuate_quotes(interpolation(ex));
|
861
|
+
} else if (Selector* var = dynamic_cast<Selector*>(s)) {
|
862
|
+
Expression* ex = var->perform(this);
|
785
863
|
return evacuate_quotes(interpolation(ex));
|
786
|
-
|
787
864
|
} else {
|
788
|
-
|
789
865
|
To_String to_string(&ctx);
|
790
866
|
// to_string.in_decl_list = true;
|
791
867
|
return evacuate_quotes(s->perform(&to_string));
|
792
|
-
|
793
868
|
}
|
794
869
|
}
|
795
870
|
|
@@ -938,6 +1013,15 @@ namespace Sass {
|
|
938
1013
|
return 0;
|
939
1014
|
}
|
940
1015
|
|
1016
|
+
Expression* Eval::operator()(Parent_Selector* p)
|
1017
|
+
{
|
1018
|
+
Selector* s = p->perform(contextualize);
|
1019
|
+
// access to parent selector may return 0
|
1020
|
+
Selector_List* l = static_cast<Selector_List*>(s);
|
1021
|
+
if (!s) { l = new (ctx.mem) Selector_List(p->pstate()); }
|
1022
|
+
return l->perform(listize);
|
1023
|
+
}
|
1024
|
+
|
941
1025
|
inline Expression* Eval::fallback_impl(AST_Node* n)
|
942
1026
|
{
|
943
1027
|
return static_cast<Expression*>(n);
|