<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -85,13 +85,13 @@ For the source:
 
 Bus Scheme is currently missing pieces of functionality:
 
-=== Bugs
-* REPL should accept multiline strings
-
 === Parser
-* parse character literals
-* parse dotted cons cells
-* Ruby blocks
+* character literals
+* multiline strings
+* escape sequences in strings
+* string interpolation
+* dotted cons cells
+* Ruby blocks?
 * XML literals?
 
 === General</diff>
      <filename>README.txt</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ if ARGV.empty?
 elsif ARGV.first == '-e' and ARGV.length == 2
   puts BusScheme.eval_string(ARGV[1])
 elsif ARGV.length == 1 and File.exist?(ARGV.first)
-  puts BusScheme.eval_string &quot;(load \&quot;#{ARGV.first}\&quot;)&quot;
+  puts BusScheme.eval_string(&quot;(load \&quot;#{ARGV.first}\&quot;)&quot;)
 else
   puts &quot;Bus Scheme: a scheme interpreter written on the bus.
 Usage: bus [file | -e \&quot;form\&quot;]</diff>
      <filename>bin/bus</filename>
    </modified>
    <modified>
      <diff>@@ -20,15 +20,29 @@ module BusScheme
   VERSION = &quot;0.7.5&quot;
 
   PROMPT = '&gt; '
+  INCOMPLETE_PROMPT = ' ... '
   LOAD_PATH = [&quot;#{File.dirname(__FILE__)}/scheme/&quot;]
   
+  class BusSchemeError &lt; StandardError; end
+  class ParseError &lt; BusSchemeError; end
+  class EvalError &lt; BusSchemeError; end
+  class LoadError &lt; BusSchemeError; end
+  class IncompleteError &lt; BusSchemeError; end
+  class ArgumentError &lt; BusSchemeError; end
+  class AssertionFailed &lt; BusSchemeError; end
+
   # Read-Eval-Print-Loop
   def self.repl
     loop do
       puts begin
              input = Readline.readline(PROMPT)
              exit if input.nil? # only Ctrl-D produces nil here it seems
-             BusScheme.eval_string input
+             begin # allow for multiline input
+               BusScheme.eval_string input
+             rescue IncompleteError
+               input += &quot;\n&quot; + Readline.readline(INCOMPLETE_PROMPT)
+               retry
+             end
            rescue Interrupt
              'Type &quot;(quit)&quot; or press Ctrl-D to leave Bus Scheme.'
            rescue BusSchemeError =&gt; e</diff>
      <filename>lib/bus_scheme.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,8 +21,14 @@ module BusScheme
                end
 
       @scope = RecursiveHash.new(locals, @enclosing_scope)
-      @@stack &lt;&lt; self
-      BusScheme.eval(@body.unshift(:begin.sym)).affect { @@stack.pop }
+      # we dupe the lambda so that @scope is unique for each call of the function
+      @@stack &lt;&lt; self.dup
+      
+      begin
+        return BusScheme.eval(@body.unshift(:begin.sym))
+      ensure
+        @@stack.pop
+      end
     end
 
     # What's the current scope?
@@ -47,7 +53,7 @@ module BusScheme
     end
 
     # where were we called from?
-    def self.trace
+    def self.stacktrace
       @@stack.reverse.map { |fn| [fn.symbol, fn.file, fn.line] }
     end
   end</diff>
      <filename>lib/lambda.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,13 +11,13 @@ module BusScheme
       parse_tokens(tokenize(input).flatten).sexp
     end
 
-    # Turn a list of tokens into a properly-nested S-expression
+    # Turn a list of tokens into a properly-nested array
     def parse_tokens(tokens)
       token = tokens.shift
       if token == :'('
         parse_list(tokens)
       else
-        raise BusScheme::ParseError unless tokens.empty?
+        raise ParseError unless tokens.empty?
         token # atom
       end
     end
@@ -32,7 +32,7 @@ module BusScheme
             list &lt;&lt; element
           end
         end
-        raise ParseError unless element == :')'
+        raise IncompleteError unless element == :')'
       end
     end
 </diff>
      <filename>lib/parser.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,13 +1,6 @@
 module BusScheme
   SYMBOL_TABLE = {}
 
-  class BusSchemeError &lt; StandardError; end
-  class ParseError &lt; BusSchemeError; end
-  class EvalError &lt; BusSchemeError; end
-  class LoadError &lt; BusSchemeError; end
-  class ArgumentError &lt; BusSchemeError; end
-  class AssertionFailed &lt; BusSchemeError; end
-
   def self.define(identifier, value)
     SYMBOL_TABLE[identifier.sym] = value
   end
@@ -32,7 +25,8 @@ module BusScheme
   define 'map', lambda { |fn, list| list.map(lambda { |n| fn.call(n) }).sexp }
   
   define 'eval', lambda { |code| eval(code) }
-
+  define 'stacktrace', lambda { Lambda.stacktrace }
+  
   define 'ruby', lambda { |*code| Kernel.eval code.join('') }
   define 'send', lambda { |obj, *message| obj.send(*message) }
 </diff>
      <filename>lib/primitives.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,11 @@ $LOAD_PATH &lt;&lt; File.dirname(__FILE__)
 require 'test_helper'
 
 class BusScheme::Lambda
-  attr_accessor :body, :formals, :environment
+  attr_accessor :body, :formals, :enclosing_scope
+
+  def self.stack
+    @@stack
+  end
 end
 
 class BusSchemeLambdaTest &lt; Test::Unit::TestCase
@@ -67,15 +71,14 @@ class BusSchemeLambdaTest &lt; Test::Unit::TestCase
   (f (quote b))))&quot;
   end
 
-#   def test_args_work_right
-#     eval &quot;(define fib (lambda (x)
-#               (ruby \&quot;p Lambda.scope\&quot;)
-#               (assert (&gt; x 0))
-# 	      (if (&lt; x 3)
-# 		  1
-#                  (+ (fib (- x 1)) (fib (- x 2))))))&quot;
-#     assert_evals_to 3, &quot;(fib 3)&quot;
-#   end
+  def test_nested_function_calls_dont_affect_caller
+    eval &quot;(define fib (lambda (x)
+	      (if (&lt; x 3)
+		  1
+                 (+ (fib (- x 1)) (fib (- x 2))))))&quot;
+
+    assert_evals_to 5, &quot;(fib 5)&quot;
+  end
 
   def test_lambda_rest_args
     eval &quot;(define rest (lambda args args))&quot;
@@ -104,4 +107,16 @@ class BusSchemeLambdaTest &lt; Test::Unit::TestCase
     eval &quot;#{&quot;\n&quot; * 7} (define fab 'warble)&quot;
     assert_equal 7, Lambda[:fab.sym].line
   end
+
+  def test_stack_gets_popped
+    # TODO: 
+  end
+  
+  def test_stacktrace
+    eval &quot;(define gimme-trace (lambda () (stacktrace)))&quot;
+    eval &quot;(define nest-trace (lambda () (gimme-trace)))&quot;
+    assert_equal([[:'gimme-trace'.sym, &quot;(eval)&quot;, 0],
+                  [:'nest-trace'.sym, &quot;(eval)&quot;, 0]],
+                 eval(&quot;(nest-trace)&quot;))
+  end
 end</diff>
      <filename>test/test_lambda.rb</filename>
    </modified>
    <modified>
      <diff>@@ -120,8 +120,8 @@ class BusSchemeParserTest &lt; Test::Unit::TestCase
   end
 
   def test_requires_closed_lists
-    assert_raises(ParseError) { BusScheme.parse &quot;(+ 2 2&quot; }
-    assert_raises(ParseError) { BusScheme.parse &quot;(+ (* 3 4) 2 2&quot; }
+    assert_raises(IncompleteError) { BusScheme.parse &quot;(+ 2 2&quot; }
+    assert_raises(IncompleteError) { BusScheme.parse &quot;(+ (* 3 4) 2 2&quot; }
   end
   
 #   def test_reject_bad_identifiers</diff>
      <filename>test/test_parser.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>a325e01c5c88841c3f8299c39dfb8ca6bddc5d01</id>
    </parent>
  </parents>
  <author>
    <name>Phil Hagelberg</name>
    <email>phil@hagelb.org</email>
  </author>
  <url>http://github.com/technomancy/bus-scheme/commit/a3eb301a001dc8c18c8eb51fd4f18e71be9a9a89</url>
  <id>a3eb301a001dc8c18c8eb51fd4f18e71be9a9a89</id>
  <committed-date>2008-02-12T19:58:34-08:00</committed-date>
  <authored-date>2008-02-12T19:58:34-08:00</authored-date>
  <message>recursion fixes</message>
  <tree>5718ca21e63ccfc35bcbe3ddccc9bcd1c25abc62</tree>
  <committer>
    <name>Phil Hagelberg</name>
    <email>phil@hagelb.org</email>
  </committer>
</commit>
