shen-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +0 -0
  3. data/Gemfile +6 -0
  4. data/Gemfile.lock +20 -0
  5. data/MIT_LICENSE.txt +26 -0
  6. data/README.md +94 -0
  7. data/bin/shen_test_suite.rb +9 -0
  8. data/bin/srrepl +23 -0
  9. data/lib/kl.rb +7 -0
  10. data/lib/kl/absvector.rb +12 -0
  11. data/lib/kl/compiler.rb +253 -0
  12. data/lib/kl/cons.rb +51 -0
  13. data/lib/kl/empty_list.rb +12 -0
  14. data/lib/kl/environment.rb +123 -0
  15. data/lib/kl/error.rb +4 -0
  16. data/lib/kl/internal_error.rb +7 -0
  17. data/lib/kl/lexer.rb +186 -0
  18. data/lib/kl/primitives/arithmetic.rb +60 -0
  19. data/lib/kl/primitives/assignments.rb +18 -0
  20. data/lib/kl/primitives/booleans.rb +17 -0
  21. data/lib/kl/primitives/error_handling.rb +13 -0
  22. data/lib/kl/primitives/generic_functions.rb +22 -0
  23. data/lib/kl/primitives/lists.rb +21 -0
  24. data/lib/kl/primitives/streams.rb +38 -0
  25. data/lib/kl/primitives/strings.rb +55 -0
  26. data/lib/kl/primitives/symbols.rb +17 -0
  27. data/lib/kl/primitives/time.rb +17 -0
  28. data/lib/kl/primitives/vectors.rb +30 -0
  29. data/lib/kl/reader.rb +40 -0
  30. data/lib/kl/trampoline.rb +14 -0
  31. data/lib/shen_ruby.rb +7 -0
  32. data/lib/shen_ruby/version.rb +3 -0
  33. data/shen-ruby.gemspec +26 -0
  34. data/shen/README.txt +17 -0
  35. data/shen/lib/shen_ruby/shen.rb +124 -0
  36. data/shen/license.txt +34 -0
  37. data/shen/release/benchmarks/N_queens.shen +45 -0
  38. data/shen/release/benchmarks/README.shen +14 -0
  39. data/shen/release/benchmarks/benchmarks.shen +56 -0
  40. data/shen/release/benchmarks/bigprog +2173 -0
  41. data/shen/release/benchmarks/br.shen +13 -0
  42. data/shen/release/benchmarks/einstein.shen +33 -0
  43. data/shen/release/benchmarks/heatwave.gif +0 -0
  44. data/shen/release/benchmarks/interpreter.shen +219 -0
  45. data/shen/release/benchmarks/picture.jpg +0 -0
  46. data/shen/release/benchmarks/plato.jpg +0 -0
  47. data/shen/release/benchmarks/powerset.shen +10 -0
  48. data/shen/release/benchmarks/prime.shen +10 -0
  49. data/shen/release/benchmarks/short.shen +129 -0
  50. data/shen/release/benchmarks/text.txt +68 -0
  51. data/shen/release/k_lambda/core.kl +1002 -0
  52. data/shen/release/k_lambda/declarations.kl +1021 -0
  53. data/shen/release/k_lambda/load.kl +94 -0
  54. data/shen/release/k_lambda/macros.kl +479 -0
  55. data/shen/release/k_lambda/prolog.kl +1309 -0
  56. data/shen/release/k_lambda/reader.kl +1058 -0
  57. data/shen/release/k_lambda/sequent.kl +556 -0
  58. data/shen/release/k_lambda/sys.kl +582 -0
  59. data/shen/release/k_lambda/t-star.kl +3493 -0
  60. data/shen/release/k_lambda/toplevel.kl +223 -0
  61. data/shen/release/k_lambda/track.kl +208 -0
  62. data/shen/release/k_lambda/types.kl +455 -0
  63. data/shen/release/k_lambda/writer.kl +108 -0
  64. data/shen/release/k_lambda/yacc.kl +280 -0
  65. data/shen/release/test_programs/Chap13/problems.txt +26 -0
  66. data/shen/release/test_programs/README.shen +53 -0
  67. data/shen/release/test_programs/TinyLispFunctions.txt +16 -0
  68. data/shen/release/test_programs/TinyTypes.shen +55 -0
  69. data/shen/release/test_programs/binary.shen +24 -0
  70. data/shen/release/test_programs/bubble_version_1.shen +28 -0
  71. data/shen/release/test_programs/bubble_version_2.shen +22 -0
  72. data/shen/release/test_programs/calculator.shen +21 -0
  73. data/shen/release/test_programs/cartprod.shen +23 -0
  74. data/shen/release/test_programs/change.shen +25 -0
  75. data/shen/release/test_programs/classes-defaults.shen +94 -0
  76. data/shen/release/test_programs/classes-inheritance.shen +100 -0
  77. data/shen/release/test_programs/classes-typed.shen +74 -0
  78. data/shen/release/test_programs/classes-untyped.shen +46 -0
  79. data/shen/release/test_programs/depth_.shen +14 -0
  80. data/shen/release/test_programs/einstein.shen +33 -0
  81. data/shen/release/test_programs/fruit_machine.shen +46 -0
  82. data/shen/release/test_programs/interpreter.shen +219 -0
  83. data/shen/release/test_programs/metaprog.shen +85 -0
  84. data/shen/release/test_programs/minim.shen +193 -0
  85. data/shen/release/test_programs/mutual.shen +11 -0
  86. data/shen/release/test_programs/n_queens.shen +45 -0
  87. data/shen/release/test_programs/newton_version_1.shen +33 -0
  88. data/shen/release/test_programs/newton_version_2.shen +24 -0
  89. data/shen/release/test_programs/parse.prl +14 -0
  90. data/shen/release/test_programs/parser.shen +52 -0
  91. data/shen/release/test_programs/powerset.shen +10 -0
  92. data/shen/release/test_programs/prime.shen +10 -0
  93. data/shen/release/test_programs/proof_assistant.shen +81 -0
  94. data/shen/release/test_programs/proplog_version_1.shen +25 -0
  95. data/shen/release/test_programs/proplog_version_2.shen +27 -0
  96. data/shen/release/test_programs/qmachine.shen +67 -0
  97. data/shen/release/test_programs/red-black.shen +55 -0
  98. data/shen/release/test_programs/search.shen +56 -0
  99. data/shen/release/test_programs/semantic_net.shen +44 -0
  100. data/shen/release/test_programs/spreadsheet.shen +35 -0
  101. data/shen/release/test_programs/stack.shen +27 -0
  102. data/shen/release/test_programs/streams.shen +20 -0
  103. data/shen/release/test_programs/strings.shen +59 -0
  104. data/shen/release/test_programs/structures-typed.shen +71 -0
  105. data/shen/release/test_programs/structures-untyped.shen +42 -0
  106. data/shen/release/test_programs/tests.shen +294 -0
  107. data/shen/release/test_programs/types.shen +11 -0
  108. data/shen/release/test_programs/whist.shen +240 -0
  109. data/shen/release/test_programs/yacc.shen +136 -0
  110. data/spec/kl/cons_spec.rb +12 -0
  111. data/spec/kl/environment_spec.rb +306 -0
  112. data/spec/kl/lexer_spec.rb +149 -0
  113. data/spec/kl/primitives/generic_functions_spec.rb +29 -0
  114. data/spec/kl/primitives/symbols_spec.rb +21 -0
  115. data/spec/kl/reader_spec.rb +36 -0
  116. data/spec/spec_helper.rb +2 -0
  117. metadata +189 -0
@@ -0,0 +1,136 @@
1
+ (defcc <sent>
2
+ <np> <vp>;)
3
+
4
+ (defcc <det>
5
+ the; a;)
6
+
7
+ (defcc <np>
8
+ <det> <n>;
9
+ <name1>;)
10
+
11
+ (defcc <n>
12
+ cat; dog;)
13
+
14
+ (defcc <name1>
15
+ -*- := (if (element? -*- [(protect Bill) (protect Ben)]) -*- (fail));)
16
+
17
+ (defcc <vp>
18
+ <vtrans> <np>;)
19
+
20
+ (defcc <vtrans>
21
+ likes; chases;)
22
+
23
+ (defcc <des>
24
+ [<ds>] [<es>] := (append <ds> <es>);)
25
+
26
+ (defcc <ds>
27
+ d <ds>;
28
+ d;)
29
+
30
+ (defcc <es>
31
+ e <es>;
32
+ e;)
33
+
34
+ (defcc <sent'>
35
+ <np> <vp> := (question <np> <vp>);)
36
+
37
+ (define question
38
+ NP VP -> (append [is it true that your father] VP [?]))
39
+
40
+ (defcc <as->bs>
41
+ a <a->bs> := [b | <a->bs>];
42
+ a := [b];)
43
+
44
+ (defcc <find-digit>
45
+ <digit> <morestuff> := <digit>;
46
+ <digit> := <digit>;
47
+ -*- <find-digit> := <find-digit>;)
48
+
49
+ (defcc <morestuff>
50
+ -*- <morestuff>;
51
+ -*-;)
52
+
53
+ (defcc <digit>
54
+ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9;)
55
+
56
+ (defcc <find-digit'>
57
+ <digit> <morestuff> := -s-;
58
+ <digit> := -s-;
59
+ -*- <find-digit'> := <find-digit'>;)
60
+
61
+ (defcc <asbscs>
62
+ <as> <bs> <cs>;)
63
+
64
+ (defcc <as>
65
+ a <as>;
66
+ a;)
67
+
68
+ (defcc <bs>
69
+ b <bs>;
70
+ b;
71
+ <e>;)
72
+
73
+ (defcc <cs>
74
+ c <cs>;
75
+ c;)
76
+
77
+ (defcc <asbs'cs>
78
+ <as> <bs'> <cs>;)
79
+
80
+ (defcc <bs'>
81
+ b <bs'>;
82
+ b;
83
+ <e>;)
84
+
85
+ (defcc <find-digit''>
86
+ <digit''> <morestuff> := <digit''>;
87
+ <digit''> := <digit''>;
88
+ -*- <find-digit''> := <find-digit''>;)
89
+
90
+ (defcc <digit''>
91
+ -*- := (one_of -*- [0 1 2 3 4 5 6 7 8 9]);)
92
+
93
+ (define one_of
94
+ X Y -> (if (element? X Y) X (fail)))
95
+
96
+ (defcc <anbncn>
97
+ <as> <bs> <cs> := (if (equal-length? [<as> <bs> <cs>])
98
+ (appendall [<as> <bs> <cs>])
99
+ (fail));)
100
+
101
+ (defcc <as>
102
+ a <as>;
103
+ a;)
104
+
105
+ (defcc <bs>
106
+ b <bs>;
107
+ b;)
108
+
109
+ (defcc <cs>
110
+ c <cs>;
111
+ c;)
112
+
113
+ (define equal-length?
114
+ [] -> true
115
+ [L] -> true
116
+ [L1 L2 | Ls] -> (and (= (length L1) (length L2)) (equal-length? [L2 | Ls])))
117
+
118
+ (define appendall
119
+ [] -> []
120
+ [L | Ls] -> (append L (appendall Ls)))
121
+
122
+ (defcc <a*s>
123
+ [a] := a;)
124
+
125
+ (defcc <b*>
126
+ [b] b;)
127
+
128
+ (defcc <c*>
129
+ [<c*>] := [<c*>];
130
+ c;)
131
+
132
+ (defcc <d*>
133
+ [<d*>] <d*> := [[<d*>] | <d*>];
134
+ d <d*> := [d | <d*>];
135
+ d := [d];)
136
+
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kl::Cons, '.list' do
4
+ it 'returns Kl::EmptyList for an empty array' do
5
+ Kl::Cons.list([]).should be_kind_of Kl::EmptyList
6
+ end
7
+
8
+ it 'constructs a nil-terminated list from a non-empty array' do
9
+ Kl::Cons.list([1, 2, 3]).should ==
10
+ Kl::Cons.new(1, Kl::Cons.new(2, Kl::Cons.new(3, Kl::EmptyList.instance)))
11
+ end
12
+ end
@@ -0,0 +1,306 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kl::Environment do
4
+ def eval_str(str)
5
+ form = Kl::Reader.new(StringIO.new(str)).next
6
+ @env.__eval(form)
7
+ end
8
+
9
+ before(:each) do
10
+ @env = Kl::Environment.new
11
+ end
12
+
13
+ describe 'evaluation of atoms' do
14
+ it 'evaluates symbols to themselves' do
15
+ eval_str('foo').should == :foo
16
+ eval_str('foo-bar-<baz>').should == "foo-bar-<baz>".to_sym
17
+ end
18
+
19
+ it 'evaluates strings to themselves' do
20
+ eval_str('"foo"').should == 'foo'
21
+ eval_str('"foo #{bar} \'baz"').should == 'foo #{bar} \'baz'
22
+ eval_str('"\\"').should == '\\'
23
+ end
24
+
25
+ it 'evaluates numbers to themselves' do
26
+ eval_str('1').should == 1
27
+ eval_str('-1.7').should == -1.7
28
+ end
29
+
30
+ it 'evaluates booleans to themselves' do
31
+ eval_str('true').should == true
32
+ eval_str('false').should == false
33
+ end
34
+
35
+ it 'evaluations empty strings to themselves' do
36
+ eval_str('()').should == Kl::EmptyList.instance
37
+ end
38
+ end
39
+
40
+ describe 'evaluation of non-special forms' do
41
+ it 'evaluates simple function application' do
42
+ eval_str('(+ 1 2)').should == 3
43
+ end
44
+
45
+ it 'evaluates function arguments before application' do
46
+ eval_str('(* (+ 1 2) (- 6 1))').should == 15
47
+ end
48
+ end
49
+
50
+ describe 'evaluation of lambda special form' do
51
+ it 'evaluates them to proc objects' do
52
+ eval_str('(lambda X X)').should be_kind_of Proc
53
+ end
54
+
55
+ it 'allows them to be applied' do
56
+ eval_str('((lambda X X) 37)').should == 37
57
+ eval_str('((lambda X 42) ignore-me)').should == 42
58
+ end
59
+
60
+ it 'maintains lexical scoping' do
61
+ # (let X 1
62
+ # (let Y 3
63
+ # (let X 7
64
+ # (+ X Y))))
65
+ eval_str('((lambda X
66
+ ((lambda Y
67
+ ((lambda X (+ X Y))
68
+ 7))
69
+ 3))
70
+ 1)').should == 10
71
+ end
72
+
73
+ it 'creates closures' do
74
+ eval_str('((let X 37 (lambda IGNORE X)) ignore-me)').should == 37
75
+ end
76
+ end
77
+
78
+ describe 'evaluation of let special form' do
79
+ it 'binds its var' do
80
+ eval_str('(let X 37 X)').should == 37
81
+ end
82
+
83
+ it 'maintains lexical scoping' do
84
+ eval_str('(let X 1
85
+ (let Y 3
86
+ (let X 7
87
+ (+ X Y))))').should == 10
88
+ end
89
+ end
90
+
91
+ describe 'evaluation of defun special form' do
92
+ it 'adds a new function to the environment' do
93
+ eval_str('(defun my-add (A B) (+ A B))').should == "my-add".to_sym
94
+ eval_str('(my-add 17 20)').should == 37
95
+ end
96
+
97
+ it 'exposes the function for use in Ruby' do
98
+ pending "a clean way to handle trampolines when calling from outside"
99
+ eval_str('(defun add7 (X) (+ X 7))')
100
+ @env.add7(30).should == 37
101
+ end
102
+
103
+ it 'redefines existing functions' do
104
+ eval_str('(defun my-fun () first-version)')
105
+ eval_str('(my-fun)').should == :"first-version"
106
+ eval_str('(defun my-fun () second-version)')
107
+ eval_str('(my-fun)').should == :"second-version"
108
+ end
109
+
110
+ it 'adds a top-level function even when not executed at the top-level' do
111
+ eval_str('((lambda X
112
+ (defun return-X () X)) 7)').should == :"return-X"
113
+ eval_str('(return-X)').should == 7
114
+ end
115
+ end
116
+
117
+ describe 'evaluation of boolean special forms' do
118
+ describe "if" do
119
+ before(:each) do
120
+ eval_str('(defun one () 1)')
121
+ eval_str('(defun two () 2)')
122
+ end
123
+
124
+ it 'evaluates and returns the true clause when given true' do
125
+ @env.should_receive(:one).and_return(1)
126
+ @env.should_not_receive(:two)
127
+ eval_str('(if true (one) (two))').should == 1
128
+ end
129
+
130
+ it 'evaluates and returns the false clause when given false' do
131
+ @env.should_not_receive(:one)
132
+ @env.should_receive(:two).and_return(2)
133
+ eval_str('(if false (one) (two))').should == 2
134
+ end
135
+ end
136
+
137
+ describe "and" do
138
+ before(:each) do
139
+ eval_str('(defun tr () true)')
140
+ eval_str('(defun fa () false)')
141
+ end
142
+
143
+ it 'returns false and does not evaluate second form if first is false' do
144
+ @env.should_not_receive(:tr)
145
+ eval_str('(and (fa) (tr))').should == false
146
+ end
147
+
148
+ it 'returns false when first is true and second is false' do
149
+ eval_str('(and (tr) (fa))').should == false
150
+ end
151
+
152
+ it 'returns true when both expressions evaluate to true' do
153
+ @env.should_receive(:tr).twice.and_return(true)
154
+ eval_str('(and (tr) (tr))').should == true
155
+ end
156
+
157
+ it 'may be passed as an argument to higher order functions' do
158
+ eval_str('((lambda Op (Op true true)) and)').should == true
159
+ end
160
+ end
161
+
162
+ describe "or" do
163
+ before(:each) do
164
+ eval_str('(defun tr () true)')
165
+ eval_str('(defun fa () false)')
166
+ end
167
+
168
+ it 'returns true and does not evaluate second form if first is true' do
169
+ @env.should_not_receive(:fa)
170
+ eval_str('(or (tr) (fa))').should == true
171
+ end
172
+
173
+ it 'returns true when first is false and second is true' do
174
+ eval_str('(or (fa) (tr))').should == true
175
+ end
176
+
177
+ it 'returns false when both expressions evaluate to false' do
178
+ @env.should_receive(:fa).twice.and_return(false)
179
+ eval_str('(or (fa) (fa))').should == false
180
+ end
181
+
182
+ it 'may be passed as an argument to higher order functions' do
183
+ eval_str('((lambda Op (Op false false)) or)').should == false
184
+ end
185
+
186
+ end
187
+
188
+ describe "cond" do
189
+ before(:each) do
190
+ eval_str('(defun tr () true)')
191
+ eval_str('(defun fa () false)')
192
+ end
193
+
194
+ it 'returns the value of the expression associate with the first true' do
195
+ @env.should_not_receive(:tr)
196
+ eval_str('(cond (false (tr))
197
+ ((fa) 37)
198
+ (true 42)
199
+ (true (tr)))').should == 42
200
+ end
201
+
202
+ it 'raises an error upon falling off the end' do
203
+ expect {
204
+ eval_str('(cond (false 37) ((fa) 42))')
205
+ }.to raise_error(Kl::Error, 'condition failure')
206
+ end
207
+ end
208
+ end
209
+
210
+ describe "error handling" do
211
+ it 'raises uncaught errors' do
212
+ expect {
213
+ eval_str('(simple-error "boom!")')
214
+ }.to raise_error(Kl::Error, 'boom!')
215
+ end
216
+
217
+ it 'moves past caught errors' do
218
+ eval_str('(trap-error
219
+ (simple-error "boom!")
220
+ (lambda E 37))').should == 37
221
+ end
222
+
223
+ it 'treats undefined functions as simple errors' do
224
+ expect {
225
+ eval_str('(foo)')
226
+ }.to raise_error(Kl::Error, 'The function foo is undefined')
227
+ end
228
+ end
229
+
230
+ describe "setting values" do
231
+ it 'returns the value set' do
232
+ eval_str('(set foo 37)').should == 37
233
+ end
234
+
235
+ it 'previously set values are retrievable' do
236
+ eval_str('(set foo 37)')
237
+ eval_str('(value foo)').should == 37
238
+ end
239
+ end
240
+
241
+ describe "evaluation of freeze" do
242
+ it 'delays computation' do
243
+ eval_str('(defun one () 1)')
244
+ @env.should_not_receive(:one)
245
+ eval_str('(freeze (one))').should be_kind_of Proc
246
+ end
247
+
248
+ it 'is thawable later' do
249
+ eval_str('(defun one () 1)')
250
+ eval_str('((freeze (one)))').should == 1
251
+ end
252
+ end
253
+
254
+ describe 'evaulation of type' do
255
+ it 'evaluates the expression and ignores the type information' do
256
+ eval_str('(type (+ 1 2) number)').should == 3
257
+ end
258
+ end
259
+
260
+ describe 'evaluation of eval-kl' do
261
+ it 'evals as expected' do
262
+ eval_str('(eval-kl (+ 1 2))').should == 3
263
+ end
264
+ end
265
+
266
+ describe 'currying' do
267
+ it 'supports partial application of primitives' do
268
+ eval_str('((+ 1) 2)').should == 3
269
+ eval_str('(((+) 1) 2)').should == 3
270
+ end
271
+
272
+ it 'supports partial application of user-defined functions' do
273
+ eval_str('(defun adder (X Y) (+ X Y))')
274
+ eval_str('((adder 1) 2)').should == 3
275
+ eval_str('(((adder) 1) 2)').should == 3
276
+ end
277
+
278
+ it 'supports uncurrying of nested lambdas' do
279
+ eval_str('((lambda X (lambda Y (* X Y))) 6 7)').should == 42
280
+ end
281
+
282
+ it 'supports uncurrying of higher-order functions' do
283
+ eval_str('(defun adder (X) (lambda Y (+ X Y)))')
284
+ eval_str('(adder 1 2)').should == 3
285
+ end
286
+ end
287
+
288
+ describe 'tail recursion' do
289
+ it 'does not blow the stack' do
290
+ eval_str('(defun count-down (X)
291
+ (if (= X 0)
292
+ success
293
+ (count-down (- X 1))))')
294
+ eval_str('(count-down 100000)').should == :success
295
+ end
296
+ end
297
+
298
+ describe 'stack overflow' do
299
+ it 'is translated into a Shen simple-error' do
300
+ eval_str('(defun boom () (+ 1 (boom)))')
301
+ expect {
302
+ eval_str('(boom)')
303
+ }.to raise_error(Kl::Error, 'maximum stack depth exceeded')
304
+ end
305
+ end
306
+ end