shen-ruby 0.1.0

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.
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