<commit_before>module.exports = function () {
  return {
    schemeEval: function (exp) {


      return loop_run(exp, []);

      function loop_run(exp, stack) {
        // console.log(exp, stack);
        // REMOVE OUTER PARENS

        // RETURN A SINGLE NUMBER, LIKE (3341)
        if (Number(exp)) {
          return Number(exp);
        }

        // RETURN A BOOLEAN
        switch (exp) {
          case '#t':
            return true;
            break;
          case '#f':
            return false;
            break;
        }

        // try to get the innermost list
        try {
          var innerMostRe = /^\(.*(\(.*\))\)$/,
            innerMostExp = exp.match(innerMostRe)[1],
            nextExp = prep(innerMostExp),
            value = inject(nextExp.exp, nextExp.operator);

          console.dir(exp);
          var newExp = exp.replace(innerMostExp, value.toString());

          console.dir(newExp);
          return loop_run(newExp, stack);

        // else...
        } catch(error) {
          console.dir(error);
          // if it's a single list item, return it
          if (exp.match(/^\(\S+\)$/)) {
            return trimParens(exp);
          }

          var injectables = prep(exp);

          return loop_run(inject(injectables.exp, injectables.operator), stack);
        }

        // HELPERS
        function prep (exp) {
          exp = trimParens(exp).split(' ');
          var operator = exp.shift();
          exp = exp.map(function (item) {
            return Number(item);
          });

          return {
            exp: exp,
            operator: operator
          }
        }

        function trimParens (exp) {
          return exp.slice(1, -1);
        }

        // there has got to be a way to do this more elegantly
        function inject (list, operator) {
          switch (operator) {
            case '+':
              return list.reduce(function (x, y) {
                return x + y;
              });

              break;
            case '-':
              return list.reduce(function (x, y) {
                return x - y;
              });

              break;
            case '*':
              return list.reduce(function (x, y) {
                return x * y;
              });

              break;
            case '/':
              return list.reduce(function (x, y) {
                return x / y;
              });

              break;
          }
        }
      }
    }
  }
}<commit_msg>+ - * / nesting and tests<commit_after>module.exports = function () {
  if (!Array.prototype.flatten) {
    Array.prototype.flatten = function () {
      var result = [];
      return result.concat.apply(result, this);
    }
  }

  // split off parens
  if (!Array.prototype.splitParens) {
   Array.prototype.splitParens = function (re) {
      return this.map(function (el) {
        return el.split(re);
      }).flatten();
    }
  }

  function tokenize (exp) {
    var tokens = exp.split(' ');
    var leftParen = /(\()/;
    var rightParen = /(\))/;

    // split parens
    tokens = tokens.splitParens(leftParen).splitParens(rightParen);

    // remove spaces
    tokens = tokens.filter(function (token) {
      return token !== '';
    });

    return tokens;
  }

  function parse (tokens) {
    var token = tokens.shift();

    if (token === '(') {
      var list = [];
      while (tokens[0] !== ')') {
        list.push(parse(tokens));
      }

    return list;
    } else if (token === ')') {
      throw "parenError";
    } else {
      return atom(token);
    }
  }

  function atom (token) {
    if (Number(token) == token) {
      return Number(token);
    }

    return token;
  }

  // MAIN
  return function eval(exp) {
    var stack = parse(tokenize(exp));

    if (typeof stack === 'string') {
      stack = Array(stack);
    }

    // eval loop
    return (function rec (stack) {

      // truthy/numbery base cases
      if (stack.length === 1) {
        var result = stack[0];
        switch (typeof result) {
          case 'string':
            if (result === '#t') {
              return true;
            } else if (result === '#f') {
              return false;
            } else {
              return result;
            }
            break;
          case 'number':
            return result;
            break;
          default:
            return result;
            break;
        }
      }

      // current element
      var current = stack.shift();

      if (Array.isArray(current)) {
        // recurse
        return rec(current);

        // MATH
      } else if (current === '+') {
        var result = mathEval(addRed);

        if (stack.length === 0) {
          return result;
        }

        return result + rec(stack.shift());

      } else if (current === '-') {
        var result = mathEval(subRed);
        if (stack.length === 0) {
          return result;
        }

        return result - rec(stack.shift());

      } else if (current === '*') {
        var result = mathEval(multRed);
        if (stack.length === 0) {
          return result;
        }

        return result * rec(stack.shift());

      } else if (current === '/') {
        var result = mathEval(divRed);

        if (stack.length === 0) {
          return result;
        }

        return result / rec(stack.shift());

      } else if (typeof current === 'number') {
        return rec(stack);
        return current;
      }

      // create math substack, eval what can be eval'd
      function mathEval (opFn) {
        var mathStack = [];
        while (!Array.isArray(stack[0]) && stack.length > 0) {
          mathStack.push(stack.shift());
        }

        return mathStack.reduce(opFn);
      }

      // mathematical operator callbacks for reduce
      function addRed (a, b) { return a + b; }
      function subRed (a, b) { return a - b; }
      function multRed (a, b) { return a * b; }
      function divRed (a, b) { return a / b; }
    })(stack);
  }
}
{'fraction_non_alphanumeric': 0.13637884872824632, 'fraction_numerical': 0.002677376171352075, 'mean_word_length': 1.4071687474828836, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, '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': '1236806', 'n_tokens_mistral': 1762, 'n_tokens_neox': 1689, 'n_words': 438}