shen-ruby 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.travis.yml +9 -3
  4. data/Gemfile +1 -4
  5. data/HISTORY.md +16 -0
  6. data/MIT_LICENSE.txt +1 -1
  7. data/README.md +25 -26
  8. data/Rakefile +3 -11
  9. data/bin/shen_test_suite.rb +15 -3
  10. data/bin/srrepl +6 -8
  11. data/lib/shen_ruby.rb +6 -1
  12. data/lib/shen_ruby/converters.rb +23 -0
  13. data/lib/shen_ruby/version.rb +1 -1
  14. data/shen-ruby.gemspec +4 -1
  15. data/shen/lib/shen_ruby/shen.rb +49 -33
  16. data/shen/release/benchmarks/N_queens.shen +45 -45
  17. data/shen/release/benchmarks/README.shen +14 -14
  18. data/shen/release/benchmarks/benchmarks.shen +52 -52
  19. data/shen/release/benchmarks/einstein.shen +32 -32
  20. data/shen/release/benchmarks/interpreter.shen +219 -219
  21. data/shen/release/benchmarks/jnk.shen +193 -193
  22. data/shen/release/benchmarks/powerset.shen +10 -10
  23. data/shen/release/benchmarks/prime.shen +10 -10
  24. data/shen/release/benchmarks/short.shen +129 -129
  25. data/shen/release/k_lambda/core.kl +181 -181
  26. data/shen/release/k_lambda/declarations.kl +131 -131
  27. data/shen/release/k_lambda/load.kl +84 -84
  28. data/shen/release/k_lambda/macros.kl +112 -112
  29. data/shen/release/k_lambda/prolog.kl +252 -252
  30. data/shen/release/k_lambda/reader.kl +222 -222
  31. data/shen/release/k_lambda/sequent.kl +166 -166
  32. data/shen/release/k_lambda/sys.kl +271 -271
  33. data/shen/release/k_lambda/t-star.kl +139 -139
  34. data/shen/release/k_lambda/toplevel.kl +135 -135
  35. data/shen/release/k_lambda/track.kl +103 -103
  36. data/shen/release/k_lambda/types.kl +324 -324
  37. data/shen/release/k_lambda/writer.kl +105 -105
  38. data/shen/release/k_lambda/yacc.kl +113 -113
  39. data/shen/release/test_programs/Chap13/problems.txt +26 -26
  40. data/shen/release/test_programs/README.shen +52 -52
  41. data/shen/release/test_programs/TinyLispFunctions.txt +15 -15
  42. data/shen/release/test_programs/TinyTypes.shen +55 -55
  43. data/shen/release/test_programs/binary.shen +24 -24
  44. data/shen/release/test_programs/bubble_version_1.shen +28 -28
  45. data/shen/release/test_programs/bubble_version_2.shen +22 -22
  46. data/shen/release/test_programs/calculator.shen +21 -21
  47. data/shen/release/test_programs/cartprod.shen +23 -23
  48. data/shen/release/test_programs/change.shen +25 -25
  49. data/shen/release/test_programs/classes-defaults.shen +94 -94
  50. data/shen/release/test_programs/classes-inheritance.shen +100 -100
  51. data/shen/release/test_programs/classes-typed.shen +74 -74
  52. data/shen/release/test_programs/classes-untyped.shen +46 -46
  53. data/shen/release/test_programs/depth_.shen +14 -14
  54. data/shen/release/test_programs/einstein.shen +34 -34
  55. data/shen/release/test_programs/fruit_machine.shen +46 -46
  56. data/shen/release/test_programs/interpreter.shen +217 -217
  57. data/shen/release/test_programs/metaprog.shen +85 -85
  58. data/shen/release/test_programs/minim.shen +192 -192
  59. data/shen/release/test_programs/mutual.shen +11 -11
  60. data/shen/release/test_programs/n_queens.shen +45 -45
  61. data/shen/release/test_programs/newton_version_1.shen +33 -33
  62. data/shen/release/test_programs/newton_version_2.shen +24 -24
  63. data/shen/release/test_programs/parse.prl +14 -14
  64. data/shen/release/test_programs/parser.shen +51 -51
  65. data/shen/release/test_programs/powerset.shen +10 -10
  66. data/shen/release/test_programs/prime.shen +10 -10
  67. data/shen/release/test_programs/prolog.shen +78 -78
  68. data/shen/release/test_programs/proof_assistant.shen +80 -80
  69. data/shen/release/test_programs/proplog_version_1.shen +25 -25
  70. data/shen/release/test_programs/proplog_version_2.shen +27 -27
  71. data/shen/release/test_programs/qmachine.shen +66 -66
  72. data/shen/release/test_programs/red-black.shen +54 -54
  73. data/shen/release/test_programs/search.shen +55 -55
  74. data/shen/release/test_programs/semantic_net.shen +44 -44
  75. data/shen/release/test_programs/spreadsheet.shen +34 -34
  76. data/shen/release/test_programs/stack.shen +27 -27
  77. data/shen/release/test_programs/streams.shen +20 -20
  78. data/shen/release/test_programs/strings.shen +57 -57
  79. data/shen/release/test_programs/structures-typed.shen +71 -71
  80. data/shen/release/test_programs/structures-untyped.shen +41 -41
  81. data/shen/release/test_programs/tests.shen +232 -232
  82. data/shen/release/test_programs/types.shen +11 -11
  83. data/shen/release/test_programs/whist.shen +239 -239
  84. data/shen/release/test_programs/yacc.shen +132 -132
  85. data/spec/shen_ruby/converters_spec.rb +48 -0
  86. data/spec/spec_helper.rb +1 -2
  87. metadata +55 -60
  88. data/k_lambda_spec/atom_spec.rb +0 -85
  89. data/k_lambda_spec/primitives/arithmetic_spec.rb +0 -175
  90. data/k_lambda_spec/primitives/assignments_spec.rb +0 -44
  91. data/k_lambda_spec/primitives/boolean_operations_spec.rb +0 -136
  92. data/k_lambda_spec/primitives/generic_functions_spec.rb +0 -120
  93. data/k_lambda_spec/primitives/lists_spec.rb +0 -40
  94. data/k_lambda_spec/primitives/strings_spec.rb +0 -77
  95. data/k_lambda_spec/primitives/symbols_spec.rb +0 -24
  96. data/k_lambda_spec/primitives/vectors_spec.rb +0 -92
  97. data/k_lambda_spec/spec_helper.rb +0 -29
  98. data/k_lambda_spec/support/shared_examples.rb +0 -124
  99. data/k_lambda_spec/tail_recursion_spec.rb +0 -30
  100. data/lib/kl.rb +0 -7
  101. data/lib/kl/absvector.rb +0 -12
  102. data/lib/kl/compiler.rb +0 -360
  103. data/lib/kl/cons.rb +0 -51
  104. data/lib/kl/empty_list.rb +0 -12
  105. data/lib/kl/environment.rb +0 -163
  106. data/lib/kl/error.rb +0 -4
  107. data/lib/kl/internal_error.rb +0 -7
  108. data/lib/kl/lexer.rb +0 -186
  109. data/lib/kl/primitives/arithmetic.rb +0 -60
  110. data/lib/kl/primitives/assignments.rb +0 -15
  111. data/lib/kl/primitives/booleans.rb +0 -21
  112. data/lib/kl/primitives/error_handling.rb +0 -13
  113. data/lib/kl/primitives/extensions.rb +0 -12
  114. data/lib/kl/primitives/generic_functions.rb +0 -29
  115. data/lib/kl/primitives/lists.rb +0 -23
  116. data/lib/kl/primitives/streams.rb +0 -28
  117. data/lib/kl/primitives/strings.rb +0 -63
  118. data/lib/kl/primitives/symbols.rb +0 -18
  119. data/lib/kl/primitives/time.rb +0 -17
  120. data/lib/kl/primitives/vectors.rb +0 -36
  121. data/lib/kl/reader.rb +0 -46
  122. data/spec/kl/cons_spec.rb +0 -12
  123. data/spec/kl/environment_spec.rb +0 -282
  124. data/spec/kl/interop_spec.rb +0 -68
  125. data/spec/kl/lexer_spec.rb +0 -149
  126. data/spec/kl/primitives/generic_functions_spec.rb +0 -29
  127. data/spec/kl/primitives/symbols_spec.rb +0 -21
  128. data/spec/kl/reader_spec.rb +0 -42
@@ -1,18 +0,0 @@
1
- module Kl
2
- module Primitives
3
- module Symbols
4
- def intern(str)
5
- raise Kl::Error, "#{str} is not a string" unless str.kind_of? String
6
- # 'true' and 'false' are treated specially and return the
7
- # corresponding booleans
8
- if str == 'true'
9
- true
10
- elsif str == 'false'
11
- false
12
- else
13
- str.to_sym
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,17 +0,0 @@
1
- module Kl
2
- module Primitives
3
- module Time
4
- define_method 'get-time' do |time_type|
5
- case time_type
6
- when :run, :real
7
- ::Time.now.to_f
8
- when :unix
9
- ::Time.now.to_i
10
- else
11
- raise Kl::Error, "unsupported time type: #{time_type}"
12
- end
13
- end
14
- end
15
- end
16
- end
17
-
@@ -1,36 +0,0 @@
1
- module Kl
2
- module Primitives
3
- module Vectors
4
- def absvector(n)
5
- raise Kl::Error, "#{n} is not a number" unless n.kind_of? Fixnum
6
- raise Kl::Error, "#{n} must be >= 0" unless n >= 0
7
- Kl::Absvector.new(n)
8
- end
9
-
10
- define_method 'address->' do |v, n, value|
11
- raise Kl::Error, "#{v} is not a vector" unless v.kind_of? Kl::Absvector
12
- raise Kl::Error, "#{n} is not a number" unless n.kind_of? Fixnum
13
- if n < 0 || n >= v.upper_limit
14
- raise Kl::Error, "out of bounds"
15
- end
16
-
17
- v[n] = value
18
- v
19
- end
20
-
21
- define_method '<-address' do |v, n|
22
- raise Kl::Error, "#{v} is not a vector" unless v.kind_of? Kl::Absvector
23
- raise Kl::Error, "#{n} is not a number" unless n.kind_of? Fixnum
24
- if n < 0 || n >= v.upper_limit
25
- raise Kl::Error, "out of bounds"
26
- end
27
-
28
- v[n]
29
- end
30
-
31
- def absvector?(v)
32
- v.kind_of? Kl::Absvector
33
- end
34
- end
35
- end
36
- end
data/lib/kl/reader.rb DELETED
@@ -1,46 +0,0 @@
1
- require 'kl/lexer'
2
-
3
- module Kl
4
- class Reader
5
- def initialize(stream)
6
- @lexer = Kl::Lexer.new(stream)
7
- end
8
-
9
- def next
10
- token = @lexer.next
11
- unless token.nil?
12
- if token.kind_of? Kl::Lexer::OpenParen
13
- read_list
14
- else
15
- token
16
- end
17
- end
18
- end
19
-
20
- private
21
-
22
- def read_list
23
- items = []
24
- stack = [items]
25
-
26
- until stack.empty? do
27
- token = @lexer.next
28
- raise Kl::Error, 'Unterminated list' if token.nil?
29
- case token
30
- when Kl::Lexer::OpenParen
31
- items = []
32
- stack.push items
33
- when Kl::Lexer::CloseParen
34
- list = Kl::Cons.list(stack.pop)
35
- unless stack.empty?
36
- items = stack.last
37
- items << list
38
- end
39
- else
40
- items << token
41
- end
42
- end
43
- list
44
- end
45
- end
46
- end
data/spec/kl/cons_spec.rb DELETED
@@ -1,12 +0,0 @@
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
@@ -1,282 +0,0 @@
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
- eval_str('(defun add7 (X) (+ X 7))')
99
- @env.add7(30).should == 37
100
-
101
- eval_str('(defun add14 (X) (add7 (add7 X)))')
102
- @env.add14(7).should == 21
103
- end
104
-
105
- it 'redefines existing functions' do
106
- eval_str('(defun my-fun () first-version)')
107
- eval_str('(my-fun)').should == :"first-version"
108
- eval_str('(defun my-fun () second-version)')
109
- eval_str('(my-fun)').should == :"second-version"
110
- end
111
-
112
- it 'adds a top-level function even when not executed at the top-level' do
113
- eval_str('((lambda X
114
- (defun return-X () X)) 7)').should == :"return-X"
115
- eval_str('(return-X)').should == 7
116
- end
117
-
118
- it 'raises an error when attempting to redefine a primitive' do
119
- expect {
120
- eval_str('(defun + (A B) (* A B))')
121
- }.to raise_error(Kl::Error, '+ is primitive and may not be redefined')
122
- end
123
- end
124
-
125
- describe 'evaluation of boolean special forms' do
126
- describe "cond" do
127
- before(:each) do
128
- eval_str('(defun tr () true)')
129
- eval_str('(defun fa () false)')
130
- end
131
-
132
- it 'returns the value of the expression associate with the first true' do
133
- @env.should_not_receive(:tr)
134
- eval_str('(cond (false (tr))
135
- ((fa) 37)
136
- (true 42)
137
- (true (tr)))').should == 42
138
- end
139
-
140
- it 'raises an error upon falling off the end' do
141
- expect {
142
- eval_str('(cond (false 37) ((fa) 42))')
143
- }.to raise_error(Kl::Error, 'condition failure')
144
- end
145
- end
146
- end
147
-
148
- describe "error handling" do
149
- it 'raises uncaught errors' do
150
- expect {
151
- eval_str('(simple-error "boom!")')
152
- }.to raise_error(Kl::Error, 'boom!')
153
- end
154
-
155
- it 'moves past caught errors' do
156
- eval_str('(trap-error
157
- (simple-error "boom!")
158
- (lambda E 37))').should == 37
159
- end
160
-
161
- it 'treats undefined functions as simple errors' do
162
- expect {
163
- eval_str('(foo)')
164
- }.to raise_error(Kl::Error, 'The function foo is undefined')
165
- end
166
- end
167
-
168
- describe "setting values" do
169
- it 'returns the value set' do
170
- eval_str('(set foo 37)').should == 37
171
- end
172
-
173
- it 'previously set values are retrievable' do
174
- eval_str('(set foo 37)')
175
- eval_str('(value foo)').should == 37
176
- end
177
-
178
- it 'raises an error when fetching an unset value' do
179
- expect {
180
- eval_str('(value foo)')
181
- }.to raise_error(Kl::Error, 'variable foo has no value')
182
- end
183
- end
184
-
185
- describe "evaluation of freeze" do
186
- it 'delays computation' do
187
- eval_str('(defun one () 1)')
188
- @env.should_not_receive(:one)
189
- eval_str('(freeze (one))').should be_kind_of Proc
190
- end
191
-
192
- it 'is thawable later' do
193
- eval_str('(defun one () 1)')
194
- eval_str('((freeze (one)))').should == 1
195
- end
196
- end
197
-
198
- describe 'evaulation of type' do
199
- it 'evaluates the expression and ignores the type information' do
200
- eval_str('(type (+ 1 2) number)').should == 3
201
- end
202
- end
203
-
204
- describe 'evaluation of eval-kl' do
205
- it 'evals as expected' do
206
- eval_str('(eval-kl (+ 1 2))').should == 3
207
- end
208
- end
209
-
210
- describe 'currying' do
211
- it 'supports partial application of primitives' do
212
- eval_str('((+ 1) 2)').should == 3
213
- eval_str('(((+) 1) 2)').should == 3
214
- end
215
-
216
- it 'supports partial application of user-defined functions' do
217
- eval_str('(defun adder (X Y) (+ X Y))')
218
- eval_str('((adder 1) 2)').should == 3
219
- eval_str('(((adder) 1) 2)').should == 3
220
- end
221
-
222
- it 'supports uncurrying of nested lambdas' do
223
- eval_str('((lambda X (lambda Y (* X Y))) 6 7)').should == 42
224
- end
225
-
226
- it 'supports uncurrying of higher-order functions' do
227
- eval_str('(defun adder (X) (lambda Y (+ X Y)))')
228
- eval_str('(adder 1 2)').should == 3
229
- end
230
-
231
- it 'raises an error of too many arguments are given' do
232
- expect {
233
- eval_str('((lambda X (lambda Y (* X Y))) 6 7 8)')
234
- }.to raise_error(Kl::Error, 'The value 42 is neither a function nor a symbol.')
235
- end
236
- end
237
-
238
- describe 'tail recursion' do
239
- it 'does not blow the stack' do
240
- eval_str('(defun count-down (X)
241
- (if (= X 0)
242
- success
243
- (count-down (- X 1))))')
244
- eval_str('(count-down 100000)').should == :success
245
- end
246
- end
247
-
248
- describe 'stack overflow' do
249
- it 'is translated into a Shen simple-error' do
250
- eval_str('(defun boom () (+ 1 (boom)))')
251
- expect {
252
- eval_str('(boom)')
253
- }.to raise_error(Kl::Error, 'maximum stack depth exceeded')
254
- end
255
-
256
- it 'doesn\'t overflow when do is in tail position' do
257
- eval_str('(defun factorial-h (X Acc)
258
- (if (= X 0)
259
- Acc
260
- (do dummy (factorial-h (- X 1) (* X Acc)))))')
261
- expect {
262
- eval_str('(factorial-h 10000 1)')
263
- }.to_not raise_error
264
- end
265
- end
266
-
267
- describe 'optimized do expression' do
268
- it 'evaluates to the value of the second expression' do
269
- eval_str('(do (cn "fi" "rst") (cn "sec" "ond"))').should == "second"
270
- end
271
-
272
- it 'evaluates the first expression, then the second' do
273
- eval_str('(set temp-value 0)')
274
- eval_str('(do (set temp-value 10) (= 10 (value temp-value)))').should == true
275
- end
276
-
277
- it 'supports partial application' do
278
- eval_str('((do a) b)').should == :b
279
- eval_str('(((do) a) b)').should == :b
280
- end
281
- end
282
- end
@@ -1,68 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Ruby->Shen interop' 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
- it 'allows K Lambda functions to be invoked as methods on environment' do
14
- eval_str('(defun square (X) (* X X))')
15
- @env.respond_to?(:square).should be true
16
- @env.square(7).should == 49
17
- end
18
-
19
- it 'hides the details of trampolines for tail recursive functions' do
20
- eval_str('(defun countdown (X) (if (= X 0) true (countdown (- X 1))))')
21
- @env.countdown(10001).should == true
22
- end
23
-
24
- it 'coerces underscores to hyphens in function names' do
25
- eval_str('(defun typical-function-name (X) X)')
26
- @env.respond_to?(:typical_function_name).should be true
27
- @env.typical_function_name(37).should == 37
28
- end
29
-
30
- it 'raises NoMethodError if the function cannot be found' do
31
- expect {
32
- @env.undefined_function
33
- }.to raise_error(NoMethodError)
34
- end
35
-
36
- describe 'when invoking non-primitives' do
37
- it 'coerces array arguments to K Lambda lists ' do
38
- eval_str('(defun first (X) (hd X))')
39
- @env.first([1, 2, 3]).should == 1
40
- end
41
-
42
- it 'coerces nested array arguments to K Lambda lists ' do
43
- eval_str('(defun caadr (X) (hd (hd (tl X))))')
44
- @env.caadr([1, [2, 3]]).should == 2
45
- end
46
-
47
- it 'coerces list results to Ruby arrays' do
48
- eval_str('(defun a-list () (cons 1 (cons 2 ())))')
49
- @env.a_list.should == [1, 2]
50
- end
51
-
52
- it 'coerces nested list results to Ruby arrays' do
53
- eval_str('(defun a-list () (cons 1 (cons (cons 2 (cons 3 ())) ())))')
54
- @env.a_list.should == [1, [2, 3]]
55
- end
56
-
57
- it 'coerces underscore to hyphen in symbol arguments' do
58
- eval_str('(defun foo (X) (set result X))')
59
- @env.foo(:a_symbol)
60
- eval_str('(value result)').should == :"a-symbol"
61
- end
62
-
63
- it 'coerces hyphen to underscore in results' do
64
- eval_str('(defun foo () a-symbol)')
65
- @env.foo.should == :a_symbol
66
- end
67
- end
68
- end