bus-scheme 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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