;(function(exports) {
  var library = {
    first: function(x) {
      return x[0];
    },
    rest: function(x) {
      return x.slice(1);
    },
    print: function(x) {
      console.log(x);
      return x;
    }
  };

  var Ctx = function(scope, parent) {
    this.scope = scope;
    this.parent = parent;
    this.get = function(identifier) {
      if (identifier in this.scope) {
        return this.scope[identifier];
      } else if (this.parent !== undefined) {
        return this.parent.get(identifier);
      }
    };
  };

  var special = {
    let: function(input, ctx) {
      var letCtx = new Ctx({}, ctx);
      input[1].forEach(function(binding) {
        var name = binding[0].value;
        var init = binding[1];
        letCtx.scope[name] = interpret(init, ctx);
      });
      return interpret(input[2], letCtx);
    },

    lambda: function(input, ctx) {
      return {
        type: "function",
        value: function(args) {
          var lambdaScope = input[1].reduce(function(acc, x, i) {
          acc[x.value] = args[i];
            return acc;
          }, {});
          return interpret(input[2], new Ctx(lambdaScope, ctx));
        }
      };
    },

    if: function(input, ctx) {
      return interpret(input[1], ctx) ? interpret(input[2], ctx) : interpret(input[3], ctx);
    }
  };

  var fn = function(input, ctx) {
    return {
      type: "function",
      value: function(args) {
        return ctx.get(input.value).apply(undefined, args);
      }
    };
  };

  var interpret = function(input, ctx) {
    if (ctx === undefined) {
      return interpret(input, new Ctx(library));
    } else if (input instanceof Array) {
      if (input[0].value in special) {
        return special[input[0].value](input, ctx);
      } else {
        var list = input.map(function(x) { return interpret(x, ctx); });
        if (list[0].type === "function") {
          return list[0].value(list.slice(1));
        } else {
          return list;
        }
      }
    } else if (input.type === "identifier") {
      if (ctx.get(input.value) instanceof Function) { // prepare fn
        return fn(input, ctx);
      } else { // var lookup
        return ctx.get(input.value);
      }
    } else { // literal
      return input.value;
    }
  };

  var categorize = function(input) {
    if (input instanceof Array) {
      return input.map(categorize);
    } else { // atom
      if (!isNaN(parseFloat(input))) {
        return { type:'literal', value: parseFloat(input) };
      } else if (input[0] === '"' && input.slice(-1) === '"') {
        return { type:'literal', value: input.slice(1, -1) };
      } else {
        return { type:'identifier', value: input };
      }
    }
  };

  var atDepth = function(output, depth) {
    if (depth === 0) {
      return output;
    } else {
      return atDepth(output[output.length - 1], depth - 1);
    }
  };

  var parenthesize = function(input) {
    var output = [];
    var depth = 0;
    input.forEach (function(token) {
      if (token === "(") {
        atDepth(output, depth++).push([]);
      } else if (token === ")") {
        depth--;
      } else {
        atDepth(output, depth).push(token);
      }
    });

    return output.pop();
  };

  var tokenize = function(input) {
    return input.split('"').map(function(x, i) {
                   return i % 2 === 0 ? x : x.replace(/ /g, "!!!!!!!!!!!!");
                 }).join('"')
                .replace(/\(/g, ' ( ')
                .replace(/\)/g, ' ) ')
                .trim()
                .split(/\s+/)
                .map(function(x) {
                  return x.replace(/!!!!!!!!!!!!/g, " ");
                });
  };

  var parse = function(input) {
    return categorize(parenthesize(tokenize(input)));
  };

  exports.tinyLisp = {};
  exports.tinyLisp.parse = parse;
  exports.tinyLisp.interpret = interpret;
})(typeof exports === 'undefined' ? this : exports);

@@ -1513,16 +1513,21 @@
 nterpret
+Array
  = funct
@@ -1548,129 +1548,8 @@
 ) %7B%0A
-    if (ctx === undefined) %7B%0A      return interpret(input, new Ctx(library));%0A    %7D else if (input instanceof Array) %7B%0A  
     
@@ -1577,26 +1577,24 @@
  special) %7B%0A
-  
       return
@@ -1627,34 +1627,32 @@
 nput, ctx);%0A    
- 
- 
 %7D else %7B%0A       
@@ -1640,26 +1640,24 @@
    %7D else %7B%0A
-  
       var li
@@ -1711,26 +1711,24 @@
 , ctx); %7D);%0A
-  
       if (li
@@ -1756,34 +1756,32 @@
 ion%22) %7B%0A        
-  
 return list%5B0%5D.v
@@ -1797,26 +1797,24 @@
 .slice(1));%0A
-  
       %7D else
@@ -1820,26 +1820,24 @@
 e %7B%0A        
-  
 return list;
@@ -1847,70 +1847,77 @@
     
-  
 %7D%0A    
- 
- 
 %7D%0A
-  
   %7D
- else if (input.type === %22identifier%22
+;%0A%0A  var interpretIdentifier = function(input, ctx
 ) %7B%0A    
   if
@@ -1912,22 +1912,23 @@
 ) %7B%0A    
-  if (
+return 
 ctx.get(
@@ -1959,19 +1959,41 @@
 Function
+ ?%0A      fn(input, ctx
 ) 
-%7B
+:
  // prep
@@ -2009,18 +2009,75 @@
     
-  return f
+ctx.get(input.value); // var lookup%0A  %7D;%0A%0A  var interpret = functio
 n(in
@@ -2089,83 +2089,262 @@
 ctx)
-;
+ %7B
 %0A    
-  %7D else %7B // var lookup%0A        return ctx.get(input.value);%0A      %7D
+if (ctx === undefined) %7B%0A      return interpret(input, new Ctx(library));%0A    %7D else if (input instanceof Array) %7B%0A      return interpretArray(input, ctx);%0A    %7D else if (input.type === %22identifier%22) %7B%0A      return interpretIdentifier(input, ctx);
 %0A   

Split interpret() into sub functions for arrays and identifiers.