bus-scheme 0.7.5 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ ;; Test list functions defined in list.scm
2
+
3
+ (assert-equal (list 1 2) (append (list 1) (list 2)))
4
+
5
+ (assert-equal (quote (1 2 3 4)) (append (quote ()) (quote (1 2 3 4))))
6
+ (assert-equal (quote (1 2 3 4)) (append (quote (1 )) (quote (2 3 4))))
7
+ (assert-equal (quote (1 2 3 4)) (append (quote (1 2 )) (quote (3 4))))
8
+ (assert-equal (quote (1 2 3 4)) (append (quote (1 2 3 )) (quote (4))))
9
+ (assert-equal (quote (1 2 3 4)) (append (quote (1 2 3 4)) (quote ())))
10
+
11
+ (assert-equal (list 1 2 3) (reverse (list 3 2 1)))
@@ -6,7 +6,7 @@ class BusSchemeParserTest < Test::Unit::TestCase
6
6
  string = "(+ 2 2)"
7
7
  assert_equal :'(', BusScheme.pop_token(string)
8
8
 
9
- assert_equal :'+', BusScheme.pop_token(string)
9
+ assert_equal :'+'.sym, BusScheme.pop_token(string)
10
10
  assert_equal 2, BusScheme.pop_token(string)
11
11
  assert_equal 2, BusScheme.pop_token(string)
12
12
  assert_equal :")", BusScheme.pop_token(string)
@@ -17,9 +17,9 @@ class BusSchemeParserTest < Test::Unit::TestCase
17
17
  end
18
18
 
19
19
  def test_tokenize
20
- assert_equal [:'(', :'+', 2, 2, :')'], BusScheme.tokenize("(+ 2 2)")
21
- assert_equal [:'(', :'+', 2, :'(', :'+', 22, 2, :')', :')'], BusScheme.tokenize("(+ 2 (+ 22 2))")
22
- assert_equal [:'(', :plus, 2, 2, :')'], BusScheme.tokenize('(plus 2 2)')
20
+ assert_equal [:'(', :'+'.sym, 2, 2, :')'], BusScheme.tokenize("(+ 2 2)")
21
+ assert_equal [:'(', :'+'.sym, 2, :'(', :'+'.sym, 22, 2, :')', :')'], BusScheme.tokenize("(+ 2 (+ 22 2))")
22
+ assert_equal [:'(', :plus.sym, 2, 2, :')'], BusScheme.tokenize('(plus 2 2)')
23
23
  end
24
24
 
25
25
  def test_parse_numbers
@@ -31,35 +31,41 @@ class BusSchemeParserTest < Test::Unit::TestCase
31
31
  end
32
32
 
33
33
  def test_parses_two_strings
34
- assert_parses_to "(concat \"hello\" \"world\")", [:concat, "hello", "world"]
34
+ assert_parses_to "(concat \"hello\" \"world\")", [:concat.sym, "hello", "world"]
35
35
  end
36
36
 
37
37
  def test_parse_list_of_numbers
38
38
  assert_parses_to "(2 2)", [2, 2]
39
39
  end
40
+
41
+ def test_parse_dotted_cons
42
+ assert_parses_to "(22 . 11)", [:cons.sym, 22, 11]
43
+ assert_parses_to "((+ 2 2) . 11)", [:cons.sym, [:+.sym, 2, 2], 11]
44
+ assert_parses_to "(11 . (+ 2 2))", [:cons.sym, 11, [:+.sym, 2, 2]]
45
+ end
40
46
 
41
47
  def test_parse_list_of_atoms
42
- assert_parses_to "(+ 2 2)", [:+, 2, 2]
48
+ assert_parses_to "(+ 2 2)", [:+.sym, 2, 2]
43
49
  end
44
50
 
45
51
  def test_parse_list_of_atoms_with_string
46
- assert_parses_to "(+ 2 \"two\")", [:+, 2, "two"]
52
+ assert_parses_to "(+ 2 \"two\")", [:+.sym, 2, "two"]
47
53
  end
48
54
 
49
55
  def test_parse_list_of_nested_sexprs
50
- assert_parses_to "(+ 2 (+ 2))", [:+, 2, [:+, 2]]
56
+ assert_parses_to "(+ 2 (+ 2))", [:+.sym, 2, [:+.sym, 2]]
51
57
  end
52
58
 
53
59
  def test_parse_list_of_deeply_nested_sexprs
54
- assert_parses_to "(+ 2 (+ 2 (+ 2 2)))", [:+, 2, [:+, 2, [:+, 2, 2]]]
60
+ assert_parses_to "(+ 2 (+ 2 (+ 2 2)))", [:+.sym, 2, [:+.sym, 2, [:+.sym, 2, 2]]]
55
61
  end
56
62
 
57
63
  def test_parse_two_consecutive_parens_simple
58
- assert_parses_to "(let ((foo 2)))", [:let, [[:foo, 2]]]
64
+ assert_parses_to "(let ((foo 2)))", [:let.sym, [[:foo.sym, 2]]]
59
65
  end
60
66
 
61
67
  def test_parse_two_consecutive_parens
62
- assert_parses_to "(let ((foo 2)) (+ foo 2))", [:let, [[:foo, 2]], [:+, :foo, 2]]
68
+ assert_parses_to "(let ((foo 2)) (+ foo 2))", [:let.sym, [[:foo.sym, 2]], [:+.sym, :foo.sym, 2]]
63
69
  end
64
70
 
65
71
  def test_whitespace_indifferent
@@ -70,16 +76,11 @@ class BusSchemeParserTest < Test::Unit::TestCase
70
76
  end
71
77
 
72
78
  def test_parses_vectors
73
- assert_equal [:'(', :vector, 1, 2, :')'], BusScheme::tokenize("#(1 2)").flatten
74
- assert_parses_to "#(1 2)", [:vector, 1, 2]
75
- assert_parses_to "#(1 (2 3 4)", [:vector, 1, [2, 3, 4]]
79
+ assert_equal [:'(', :vector.sym, 1, 2, :')'], BusScheme::tokenize("#(1 2)").flatten
80
+ assert_parses_to "#(1 2)", [:vector.sym, 1, 2]
81
+ assert_parses_to "#(1 (2 3 4))", [:vector.sym, 1, [2, 3, 4]]
76
82
  end
77
83
 
78
- # def test_parses_dotted_cons
79
- # assert_parses_to "(22 . 11)", [:cons, 22, 11]
80
- # assert_parses_to "((+ 2 2) . 11)", [:cons, [:+, 2, 2], 11]
81
- # end
82
-
83
84
  def test_floats
84
85
  assert_parses_to "44.9", 44.9
85
86
  assert_parses_to "0.22", 0.22
@@ -99,15 +100,25 @@ class BusSchemeParserTest < Test::Unit::TestCase
99
100
  assert_parses_to "-0.10", -0.1
100
101
  end
101
102
 
103
+ def test_explicitly_positive_floats
104
+ assert_parses_to "+0.22", 0.22
105
+ assert_parses_to "+.22", 0.22
106
+ assert_parses_to "+0.10", 0.1
107
+ end
108
+
102
109
  # def test_character_literals
103
- # assert_parses_to "?#e", "e"
104
- # assert_parses_to "?#A", "A"
110
+ # assert_parses_to "#\e", "e"
111
+ # assert_parses_to "#\A", "A"
112
+ # assert_parses_to "#\(", "("
113
+ # assert_parses_to "#\space", ' '
114
+ # assert_parses_to "#\newline", "\n"
105
115
  # end
106
116
 
107
117
  def test_quote
108
- assert_parses_to "'foo", [:quote, :foo]
109
- assert_equal [:'(', :quote, :'(', :foo, :bar, :baz, :')', :')'], BusScheme::tokenize("'(foo bar baz)").flatten
110
- assert_parses_to "'(foo bar baz)", [:quote, [:foo, :bar, :baz]]
118
+ assert_parses_to "'foo", [:quote.sym, :foo.sym]
119
+ assert_equal [:'(', :quote.sym, :'(', :foo.sym, :bar.sym, :baz.sym, :')', :')'], BusScheme::tokenize("'(foo bar baz)").flatten
120
+ assert_parses_to "'(foo bar baz)", [:quote.sym, [:foo.sym, :bar.sym, :baz.sym]]
121
+ assert_parses_to "'(+ 20 3)", [:quote.sym, [:+.sym, 20, 3]]
111
122
  end
112
123
 
113
124
  # have to change normalize_whitespace to not turn newlines into spaces for this to work
@@ -115,7 +126,26 @@ class BusSchemeParserTest < Test::Unit::TestCase
115
126
  assert_parses_to ";; hello", nil
116
127
  assert_parses_to "12 ;; comment", 12
117
128
  assert_parses_to "(+ 2;; this is a mid-sexp comment
118
- 2)", [:+, 2, 2]
129
+ 2)", [:+.sym, 2, 2]
130
+ end
131
+
132
+ def test_requires_closed_lists
133
+ assert_raises(IncompleteError) { BusScheme.parse "(+ 2 2" }
134
+ assert_raises(IncompleteError) { BusScheme.parse "(+ (* 3 4) 2 2" }
135
+ end
136
+
137
+ def test_reject_bad_identifiers
138
+ ["14kalt", "-bolt", ".ab3"].each do |identifier|
139
+ assert_raises(ParseError, "#{identifier} should not be valid") { BusScheme.parse(identifier) }
140
+ end
141
+ end
142
+
143
+ def test_r5rs_identifiers
144
+ ["lambda", "q", "list->vector", "soup", "+",
145
+ "V17a", "<=?", "a34kTMNs",
146
+ "the-word-recursion-has-many-meanings"].each do |identifier|
147
+ assert_nothing_raised { BusScheme.parse(identifier) }
148
+ end
119
149
  end
120
150
 
121
151
  def test_parse_random_elisp_form_from_my_dot_emacs
@@ -125,17 +155,22 @@ class BusSchemeParserTest < Test::Unit::TestCase
125
155
  (if (file-exists-p system-specific-config)
126
156
  (load system-specific-config)))"
127
157
  assert_parses_to(lisp,
128
- [:let, [[:'system-specific-config',
129
- [:concat, "~/.emacs.d/",
130
- [:'shell-command-to-string', "hostname"]]]],
131
- [:if, [:'file-exists-p', :'system-specific-config'],
132
- [:load, :'system-specific-config']]])
158
+ [:let.sym, [[:'system-specific-config'.sym,
159
+ [:concat.sym, "~/.emacs.d/",
160
+ [:'shell-command-to-string'.sym, "hostname"]]]],
161
+ [:if.sym, [:'file-exists-p'.sym, :'system-specific-config'.sym],
162
+ [:load.sym, :'system-specific-config'.sym]]])
133
163
  end
134
164
 
165
+ def test_parser_saves_file_info
166
+ tree = BusScheme.parse("(define foo 23)")
167
+ assert_equal "(eval)", tree.cdr.car.file
168
+ end
169
+
135
170
  private
136
171
 
137
172
  def assert_parses_to(actual_string, expected)
138
- assert_equal expected, BusScheme.parse(actual_string)
173
+ assert_equal expected.sexp(true), BusScheme.parse(actual_string)
139
174
  end
140
175
 
141
176
  def assert_parses_equal(one, two, message = nil)
@@ -0,0 +1,24 @@
1
+ ;; still to test: number? vector? procedure? char? port?
2
+
3
+ (assert (boolean? (> 3 2)))
4
+ (assert (boolean? (> 1 2)))
5
+ (assert (not (boolean? 3)))
6
+ (assert (not (boolean? "hi")))
7
+ (assert (not (boolean? >)))
8
+
9
+ (assert (symbol? 'hi))
10
+ (assert (symbol? (quote hullo)))
11
+ (assert (not (symbol? "hi")))
12
+ (assert (not (symbol? 23)))
13
+ (assert (not (symbol? assert)))
14
+
15
+ (assert (cons? (cons 1 2)))
16
+ (assert (cons? cons?))
17
+ (assert (not (cons? 2)))
18
+ (assert (not (cons? #t)))
19
+ (assert (pair? (cons 1 2)))
20
+
21
+ (assert (string? "h"))
22
+ (assert (string? "hello"))
23
+ (assert (not (string? 'hi)))
24
+ (assert (not (string? string?)))
@@ -2,93 +2,43 @@ $LOAD_PATH << File.dirname(__FILE__)
2
2
  require 'test_helper'
3
3
 
4
4
  class PrimitivesTest < Test::Unit::TestCase
5
- def test_booleans
6
- assert BusScheme::PRIMITIVES.has_key? '#f'.intern
7
- assert_evals_to false, '#f'
8
- assert_evals_to true, '#t'
9
- end
10
-
11
- def test_arithmetic
12
- assert_evals_to 2, [:'-', 4, 2]
13
- assert_evals_to 2, [:'/', 4, 2]
14
- assert_evals_to 2, [:'*', 1, 2]
15
- end
16
-
17
- def test_many_args_for_arithmetic
18
- assert_evals_to 4, [:+, 1, 1, 1, 1]
19
- assert_evals_to 2, [:*, 1, 2, 1, 1]
20
- end
21
-
22
- def test_concat
23
- assert_evals_to "foobar", "(concat \"foo\" \"bar\")"
24
- end
25
-
26
- def test_eval
27
- assert_evals_to 23, "(eval '(+ 20 3))"
28
- end
29
-
30
- def test_eval_ruby
31
- assert_evals_to "foofoofoo", "(ruby \"'foo' * 3\")"
32
- end
33
-
34
- def test_message_passing
35
- assert_evals_to 7, "(send 3 (intern \"+\") 4)"
5
+ def test_test_framework
6
+ assert_raises(AssertionFailed) { eval "(assert (= 3 9))"}
7
+ assert_raises(AssertionFailed) { eval "(fail \"EPIC FAIL\")" }
36
8
  end
37
9
 
38
10
  def test_load_file
39
- eval "(load \"#{File.dirname(__FILE__)}/foo.scm\")"
40
- assert_evals_to 3, :foo
41
- end
42
-
43
- # special forms
44
- def test_define
45
- clear_symbols :foo
46
- eval("(define foo 5)")
47
- assert_equal 5, BusScheme::Lambda.scope[:foo]
48
- eval("(define foo (quote (5 5 5))")
49
- assert_evals_to [5, 5, 5].to_list, :foo
50
- end
51
-
52
- def test_define_returns_defined_term
53
- assert_evals_to :foo, "(define foo 2)"
54
- assert_equal 2, eval("foo")
55
- end
56
-
57
- def test_eval_quote
58
- assert_evals_to [:'+', 2, 2].to_list, [:quote, [:'+', 2, 2]]
59
- end
60
-
61
- def test_quote
62
- assert_evals_to :hi, [:quote, :hi]
63
- assert_evals_to [:a, :b, :c].to_list, "'(a b c)"
64
- assert_evals_to [:a].to_list, "(list 'a)"
65
- assert_evals_to [:a, :b].to_list, "(list 'a 'b)"
66
- assert_evals_to [:a, :b, :c].to_list, "(list 'a 'b 'c)"
67
- end
68
-
69
- def test_if
70
- assert_evals_to 7, [:if, '#f'.intern, 3, 7]
71
- assert_evals_to 3, [:if, [:>, 8, 2], 3, 7]
72
- end
73
-
74
- def test_begin
75
- eval([:begin,
76
- [:define, :foo, 779],
77
- 9])
78
- assert_equal 779, BusScheme::SYMBOL_TABLE[:foo]
11
+ eval "(load \"#{File.dirname(__FILE__)}/../examples/fib.scm\")"
12
+ assert BusScheme[:fib.sym]
13
+ assert_evals_to 5, "(+ (fib 3) (fib 4))"
14
+ assert_evals_to 8, "(fib 6)"
15
+ assert_evals_to [1, 1, 2, 3, 5, 8].to_list, "(map fib (list 1 2 3 4 5 6))"
16
+ end
17
+
18
+ def test_load_path
19
+ examples = File.dirname(__FILE__) + '/../examples/'
20
+ eval "(set! load-path (cons \"#{examples}\" load-path))"
21
+ eval "(load \"fib.scm\")"
22
+ assert BusScheme[:fib.sym]
23
+
24
+ clear_symbols :fib.sym
25
+ current = File.dirname(__FILE__)
26
+ eval "(set! load-path (cons \"#{current}\" load-path))"
27
+ eval "(load \"../examples/fib.scm\")"
28
+ assert BusScheme[:fib.sym]
79
29
  end
80
30
 
81
31
  def test_set!
82
- clear_symbols(:foo)
32
+ clear_symbols(:foo.sym)
83
33
  # can only set! existing variables
84
34
  assert_raises(BusScheme::EvalError) { eval "(set! foo 7)" }
85
35
  eval "(define foo 3)"
86
36
  eval "(set! foo 7)"
87
- assert_evals_to 7, :foo
37
+ assert_evals_to 7, :foo.sym
88
38
  end
89
39
 
90
40
  def test_consing
91
- assert_evals_to BusScheme::Cons.new(:foo, :bar), "(cons (quote foo) (quote bar))"
41
+ assert_evals_to BusScheme::Cons.new(:foo.sym, :bar.sym), "(cons (quote foo) (quote bar))"
92
42
  end
93
43
 
94
44
  def test_vectors
@@ -97,22 +47,18 @@ class PrimitivesTest < Test::Unit::TestCase
97
47
 
98
48
  def test_inspect
99
49
  assert_equal "(1)", [1].to_list.inspect
100
- assert_equal "(1 . 1)", BusScheme::Cons.new(1, 1).inspect
101
- assert_equal "(1 1 1)", BusScheme::Cons.new(1, BusScheme::Cons.new(1, BusScheme::Cons.new(1))).inspect
50
+ assert_equal "(1 . 1)", Cons.new(1, 1).inspect
51
+ assert_equal "(1 1 1)", Cons.new(1, Cons.new(1, Cons.new(1, nil))).inspect
52
+ assert_equal "(1 1 1 . 8)", Cons.new(1, Cons.new(1, Cons.new(1, 8))).inspect
102
53
  end
103
54
 
104
- def test_let
105
- assert_evals_to 4, "(let ((x 2)
106
- (y 2))
107
- (+ x y))"
108
-
109
- assert_evals_to 6, "(let ((doubler (lambda (x) (* 2 x)))
110
- (x 3))
111
- (doubler x))"
55
+ def test_boolean_short_circuit
56
+ assert_evals_to false, "(and #f (assert #f))"
57
+ assert_evals_to true, "(or #t (assert #f))"
58
+ end
112
59
 
113
- assert_evals_to 6, "(let ((doubler (lambda (x) (* 2 x)))
114
- (x 3))
115
- x
116
- (doubler x))"
60
+ def test_booleans
61
+ assert_evals_to false, '#f'
62
+ assert_evals_to true, '#t'
117
63
  end
118
64
  end
@@ -0,0 +1,55 @@
1
+ (assert #t)
2
+
3
+ ;; Arithmetic
4
+ (assert-equal 2 (+ 1 1))
5
+ (assert-equal 2 (/ 4 2))
6
+ (assert-equal 2 (* 1 2))
7
+
8
+ (assert-equal 4 (+ 1 1 1 1))
9
+ (assert-equal 2 (* 1 2 1 1))
10
+
11
+ ;; TODO: uncommenting this causes a blow-upey thing to happen
12
+ ;; (assert-equal 23 (eval '(+ 20 3)))
13
+ (assert-equal "foobar" (concat "foo" "bar"))
14
+ (assert-equal "foofoofoo" (ruby "'foo' * 3"))
15
+ (assert-equal 7 (send 3 (string->symbol "+") 4))
16
+
17
+ (assert-equal 9 (begin (define foo 779) 9))
18
+ (assert-equal 779 foo)
19
+
20
+ ;; (assert (null? (cdr (cons 3))))
21
+
22
+ ;; define
23
+ (define foo 5)
24
+ (define bar (quote (5 5 5)))
25
+ (assert-equal 5 foo)
26
+ (assert-equal (list 5 5 5) bar)
27
+
28
+ (assert-equal 'foo (define foo 5))
29
+
30
+ ;; special forms
31
+ (assert-equal 7 (if #f 3 7))
32
+ (assert-equal 3 (if (> 8 2) 3 7))
33
+
34
+ (assert-equal 4 (let ((x 2)
35
+ (y 2))
36
+ (+ x y)))
37
+ (assert-equal 6 (let ((doubler (lambda (x) (* 2 x)))
38
+ (x 3))
39
+ (doubler x)))
40
+
41
+ (assert-equal #t (and #t #t))
42
+ (assert-equal #f (and #t #f))
43
+ (assert-equal #f (and #f #t))
44
+ (assert-equal #f (and #f #f))
45
+
46
+ (assert-equal #t (or #t #t))
47
+ (assert-equal #t (or #t #f))
48
+ (assert-equal #t (or #f #t))
49
+ (assert-equal #f (or #f #f))
50
+
51
+ ; (load "../examples/fib.scm")
52
+ ; (assert fib)
53
+
54
+ ; (assert-equal (list 1 1 2 3 5 8)
55
+ ; (map fib (list 1 2 3 4 5 6)))
@@ -0,0 +1,30 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+ require 'test_helper'
3
+
4
+ class StackFrameTest < Test::Unit::TestCase
5
+ def setup
6
+ @parent = {:foo => "FOO", :baz => 'BAZ'}
7
+ @h = StackFrame.new({:foo => 'foo', :bar => 'bar'},
8
+ @parent, eval("(lambda () 1)"))
9
+ end
10
+
11
+ def test_has_key?
12
+ assert @h.has_key?(:foo)
13
+ assert @h.has_key?(:bar)
14
+ assert @h.has_key?(:baz)
15
+
16
+ assert @parent.has_key?(:baz)
17
+ assert @parent.has_key?(:foo)
18
+ assert !@parent.has_key?(:bar)
19
+
20
+ assert @h.immediate_has_key?(:foo)
21
+ assert @h.immediate_has_key?(:bar)
22
+ assert !@h.immediate_has_key?(:baz)
23
+ end
24
+
25
+ def test_setting_doesnt_alter_parent
26
+ @h[:foo] = "fooooooo"
27
+ assert_equal "fooooooo", @h[:foo]
28
+ assert_equal "FOO", @parent[:foo]
29
+ end
30
+ end