shen-ruby 0.10.0 → 0.11.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 (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