Skip to content

Commit

Permalink
Improve scope handling for variables
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed Apr 11, 2015
1 parent c4fb559 commit 9bc24a9
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 26 deletions.
8 changes: 2 additions & 6 deletions environment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ namespace Sass {
// see if we have a lexical we could update
// either update already existing lexical value
// or if flag is set, we create one if no lexical found
void set_lexical(const string& key, T val, bool global = false)
void set_lexical(const string& key, T val)
{
auto cur = this;
while (cur->is_lexical()) {
Expand All @@ -114,11 +114,7 @@ namespace Sass {
}
cur = cur->parent_;
}
if (global) {
set_global(key, val);
} else {
set_local(key, val);
}
set_local(key, val);
}

// look on the full stack for key
Expand Down
57 changes: 47 additions & 10 deletions eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,56 @@ namespace Sass {
{
string var(a->variable());
if (a->is_global()) {
env->set_global(var, a->value()->perform(this));
}
else if (a->is_default()) {
if (env->has_lexical(var)) return 0;
if (env->has_global(var)) {
Expression* e = static_cast<Expression*>(env->get_global(var));
if (e->concrete_type() == Expression::NULL_VAL) {
if (a->is_default()) {
if (env->has_global(var)) {
Expression* e = dynamic_cast<Expression*>(env->get_global(var));
if (!e || e->concrete_type() == Expression::NULL_VAL) {
env->set_global(var, a->value()->perform(this));
}
}
else {
env->set_global(var, a->value()->perform(this));
}
} else {
}
else {
env->set_global(var, a->value()->perform(this));
}
}
else if (a->is_default()) {
if (env->has_lexical(var)) {
auto cur = env;
while (cur && cur->is_lexical()) {
if (cur->has_local(var)) {
if (AST_Node* node = cur->get_local(var)) {
Expression* e = dynamic_cast<Expression*>(node);
if (!e || e->concrete_type() == Expression::NULL_VAL) {
cur->set_local(var, a->value()->perform(this));
}
}
else {
throw runtime_error("Env not in sync");
}
return 0;
}
cur = cur->parent();
}
throw runtime_error("Env not in sync");
}
else if (env->has_global(var)) {
if (AST_Node* node = env->get_global(var)) {
Expression* e = dynamic_cast<Expression*>(node);
if (!e || e->concrete_type() == Expression::NULL_VAL) {
env->set_global(var, a->value()->perform(this));
}
}
}
else if (env->is_lexical()) {
env->set_local(var, a->value()->perform(this));
}
else {
env->set_local(var, a->value()->perform(this));
}
}
else {
env->set_lexical(var, a->value()->perform(this));
}
Expand Down Expand Up @@ -122,7 +159,7 @@ namespace Sass {
double end = sass_end->value();
// only create iterator once in this environment
Number* it = new (env->mem) Number(low->pstate(), start, sass_end->unit());
AST_Node* old_var = env->get_local(variable);
AST_Node* old_var = env->has_local(variable) ? env->get_local(variable) : 0;
env->set_local(variable, it);
Block* body = f->block();
Expression* val = 0;
Expand Down Expand Up @@ -174,7 +211,7 @@ namespace Sass {
// remember variables and then reset them
vector<AST_Node*> old_vars(variables.size());
for (size_t i = 0, L = variables.size(); i < L; ++i) {
old_vars[i] = env->get_local(variables[i]);
old_vars[i] = env->has_local(variables[i]) ? env->get_local(variables[i]) : 0;
env->set_local(variables[i], 0);
}
Block* body = e->block();
Expand Down
57 changes: 47 additions & 10 deletions expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,19 +216,56 @@ namespace Sass {
string var(a->variable());
Selector* p = selector_stack.size() <= 1 ? 0 : selector_stack.back();
if (a->is_global()) {
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
}
else if (a->is_default()) {
if (env->has_lexical(var)) return 0;
if (env->has_global(var)) {
Expression* e = static_cast<Expression*>(env->get_global(var));
if (e->concrete_type() == Expression::NULL_VAL) {
if (a->is_default()) {
if (env->has_global(var)) {
Expression* e = dynamic_cast<Expression*>(env->get_global(var));
if (!e || e->concrete_type() == Expression::NULL_VAL) {
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
}
}
else {
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
}
} else {
}
else {
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
}
}
else if (a->is_default()) {
if (env->has_lexical(var)) {
auto cur = env;
while (cur && cur->is_lexical()) {
if (cur->has_local(var)) {
if (AST_Node* node = cur->get_local(var)) {
Expression* e = dynamic_cast<Expression*>(node);
if (!e || e->concrete_type() == Expression::NULL_VAL) {
cur->set_local(var, a->value()->perform(eval->with(p, env, backtrace)));
}
}
else {
throw runtime_error("Env not in sync");
}
return 0;
}
cur = cur->parent();
}
throw runtime_error("Env not in sync");
}
else if (env->has_global(var)) {
if (AST_Node* node = env->get_global(var)) {
Expression* e = dynamic_cast<Expression*>(node);
if (!e || e->concrete_type() == Expression::NULL_VAL) {
env->set_global(var, a->value()->perform(eval->with(p, env, backtrace)));
}
}
}
else if (env->is_lexical()) {
env->set_local(var, a->value()->perform(eval->with(p, env, backtrace)));
}
else {
env->set_local(var, a->value()->perform(eval->with(p, env, backtrace)));
}
}
else {
env->set_lexical(var, a->value()->perform(eval->with(p, env, backtrace)));
}
Expand Down Expand Up @@ -315,7 +352,7 @@ namespace Sass {
double end = sass_end->value();
// only create iterator once in this environment
Number* it = new (env->mem) Number(low->pstate(), start, sass_end->unit());
AST_Node* old_var = env->get_local(variable);
AST_Node* old_var = env->has_local(variable) ? env->get_local(variable) : 0;
env->set_local(variable, it);
Block* body = f->block();
if (start < end) {
Expand Down Expand Up @@ -364,7 +401,7 @@ namespace Sass {
// remember variables and then reset them
vector<AST_Node*> old_vars(variables.size());
for (size_t i = 0, L = variables.size(); i < L; ++i) {
old_vars[i] = env->get_local(variables[i]);
old_vars[i] = env->has_local(variables[i]) ? env->get_local(variables[i]) : 0;
env->set_local(variables[i], 0);
}
Block* body = e->block();
Expand Down

0 comments on commit 9bc24a9

Please sign in to comment.