af394fe08b0a565b8b0bb0489a8d3bbc9ac2b338 — Tim Morgan 1 year, 8 months ago 11e6d2b
Fix bug defining bindings in a libary
3 files changed, 74 insertions(+), 31 deletions(-)

A spec/lib/define-spec.scm
M spec/vm_spec.rb
M vm.rb
A spec/lib/define-spec.scm => spec/lib/define-spec.scm +18 -0
@@ 0,0 1,18 @@
+(import (scheme base)
+        (assert))
+
+(define (fn1 x) x)
+(define fn2 fn1)
+
+(define-library (define-in-lib-test)
+  (import (only (scheme base) define))
+  (export fn4)
+  (begin
+    (define (fn3 x) x)
+    (define fn4 fn3)))
+
+(import (define-in-lib-test))
+
+(assert (= 'a (fn1 'a)))
+(assert (= 'a (fn2 'a)))
+(assert (= 'a (fn4 'a)))

M spec/vm_spec.rb => spec/vm_spec.rb +55 -30
@@ 1080,44 1080,69 @@
   end
 
   describe 'DEFINE_VAR' do
-    before do
-      subject.execute([
-        VM::PUSH_FUNC,
-        VM::PUSH_STR, 'func.',
-        VM::DEFINE_VAR, 'x',
-        VM::PUSH_VAR, 'x',
-        VM::INT, VM::INT_WRITE,
-        VM::POP,
-        VM::RETURN,
-        VM::ENDF,
-        VM::DEFINE_VAR, 'fn',
+    context do
+      before do
+        subject.execute([
+          VM::PUSH_FUNC,
+          VM::PUSH_STR, 'func.',
+          VM::DEFINE_VAR, 'x',
+          VM::PUSH_VAR, 'x',
+          VM::INT, VM::INT_WRITE,
+          VM::POP,
+          VM::RETURN,
+          VM::ENDF,
+          VM::DEFINE_VAR, 'fn',
 
-        VM::PUSH_VAR, 'fn',
-        VM::CALL,
+          VM::PUSH_VAR, 'fn',
+          VM::CALL,
 
-        VM::PUSH_STR, 'main.',
-        VM::DEFINE_VAR, 'x',
+          VM::PUSH_STR, 'main.',
+          VM::DEFINE_VAR, 'x',
 
-        VM::PUSH_VAR, 'x',
-        VM::INT, VM::INT_WRITE,
-        VM::POP,
+          VM::PUSH_VAR, 'x',
+          VM::INT, VM::INT_WRITE,
+          VM::POP,
 
-        VM::PUSH_VAR, 'fn',
-        VM::CALL,
+          VM::PUSH_VAR, 'fn',
+          VM::CALL,
 
-        VM::HALT
-      ])
-    end
+          VM::HALT
+        ])
+      end
 
-    it 'stores the stack value in given variable index' do
-      expect(subject.local_values['x']).to eq(
-        VM::ByteArray.new('main.')
-      )
+      it 'stores the stack value in given variable index' do
+        expect(subject.local_values['x']).to eq(
+          VM::ByteArray.new('main.')
+        )
+      end
+
+      it 'keeps locals from different call frames separate' do
+        subject.stdout.rewind
+        expect(subject.stdout.read).to eq('func.main.func.')
+      end
     end
 
-    it 'keeps locals from different call frames separate' do
-      subject.stdout.rewind
-      expect(subject.stdout.read).to eq('func.main.func.')
+    context 'inside a library' do
+      before do
+        subject.execute([
+          VM::SET_LIB, 'my-lib',
+          VM::PUSH_FUNC,
+          VM::PUSH_ARG,
+          VM::NAME_ARG, 'x',
+          VM::PUSH_VAR, 'x',
+          VM::RETURN,
+          VM::ENDF,
+          VM::DEFINE_VAR, 'fn3',
+          VM::PUSH_VAR, 'fn3',
+          VM::DEFINE_VAR, 'fn4',
+          VM::ENDL,
+          VM::HALT
+        ])
+      end
+
+      it 'stores the library and does not cause an exception' do
+        expect(subject.libs['my-lib']).to be
+      end
     end
   end
 

M vm.rb => vm.rb +1 -1
@@ 302,7 302,7 @@
   end
 
   def find_call_stack_frame_with_symbol(name)
-    @call_stack.reverse.detect { |f| f[:named_args].key?(name) }
+    @call_stack.reverse.detect { |f| f[:named_args] && f[:named_args].key?(name) }
   end
 
   def build_pair(car, cdr)