Edit in JSFiddle

// eval part
var evaluate = function(x, env) {
  if (Array.isArray(x)) {
    if (x[0] === 'fn') { // 関数作成
      return function() {
        var params = x[1];
        var args = arguments;
        params.forEach(function(param, i) {env[param] = args[i];});
        return evaluate(['do'].concat(x.slice(2)), env);
      };
    } else if (x[0] === 'while') { // whileループ
      while (evaluate(x[1], env)) {
        x.slice(2).forEach(function(a){evaluate(a, env);});
      }
      return null;
    } else if (x[0] === 'def') { // 変数定義
      return env[x[1]] = evaluate(x[2], env);
    } else if (x[0] === 'set!') { // 代入
      return env[x[1]] = evaluate(x[2], env);
    } else if (x[0] === 'if') { // 条件分岐
      return String(evaluate(x[1], env)) !== 'false'
        ? evaluate(x[2], env)
        : evaluate(x[3], env);
    } else { // 関数の実行
      var exps = x.map(function(exp) {return evaluate(exp, env);});
      var proc = exps.shift();
      return proc.apply(null, exps);
    }
  } else {
    var y = env[x];
    return y !== undefined ? y : x;
  }
};
// library
var globalEnv = {
  '+': function(a, b) {return a + b;},
  '-': function(a, b) {return a - b;},
  '*': function(a, b) {return a * b;},
  '/': function(a, b) {return a / b;},
  'mod': function(a, b) {return a % b;},
  'not': function(x) {return !x;},
  '=': function(a, b) {return a === b;},
  '>': function(a, b) {return a > b;},
  '<': function(a, b) {return a < b;},
  '<=': function(a, b) {return a <= b;},
  '>=': function(a, b) {return a >= b;},
  'alert': function(a) {alert(a);},
  'console.log': function() {console.log(arguments);},
  'do': function() {return arguments[arguments.length - 1];}
};
// usage (output to JavaScript console)
console.log(
evaluate([['fn', ['a', 'b'],
            ['+', 'a', 'b']], 2, 3],
         globalEnv)
);