<commit_before>#include "eval.hpp"
#include "ast.hpp"
#include "bind.hpp"
#include "to_string.hpp"
#include "inspect.hpp"
#include "to_c.hpp"
#include "context.hpp"
#include "backtrace.hpp"
#include "prelexer.hpp"

#include <cstdlib>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <typeinfo>

namespace Sass {
  using namespace std;

  inline double add(double x, double y) { return x + y; }
  inline double sub(double x, double y) { return x - y; }
  inline double mul(double x, double y) { return x * y; }
  inline double div(double x, double y) { return x / y; } // x/0 checked by caller
  typedef double (*bop)(double, double);
  bop ops[Binary_Expression::NUM_OPS] = {
    0, 0, // and, or
    0, 0, 0, 0, 0, 0, // eq, neq, gt, gte, lt, lte
    add, sub, mul, div, fmod
  };

  Eval::Eval(Context& ctx, Env* env, Backtrace* bt)
  : ctx(ctx), env(env), backtrace(bt) { }
  Eval::~Eval() { }

  Eval* Eval::with(Env* e, Backtrace* bt) // for setting the env before eval'ing an expression
  {
    env = e;
    backtrace = bt;
    return this;
  }

  Expression* Eval::operator()(Block* b)
  {
    Expression* val = 0;
    for (size_t i = 0, L = b->length(); i < L; ++i) {
      val = (*b)[i]->perform(this);
      if (val) return val;
    }
    return val;
  }

  Expression* Eval::operator()(Assignment* a)
  {
    string var(a->variable());
    if (env->has(var)) {
      if(!a->is_guarded()) (*env)[var] = a->value()->perform(this);
    }
    else {
      env->current_frame()[var] = a->value()->perform(this);
    }
    return 0;
  }

  Expression* Eval::operator()(If* i)
  {
    if (*i->predicate()->perform(this)) {
      return i->consequent()->perform(this);
    }
    else {
      Block* alt = i->alternative();
      if (alt) return alt->perform(this);
    }
    return 0;
  }

  Expression* Eval::operator()(For* f)
  {
    string variable(f->variable());
    Expression* low = f->lower_bound()->perform(this);
    if (low->concrete_type() != Expression::NUMBER) {
      error("lower bound of `@for` directive must be numeric", low->path(), low->position());
    }
    Expression* high = f->upper_bound()->perform(this);
    if (high->concrete_type() != Expression::NUMBER) {
      error("upper bound of `@for` directive must be numeric", high->path(), high->position());
    }
    double start = static_cast<Number*>(low)->value();
    double end = static_cast<Number*>(high)->value();
    Env new_env;
    new_env[variable] = new (ctx.mem) Number(low->path(), low->position(), start);
    new_env.link(env);
    env = &new_env;
    Block* body = f->block();
    Expression* val = 0;
    if (start < end) {
      if (f->is_inclusive()) ++end;
      for (double i = start;
           i < end;
           (*env)[variable] = new (ctx.mem) Number(low->path(), low->position(), ++i)) {
        val = body->perform(this);
        if (val) break;
      }
    } else {
      if (f->is_inclusive()) --end;
      for (double i = start;
           i > end;
           (*env)[variable] = new (ctx.mem) Number(low->path(), low->position(), --i)) {
        val = body->perform(this);
        if (val) break;
      }
    }
    env = new_env.parent();
    return val;
  }

  Expression* Eval::operator()(Each* e)
  {
    vector<string> variables(e->variables());
    Expression* expr = e->list()->perform(this);
    List* list = 0;
    Map* map = 0;
    if (expr->concrete_type() == Expression::MAP) {
      map = static_cast<Map*>(expr);
    }
    else if (expr->concrete_type() != Expression::LIST) {
      list = new (ctx.mem) List(expr->path(), expr->position(), 1, List::COMMA);
      *list << expr;
    }
    else {
      list = static_cast<List*>(expr);
    }
    Env new_env;
    for (size_t i = 0, L = variables.size(); i < L; ++i) new_env[variables[i]] = 0;
    new_env.link(env);
    env = &new_env;
    Block* body = e->block();
    Expression* val = 0;

    if (map) {
      for (auto key : map->keys()) {
        (*env)[variables[0]] = key;
        (*env)[variables[1]] = map->at(key);
        val = body->perform(this);
        if (val) break;
      }
    }
    else {
      for (size_t i = 0, L = list->length(); i < L; ++i) {
        List* variable = 0;
        if ((*list)[i]->concrete_type() != Expression::LIST || variables.size() == 1) {
          variable = new (ctx.mem) List((*list)[i]->path(), (*list)[i]->position(), 1, List::COMMA);
          *variable << (*list)[i];
        }
        else {
          variable = static_cast<List*>((*list)[i]);
        }
        for (size_t j = 0, K = variables.size(); j < K; ++j) {
          if (j < variable->length()) {
            (*env)[variables[j]] = (*variable)[j];
          }
          else {
            (*env)[variables[j]] = new (ctx.mem) Null(expr->path(), expr->position());
          }
          val = body->perform(this);
          if (val) break;
        }
      }
    }
    env = new_env.parent();
    return val;
  }

  Expression* Eval::operator()(While* w)
  {
    Expression* pred = w->predicate();
    Block* body = w->block();
    while (*pred->perform(this)) {
      Expression* val = body->perform(this);
      if (val) return val;
    }
    return 0;<commit_msg>Bubble @return in each lists<commit_after>#include "eval.hpp"
#include "ast.hpp"
#include "bind.hpp"
#include "to_string.hpp"
#include "inspect.hpp"
#include "to_c.hpp"
#include "context.hpp"
#include "backtrace.hpp"
#include "prelexer.hpp"

#include <cstdlib>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <typeinfo>

namespace Sass {
  using namespace std;

  inline double add(double x, double y) { return x + y; }
  inline double sub(double x, double y) { return x - y; }
  inline double mul(double x, double y) { return x * y; }
  inline double div(double x, double y) { return x / y; } // x/0 checked by caller
  typedef double (*bop)(double, double);
  bop ops[Binary_Expression::NUM_OPS] = {
    0, 0, // and, or
    0, 0, 0, 0, 0, 0, // eq, neq, gt, gte, lt, lte
    add, sub, mul, div, fmod
  };

  Eval::Eval(Context& ctx, Env* env, Backtrace* bt)
  : ctx(ctx), env(env), backtrace(bt) { }
  Eval::~Eval() { }

  Eval* Eval::with(Env* e, Backtrace* bt) // for setting the env before eval'ing an expression
  {
    env = e;
    backtrace = bt;
    return this;
  }

  Expression* Eval::operator()(Block* b)
  {
    Expression* val = 0;
    for (size_t i = 0, L = b->length(); i < L; ++i) {
      val = (*b)[i]->perform(this);
      if (val) return val;
    }
    return val;
  }

  Expression* Eval::operator()(Assignment* a)
  {
    string var(a->variable());
    if (env->has(var)) {
      if(!a->is_guarded()) (*env)[var] = a->value()->perform(this);
    }
    else {
      env->current_frame()[var] = a->value()->perform(this);
    }
    return 0;
  }

  Expression* Eval::operator()(If* i)
  {
    if (*i->predicate()->perform(this)) {
      return i->consequent()->perform(this);
    }
    else {
      Block* alt = i->alternative();
      if (alt) return alt->perform(this);
    }
    return 0;
  }

  Expression* Eval::operator()(For* f)
  {
    string variable(f->variable());
    Expression* low = f->lower_bound()->perform(this);
    if (low->concrete_type() != Expression::NUMBER) {
      error("lower bound of `@for` directive must be numeric", low->path(), low->position());
    }
    Expression* high = f->upper_bound()->perform(this);
    if (high->concrete_type() != Expression::NUMBER) {
      error("upper bound of `@for` directive must be numeric", high->path(), high->position());
    }
    double start = static_cast<Number*>(low)->value();
    double end = static_cast<Number*>(high)->value();
    Env new_env;
    new_env[variable] = new (ctx.mem) Number(low->path(), low->position(), start);
    new_env.link(env);
    env = &new_env;
    Block* body = f->block();
    Expression* val = 0;
    if (start < end) {
      if (f->is_inclusive()) ++end;
      for (double i = start;
           i < end;
           (*env)[variable] = new (ctx.mem) Number(low->path(), low->position(), ++i)) {
        val = body->perform(this);
        if (val) break;
      }
    } else {
      if (f->is_inclusive()) --end;
      for (double i = start;
           i > end;
           (*env)[variable] = new (ctx.mem) Number(low->path(), low->position(), --i)) {
        val = body->perform(this);
        if (val) break;
      }
    }
    env = new_env.parent();
    return val;
  }

  Expression* Eval::operator()(Each* e)
  {
    vector<string> variables(e->variables());
    Expression* expr = e->list()->perform(this);
    List* list = 0;
    Map* map = 0;
    if (expr->concrete_type() == Expression::MAP) {
      map = static_cast<Map*>(expr);
    }
    else if (expr->concrete_type() != Expression::LIST) {
      list = new (ctx.mem) List(expr->path(), expr->position(), 1, List::COMMA);
      *list << expr;
    }
    else {
      list = static_cast<List*>(expr);
    }
    Env new_env;
    for (size_t i = 0, L = variables.size(); i < L; ++i) new_env[variables[i]] = 0;
    new_env.link(env);
    env = &new_env;
    Block* body = e->block();
    Expression* val = 0;

    if (map) {
      for (auto key : map->keys()) {
        (*env)[variables[0]] = key;
        (*env)[variables[1]] = map->at(key);
        val = body->perform(this);
        if (val) break;
      }
    }
    else {
      for (size_t i = 0, L = list->length(); i < L; ++i) {
        List* variable = 0;
        if ((*list)[i]->concrete_type() != Expression::LIST || variables.size() == 1) {
          variable = new (ctx.mem) List((*list)[i]->path(), (*list)[i]->position(), 1, List::COMMA);
          *variable << (*list)[i];
        }
        else {
          variable = static_cast<List*>((*list)[i]);
        }
        for (size_t j = 0, K = variables.size(); j < K; ++j) {
          if (j < variable->length()) {
            (*env)[variables[j]] = (*variable)[j];
          }
          else {
            (*env)[variables[j]] = new (ctx.mem) Null(expr->path(), expr->position());
          }
          val = body->perform(this);
          if (val) break;
        }
        if (val) break;
      }
    }
    env = new_env.parent();
    return val;
  }

  Expression* Eval::operator()(While* w)
  {
    Expression* pred = w->predicate();
    Block* body = w->block();
    while (*pred->perform(this)) {
      Expression* val = body->perform(this);
      if (val) return val;
    }
    return 0;
{'fraction_non_alphanumeric': 0.19250409480682146, 'fraction_numerical': 0.005395510164755757, 'mean_word_length': 2.5043889264010804, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 153, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '150267', 'n_tokens_mistral': 3609, 'n_tokens_neox': 3529, 'n_words': 892}