         if node.argument.type is 'Identifier'
           env.insert node.argument.name, newValue
         else if node.argument.type is 'MemberExpression'
-          await evalMemberExpr node.argument, env, defer(e, result)
-          return cont(e) if e?
-          [object, property] = result
+          await evalMemberExpr node.argument, env, defer(object, property), errCont
           object[property] = newValue
-        if node.prefix
-          return cont(null, newValue)
-        else
-          return cont(null, original)
+        cont(if node.prefix then newValue else original)
       when 'UnaryExpression'
         if node.operator is 'delete'
           if node.argument.type is 'MemberExpression'
-            await evalMemberExpr node.argument, env, defer(e, result)
-            return cont(e) if e?
-            [object, property] = result
-            return cont(null, delete object[property])
-          else
-            throw "NYI"
-        else
-          await interp node.argument, env, defer(e, arg)
-          return cont(e) if e?
+            await evalMemberExpr node.argument, env, defer(object, property), errCont
+            cont(delete object[property])
+          else
+            errCont "NYI"
+        else
+          await interp node.argument, env, defer(arg), errCont
           switch node.operator
             when '-'
-              return cont(null, -arg)
+              cont(-arg)
             when '~'
-              return cont(null, ~arg)
+              cont(~arg)
             when '!'
-              return cont(null, !arg)
+              cont(!arg)
             when 'typeof'
-              return cont(null, typeof arg)
+              cont(typeof arg)
             else
-              return cont("NYI")
+              errCont("NYI")
       #*** Identifiers and Literals ***#
       when 'Identifier'
-        return cont(null, env.resolve node.name)
+        cont(env.resolve node.name)
       when 'MemberExpression'
-        await evalMemberExpr node, env, defer(e, result)
-        return cont(e) if e?
-        [object, property] = result
-        return cont(null, object[property])
+        await evalMemberExpr node, env, defer(object, property), errCont
+        cont(object[property])
       when 'ThisExpression'
-        return cont(null, env.resolve 'this')
+        cont(env.resolve 'this')
       when 'Literal'
-        return cont(null, node.value)
+        cont(node.value)
       when 'ObjectExpression'
         obj = {}
         for prop in node.properties
-          await interp prop.value, env, defer(e, propValue)
-          return cont(e) if e?
+          await interp prop.value, env, defer(propValue), errCont
           obj[prop.key.name ? prop.key.value] = propValue
-        return cont(null, obj)
+        cont(obj)
       when 'ArrayExpression'
-        arr = []
-        for el in node.elements
-          await interp el, env, defer(e, elValue)
-          return cont(e) if e?
-          arr.push elValue
-        return cont(null, arr)
+        cont(
+          for el in node.elements
+            await interp el, env, defer(elValue), errCont)
       else
         console.log "Unrecognized node!"
         console.log node
-        return cont('Unrecognized node!')
+        errCont('Unrecognized node!')
   catch e
     unless e instanceof InterpreterException
       console.log "Line #{node.loc.start.line}: Error in #{node.type}"
-    return cont(e)
-
-evalMemberExpr = (node, env, cont) ->
-  await interp node.object, env, defer(e, object)
-  return cont(e) if e?
+    errCont(e)
+  return
+
+evalMemberExpr = (node, env, cont, errCont) ->
+  await interp node.object, env, defer(object), errCont
   propNode = node.property
   if propNode.type is 'Identifier' and not node.computed
-    cont(null, [object, propNode.name])
+    cont(object, propNode.name)
   else
-    await interp propNode, env, defer(e, property)
-    return cont(e, [object, property])
-
-assign = (node, value, env, cont) ->
+    await interp propNode, env, defer(property), errCont
+    cont(object, property)
+
+assign = (node, value, env, cont, errCont) ->
   if node.type is 'Identifier'
     try
       env.update node.name, value
     catch e
       env.globalInsert node.name, value
-    return cont(null, value)
+    cont(value)
   else if node.type is 'MemberExpression'
-    await evalMemberExpr node, env, defer(e, result)
-    return cont(e) if e?
-    [object, property] = result
+    await evalMemberExpr node, env, defer(object, property), errCont
     object[property] = value
-    return cont(null, value)
+    cont(value)
   else
-    return cont("Invalid LHS in assignment")
+    errCont("Invalid LHS in assignment")
+
+makeLoopCont = (body, env, bodyCont, cont, errCont) ->
+  (e) ->
+    if e instanceof BreakException
+      cont()
+    else if e instanceof ContinueException
+      bodyCont()
+    else
+      errCont(e)
 
 toplevel = ->
   repl = require 'repl'
   env = new Environment
   repl.start
     eval: (cmd, ctx, filename, callback) ->
-      await interp (esprima.parse cmd[1..-2], loc: true), env, defer(e, result)
-      callback null, e ? result
+      await interp (esprima.parse cmd[1..-2], loc: true), env, callback, callback
 
 if require.main is module
   {argv} = require 'optimist'

            else
              null
          if fnName is 'eval'
            await interp ast, env, defer(e, result)
            return cont(e, result)
          else
            await interp ast, env.getGlobalEnv(), defer(e, result)
            return cont(e, result)
        else
          if callee instanceof InterpretedFunction
            await callee.applyCps _this, args, defer(e, applied)
            return cont(e) if e?
            return cont(null, applied)
          else
            applied = callee.apply _this, args
            return cont(null, applied)
      when 'NewExpression'
        await interp node.callee, env, defer(e, callee)
        return cont(e) if e?
        args = []
        for arg in node.arguments
          await interp(arg, env, defer(e, result))
          return cont(e) if e?
          args.push(result)
        if callee.__ctor__?
          obj = new callee.__ctor__
          if callee instanceof InterpretedFunction
            await callee.applyCps obj, args, defer(e, result)
            return cont(e) if e?
          else
            callee.apply obj, args
        else
          if callee instanceof InterpretedFunction
            await callee.bind.applyCps callee, ([null].concat args), defer(e, result)
            return cont(e) if e?
          else
            obj = new (callee.bind.apply callee, [null].concat args)
        return cont(null, obj)
      #*** Control Flow ***#
      when 'IfStatement'
        await interp node.test, env, defer(e, test)
        return cont(e) if e?
        if (test)
          await interp node.consequent, env, defer(e, result)
          return cont(e, result)
        else if node.alternate?
          await interp node.alternate, env, defer(e, result)
          return cont(e, result)
        else
          return cont()
      when 'WhileStatement'
        while (true)
          # Test
          await interp node.test env, defer(e, test)
          return cont(e) if e?
          return cont() if not test
          # Body
          await interp node.body, env, defer(e)
          return cont() if e instanceof BreakException
          return cont(e) if e? and not (e instanceof ContinueException)
        return cont()
      when 'DoWhileStatement'
        while (true)
          # Body
          await interp node.body, env, defer(e)
          return cont() if e instanceof BreakException
          return cont(e) if e? and not (e instanceof ContinueException)
          # Test
          await interp node.test, env, defer(e, test)
          return cont(e) if e?
          return cont() if not test
        return cont()
      when 'ForStatement'
        await interp node.init, env, defer(e)
        return cont(e) if e?
        while (true)
          # Test
          await interp node.test, env, defer(e, test)
          return cont(e) if e?
          return cont() if not test
          # Body
          await interp node.body, env, defer(e)
          return cont() if e instanceof BreakException
          return cont(e) if e? and not (e instanceof ContinueException)
          # Update
          await interp node.update, env, defer(e)
          return cont() if e instanceof BreakException
          return cont(e) if e? and not (e instanceof ContinueException)
      when 'ForInStatement'
        await interp node.left, env, defer(e)
        return cont(e) if e?
        await interp node.right, env, defer(e, obj)
        return cont(e) if e?
        for k of obj
          if node.left.type is 'VariableDeclaration'
            await assign node.left.declarations[0].id, k, env, defer(e, result)
            return cont(e) if e?
          else
            await assign node.left, k, env, defer(e, result)
            return cont(e) if e?
          await interp node.body, env, defer(e)
          return cont(e) if e?
        return cont()
      when 'BreakStatement'
        return cont(new BreakException)
      when 'ContinueStatement'
        return cont(new ContinueException)
      when 'ReturnStatement'
        return cont(new ReturnException undefined) if node.argument is null
        await interp node.argument, env, defer(e, result)
        return cont(e || new ReturnException result)
      when 'ThrowStatement'
        await interp node.argument, env, defer(e, result)
        return cont(e || new JSException result)
      when 'TryStatement'
        await interp node.block, env, defer(errorInTry, result)
        if errorInTry instanceof JSException and node.handlers.length > 0
          catchEnv = env.increaseScope true
          catchEnv.set node.handlers[0].param.name, errorInTry.exception
          await interp node.handlers[0], env, defer(errorInCatch, result)
          env.decreaseScope() # unless errorInCatch?
          if node.finalizer # try->catch->finally
            await interp node.finalizer, env, defer(errorInFinalizer, result)
            return cont(errorInFinalizer || errorInCatch)
          else # try->catch
            return cont(eInCatch)
        else if node.finalizer
          await interp node.finalizer, env, defer(errorInFinalizer, result)
          return cont(errorInFinalizer || errorInTry) # try->finally
        else
          return cont(errorInTry) # try
      when 'CatchClause'
        await interp node.body, env, defer(e, result)
        return cont(e, result)
      #*** Operator Expressions ***#
      when 'BinaryExpression'
        await interp node.left, env, defer(e, lhs)
        return cont(e) if e?
        await interp node.right, env, defer(e, rhs)
        return cont(e) if e?
        switch node.operator
          when '+'
            return cont(null, lhs + rhs)
          when '-'
            return cont(null, lhs - rhs)
          when '*'
            return cont(null, lhs * rhs)
          when '/'
            return cont(null, lhs / rhs)
          when '&'
            return cont(null, lhs & rhs)
          when '|'
            return cont(null, lhs | rhs)
          when '^'
            return cont(null, lhs ^ rhs)
          when '>>'
            return cont(null, lhs >> rhs)
          when '<<'
            return cont(null, lhs << rhs)
          when '>>>'
            return cont(null, lhs >>> rhs)
          when '<'
            return cont(null, lhs < rhs)
          when '>'
            return cont(null, lhs > rhs)
          when '<='
            return cont(null, lhs <= rhs)
          when '>='
            return cont(null, lhs >= rhs)
          when '=='
            return cont(null, `lhs == rhs`)
          when '==='
            return cont(null, `lhs === rhs`)
          when '!='
            return cont(null, `lhs != rhs`)
          when '!=='
            return cont(null, `lhs !== rhs`)
          when 'instanceof'
            return cont(null, lhs instanceof rhs.__ctor__)
          else
            return cont("Unrecognized operator #{node.operator}")
      when 'AssignmentExpression'
        await interp node.right, env, defer(e, value)
        return cont(e) if e?
        if node.operator is '='
          await assign node.left, value, env, defer(e, result)
          return cont(e, result)
        else
          if node.left.type is 'Identifier'
            original = env.resolve node.left.name
          else if node.left.type is 'MemberExpression'
            evalMemberExpr node.left, env, cont(e, result)
            return cont(e) if e?
            [object, property] = result
            original = object[property]
          else
            throw "Invalid LHS in assignment"

  else
    parsed = esprima.parse (fs.readFileSync argv._[0]), loc: true
    # interp parsed, new Environment
    interp parsed, new Environment, (->), (e) ->
      console.log "Error: ", e
      process.exit 1
