public
Description: a Scheme written in Ruby, but implemented on the bus!
Homepage: http://bus-scheme.rubyforge.org
Clone URL: git://github.com/technomancy/bus-scheme.git
horribly broken! but apply doesn't assume arg lists are arrays
technomancy (author)
Fri May 30 14:00:08 -0700 2008
commit  e2e38bb3a579bff528af27c7b56b410e678b8ab4
tree    1e5a5306b20f55e3c799a58530add4551f57dc9a
parent  3b49e639fb50a3f9a29d2dc17f62063c01041201
...
79
80
81
82
83
 
 
84
85
86
...
79
80
81
 
 
82
83
84
85
86
0
@@ -79,8 +79,8 @@ module BusScheme
0
     (@loaded_files ||= ["(eval)"])
0
   end
0
 
0
- ['core.scm', 'test.scm', 'list.scm', 'predicates.scm'
0
- ].each { |f| load(f) }
0
+# ['core.scm', 'test.scm', 'list.scm', 'predicates.scm'
0
+# ].each { |f| load(f) }
0
 end
0
 
0
 begin
...
10
11
12
13
 
14
15
16
...
21
22
23
24
25
26
27
 
 
28
29
 
30
31
32
...
10
11
12
 
13
14
15
16
...
21
22
23
 
24
 
 
25
26
27
 
28
29
30
31
0
@@ -10,7 +10,7 @@ module BusScheme
0
 
0
   # Eval a form passed in as an array
0
   def eval(form)
0
- if (form.is_a?(Cons) or form.is_a?(Array)) and form.first
0
+ if (form.is_a?(Cons)) and form.first
0
       apply(form.first, form.rest)
0
     elsif form.is_a? Sym
0
       self[form.sym]
0
@@ -21,12 +21,11 @@ module BusScheme
0
 
0
   # Call a function with given args
0
   def apply(function_sym, args)
0
- args = args.to_a
0
     function = eval(function_sym)
0
- args.map!{ |arg| eval(arg) } unless function.special_form
0
- puts ' ' * stack.length + Cons.new(function_sym, args.sexp).inspect if (@trace ||= false)
0
+ args = args.map { |arg| eval(arg) } unless function.special_form
0
+ puts ' ' * stack.length + Cons.new(function_sym, args).inspect if (@trace ||= false)
0
 
0
- function.call_as function_sym, *args
0
+ function.call_as function_sym, args
0
   end
0
 
0
   # Scoping methods:
...
38
39
40
41
 
42
43
44
45
 
46
47
48
...
68
69
70
71
 
72
73
74
75
76
 
77
78
79
...
38
39
40
 
41
42
43
44
 
45
46
47
48
...
68
69
70
 
71
72
73
74
75
 
76
77
78
79
0
@@ -38,11 +38,11 @@ class BusSchemeEvalTest < Test::Unit::TestCase
0
   end
0
 
0
   def test_blows_up_with_undefined_symbol
0
- assert_raises(EvalError) { eval("undefined-symbol") }
0
+ assert_raises(EvalError) { eval!("undefined-symbol") }
0
   end
0
 
0
   def test_variable_substitution
0
- eval "(define foo 7)"
0
+ eval! "(define foo 7)"
0
     assert_evals_to 7, :foo.sym
0
     assert_evals_to 21, [:*.sym, 3, :foo.sym]
0
   end
0
@@ -68,12 +68,12 @@ class BusSchemeEvalTest < Test::Unit::TestCase
0
 
0
   def test_eval_multiple_forms
0
     assert_raises(EvalError) do
0
- BusScheme.eval_string "(+ 2 2) (undefined-symbol)"
0
+ eval! "(+ 2 2) (undefined-symbol)"
0
     end
0
   end
0
 
0
   def test_define_after_load
0
- BusScheme.eval_string "(load \"#{File.dirname(__FILE__)}/../examples/fib.scm\")
0
+ eval! "(load \"#{File.dirname(__FILE__)}/../examples/fib.scm\")
0
 (define greeting \"hi\")"
0
     assert BusScheme.in_scope?(:greeting.sym)
0
   end
...
1
2
3
4
5
 
 
 
 
 
6
7
8
...
18
19
20
21
 
22
23
24
...
35
36
37
38
 
39
40
41
...
49
50
51
52
 
53
54
55
...
58
59
60
61
 
62
63
 
64
65
66
...
 
 
 
 
 
1
2
3
4
5
6
7
8
...
18
19
20
 
21
22
23
24
...
35
36
37
 
38
39
40
41
...
49
50
51
 
52
53
54
55
...
58
59
60
 
61
62
 
63
64
65
66
0
@@ -1,8 +1,8 @@
0
-begin
0
- require 'rubygems'
0
- gem 'miniunit'
0
-rescue LoadError
0
-end
0
+# begin
0
+# require 'rubygems'
0
+# gem 'miniunit'
0
+# rescue LoadError
0
+# end
0
 
0
 $LOAD_PATH << File.dirname(__FILE__) + '/../lib/'
0
 require 'test/unit'
0
@@ -18,7 +18,7 @@ module BusScheme
0
     @@stack = []
0
   end
0
   
0
- def trace=(tr)
0
+ def self.trace=(tr)
0
     @trace = tr
0
   end
0
 end
0
@@ -35,7 +35,7 @@ class Test::Unit::TestCase
0
   include BusScheme
0
 
0
   # convenience method that accepts string or form
0
- def eval(form)
0
+ def eval!(form)
0
     begin
0
       if form.is_a?(String)
0
         BusScheme.eval_string(form)
0
@@ -49,7 +49,7 @@ class Test::Unit::TestCase
0
   end
0
 
0
   def assert_evals_to(expected, form)
0
- assert_equal expected, eval(form)
0
+ assert_equal expected, eval!(form)
0
   end
0
 
0
   # remove symbols from all scopes
0
@@ -58,9 +58,9 @@ class Test::Unit::TestCase
0
   end
0
 
0
   # Run the provided block with tracing on
0
- def trace &block
0
+ def trace
0
     BusScheme.trace = true
0
- block.call
0
+ yield
0
   rescue
0
     BusScheme.trace = false
0
   end
...
3
4
5
6
 
7
8
9
10
11
 
12
13
14
15
16
17
 
18
19
20
...
23
24
25
26
 
27
28
29
30
31
32
 
33
34
35
36
37
38
39
40
 
 
41
42
43
44
45
46
 
47
48
 
49
50
51
52
53
54
 
55
56
57
58
 
59
60
61
...
82
83
84
85
 
86
87
88
...
92
93
94
95
 
96
97
98
99
100
101
 
 
102
103
104
105
106
107
108
 
109
110
111
112
113
114
 
115
116
 
117
118
119
120
121
122
 
123
124
125
...
127
128
129
 
 
 
 
 
 
 
 
130
...
3
4
5
 
6
7
8
9
10
 
11
12
13
14
15
16
 
17
18
19
20
...
23
24
25
 
26
27
28
29
30
31
 
32
33
34
35
36
37
38
 
 
39
40
41
42
43
44
45
 
46
47
 
48
49
50
51
52
53
 
54
55
56
57
 
58
59
60
61
...
82
83
84
 
85
86
87
88
...
92
93
94
 
95
96
97
98
99
 
 
100
101
102
103
104
105
106
107
 
108
109
110
111
112
113
 
114
115
 
116
117
118
119
120
121
 
122
123
124
125
...
127
128
129
130
131
132
133
134
135
136
137
138
0
@@ -3,18 +3,18 @@ require 'test_helper'
0
 
0
 class BusSchemeLambdaTest < Test::Unit::TestCase
0
   def test_simple_lambda
0
- l = eval("(lambda () (+ 1 1))")
0
+ l = eval!("(lambda () (+ 1 1))")
0
     assert l.is_a?(Lambda)
0
     assert_equal [[:+.sym, 1, 1].to_list], l.body
0
     assert_equal 0, l.formals.length
0
 
0
- eval("(define foo (lambda () (+ 1 1)))")
0
+ eval!("(define foo (lambda () (+ 1 1)))")
0
     assert BusScheme[:foo.sym].is_a?(Lambda)
0
     assert_evals_to 2, [:foo.sym]
0
   end
0
 
0
   def test_lambda_with_arg
0
- eval("(define foo (lambda (x) (+ x 1)))")
0
+ eval!("(define foo (lambda (x) (+ x 1)))")
0
     assert_evals_to 2, "(foo 1)"
0
   end
0
 
0
@@ -23,39 +23,39 @@ class BusSchemeLambdaTest < Test::Unit::TestCase
0
   end
0
 
0
   def test_lambda_with_incorrect_arity
0
- eval("(define foo (lambda (x) (+ x 1)))")
0
+ eval!("(define foo (lambda (x) (+ x 1)))")
0
     assert_raises(ArgumentError) { assert_evals_to 2, "(foo 1 3)" }
0
   end
0
 
0
   def test_lambda_args_dont_stay_in_scope
0
     clear_symbols(:x, :foo)
0
- eval("(define foo (lambda (x) (+ x 1)))")
0
+ eval!("(define foo (lambda (x) (+ x 1)))")
0
     assert ! BusScheme.in_scope?(:x)
0
     assert_evals_to 2, "(foo 1)"
0
     assert ! BusScheme.in_scope?(:x)
0
   end
0
 
0
   def test_lambda_calls_lambda
0
- eval "(define f (lambda (x) (+ 3 x)))"
0
- eval "(define g (lambda (y) (* 3 y)))"
0
+ eval! "(define f (lambda (x) (+ 3 x)))"
0
+ eval! "(define g (lambda (y) (* 3 y)))"
0
     assert_evals_to 12, "(f (g 3))"
0
     assert_evals_to 1, "((lambda () ((lambda () 1))))"
0
   end
0
 
0
   def test_enforces_arg_count
0
- assert_equal 3, eval("(lambda (x y z) z)").formals.size
0
+ assert_equal 3, eval!("(lambda (x y z) z)").formals.size
0
     assert_raises(ArgumentError) do
0
- eval "((lambda (x) x))"
0
+ eval! "((lambda (x) x))"
0
     end
0
   end
0
   
0
   def test_lambda_closures
0
     assert_evals_to 3, "((lambda (x) ((lambda (y) 3) 1)) 1)"
0
- eval "(define foo (lambda (xx) ((lambda (y) (+ xx y)) (* xx 2))))"
0
+ eval! "(define foo (lambda (xx) ((lambda (y) (+ xx y)) (* xx 2))))"
0
     assert foo = BusScheme[:foo.sym]
0
     
0
     assert_evals_to 3, foo.call(1)
0
- eval "(define holder ((lambda (x) (lambda () x)) 2))"
0
+ eval! "(define holder ((lambda (x) (lambda () x)) 2))"
0
     assert_evals_to 2, "(holder)"
0
   end
0
 
0
@@ -82,7 +82,7 @@ class BusSchemeLambdaTest < Test::Unit::TestCase
0
   end
0
 
0
   def test_nested_function_calls_dont_affect_caller
0
- eval "(define fib (lambda (x)
0
+ eval! "(define fib (lambda (x)
0
    (if (< x 3)
0
      1
0
                  (+ (fib (- x 1)) (fib (- x 2))))))"
0
@@ -92,34 +92,34 @@ class BusSchemeLambdaTest < Test::Unit::TestCase
0
   end
0
 
0
   def test_lambda_rest_args
0
- eval "(define rest (lambda args args))"
0
+ eval! "(define rest (lambda args args))"
0
     assert_evals_to [:a.sym, :b.sym, :c.sym].to_list, "(rest 'a 'b 'c)"
0
   end
0
 
0
   def test_stacktrace
0
- eval '(load "test/tracer.scm")'
0
- assert_equal ["(eval):1 in top-level"], eval("(stacktrace)")
0
+ eval! '(load "test/tracer.scm")'
0
+ assert_equal ["(eval):1 in top-level"], eval!("(stacktrace)")
0
     
0
     assert_equal(["test/tracer.scm:1 in f",
0
                   "test/tracer.scm:4 in g",
0
                   "(eval):1 in (anonymous)",
0
                   "(eval):0 in top-level"
0
                  ],
0
- eval("((lambda () (g)))"))
0
+ eval!("((lambda () (g)))"))
0
   end
0
 
0
   # TODO: check the stack traces that the scheme tests give
0
 
0
   def test_stack_grows
0
- eval "(define stack-growth
0
+ eval! "(define stack-growth
0
 (lambda () (ruby \"raise 'wtf' if BusScheme.stack.size < 1\")))"
0
- eval "(stack-growth)"
0
+ eval! "(stack-growth)"
0
   end
0
 
0
   def test_primitives_live_on_stack
0
     BusScheme.define 'stack-growth', BusScheme.primitive { assert BusScheme.stack.size > 1 }
0
     assert SYMBOL_TABLE.has_key?('stack-growth'.sym)
0
- eval "(stack-growth)"
0
+ eval! "(stack-growth)"
0
   end
0
 
0
   def test_array_to_hash
0
@@ -127,4 +127,12 @@ class BusSchemeLambdaTest < Test::Unit::TestCase
0
     assert_equal [1, 2, 3, 4, 5, 6], a.flatten_non_recursive
0
     assert_equal({ 1 => 2, 3 => 4, 5 => 6 }, a.to_hash)
0
   end
0
+
0
+ def test_lambdas_accept_list_of_args
0
+ BusScheme['prim'] = Primitive.new(lambda { |args| assert args.is_a?(Cons) })
0
+ BusScheme['prim'].call(cons(1))
0
+
0
+ apply(:prim.sym, cons(1, cons(2)))
0
+ # lamb = Lambda.new
0
+ end
0
 end

Comments

    No one has commented yet.