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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.travis.yml +9 -3
- data/Gemfile +1 -4
- data/HISTORY.md +16 -0
- data/MIT_LICENSE.txt +1 -1
- data/README.md +25 -26
- data/Rakefile +3 -11
- data/bin/shen_test_suite.rb +15 -3
- data/bin/srrepl +6 -8
- data/lib/shen_ruby.rb +6 -1
- data/lib/shen_ruby/converters.rb +23 -0
- data/lib/shen_ruby/version.rb +1 -1
- data/shen-ruby.gemspec +4 -1
- data/shen/lib/shen_ruby/shen.rb +49 -33
- data/shen/release/benchmarks/N_queens.shen +45 -45
- data/shen/release/benchmarks/README.shen +14 -14
- data/shen/release/benchmarks/benchmarks.shen +52 -52
- data/shen/release/benchmarks/einstein.shen +32 -32
- data/shen/release/benchmarks/interpreter.shen +219 -219
- data/shen/release/benchmarks/jnk.shen +193 -193
- data/shen/release/benchmarks/powerset.shen +10 -10
- data/shen/release/benchmarks/prime.shen +10 -10
- data/shen/release/benchmarks/short.shen +129 -129
- data/shen/release/k_lambda/core.kl +181 -181
- data/shen/release/k_lambda/declarations.kl +131 -131
- data/shen/release/k_lambda/load.kl +84 -84
- data/shen/release/k_lambda/macros.kl +112 -112
- data/shen/release/k_lambda/prolog.kl +252 -252
- data/shen/release/k_lambda/reader.kl +222 -222
- data/shen/release/k_lambda/sequent.kl +166 -166
- data/shen/release/k_lambda/sys.kl +271 -271
- data/shen/release/k_lambda/t-star.kl +139 -139
- data/shen/release/k_lambda/toplevel.kl +135 -135
- data/shen/release/k_lambda/track.kl +103 -103
- data/shen/release/k_lambda/types.kl +324 -324
- data/shen/release/k_lambda/writer.kl +105 -105
- data/shen/release/k_lambda/yacc.kl +113 -113
- data/shen/release/test_programs/Chap13/problems.txt +26 -26
- data/shen/release/test_programs/README.shen +52 -52
- data/shen/release/test_programs/TinyLispFunctions.txt +15 -15
- data/shen/release/test_programs/TinyTypes.shen +55 -55
- data/shen/release/test_programs/binary.shen +24 -24
- data/shen/release/test_programs/bubble_version_1.shen +28 -28
- data/shen/release/test_programs/bubble_version_2.shen +22 -22
- data/shen/release/test_programs/calculator.shen +21 -21
- data/shen/release/test_programs/cartprod.shen +23 -23
- data/shen/release/test_programs/change.shen +25 -25
- data/shen/release/test_programs/classes-defaults.shen +94 -94
- data/shen/release/test_programs/classes-inheritance.shen +100 -100
- data/shen/release/test_programs/classes-typed.shen +74 -74
- data/shen/release/test_programs/classes-untyped.shen +46 -46
- data/shen/release/test_programs/depth_.shen +14 -14
- data/shen/release/test_programs/einstein.shen +34 -34
- data/shen/release/test_programs/fruit_machine.shen +46 -46
- data/shen/release/test_programs/interpreter.shen +217 -217
- data/shen/release/test_programs/metaprog.shen +85 -85
- data/shen/release/test_programs/minim.shen +192 -192
- data/shen/release/test_programs/mutual.shen +11 -11
- data/shen/release/test_programs/n_queens.shen +45 -45
- data/shen/release/test_programs/newton_version_1.shen +33 -33
- data/shen/release/test_programs/newton_version_2.shen +24 -24
- data/shen/release/test_programs/parse.prl +14 -14
- data/shen/release/test_programs/parser.shen +51 -51
- data/shen/release/test_programs/powerset.shen +10 -10
- data/shen/release/test_programs/prime.shen +10 -10
- data/shen/release/test_programs/prolog.shen +78 -78
- data/shen/release/test_programs/proof_assistant.shen +80 -80
- data/shen/release/test_programs/proplog_version_1.shen +25 -25
- data/shen/release/test_programs/proplog_version_2.shen +27 -27
- data/shen/release/test_programs/qmachine.shen +66 -66
- data/shen/release/test_programs/red-black.shen +54 -54
- data/shen/release/test_programs/search.shen +55 -55
- data/shen/release/test_programs/semantic_net.shen +44 -44
- data/shen/release/test_programs/spreadsheet.shen +34 -34
- data/shen/release/test_programs/stack.shen +27 -27
- data/shen/release/test_programs/streams.shen +20 -20
- data/shen/release/test_programs/strings.shen +57 -57
- data/shen/release/test_programs/structures-typed.shen +71 -71
- data/shen/release/test_programs/structures-untyped.shen +41 -41
- data/shen/release/test_programs/tests.shen +232 -232
- data/shen/release/test_programs/types.shen +11 -11
- data/shen/release/test_programs/whist.shen +239 -239
- data/shen/release/test_programs/yacc.shen +132 -132
- data/spec/shen_ruby/converters_spec.rb +48 -0
- data/spec/spec_helper.rb +1 -2
- metadata +55 -60
- data/k_lambda_spec/atom_spec.rb +0 -85
- data/k_lambda_spec/primitives/arithmetic_spec.rb +0 -175
- data/k_lambda_spec/primitives/assignments_spec.rb +0 -44
- data/k_lambda_spec/primitives/boolean_operations_spec.rb +0 -136
- data/k_lambda_spec/primitives/generic_functions_spec.rb +0 -120
- data/k_lambda_spec/primitives/lists_spec.rb +0 -40
- data/k_lambda_spec/primitives/strings_spec.rb +0 -77
- data/k_lambda_spec/primitives/symbols_spec.rb +0 -24
- data/k_lambda_spec/primitives/vectors_spec.rb +0 -92
- data/k_lambda_spec/spec_helper.rb +0 -29
- data/k_lambda_spec/support/shared_examples.rb +0 -124
- data/k_lambda_spec/tail_recursion_spec.rb +0 -30
- data/lib/kl.rb +0 -7
- data/lib/kl/absvector.rb +0 -12
- data/lib/kl/compiler.rb +0 -360
- data/lib/kl/cons.rb +0 -51
- data/lib/kl/empty_list.rb +0 -12
- data/lib/kl/environment.rb +0 -163
- data/lib/kl/error.rb +0 -4
- data/lib/kl/internal_error.rb +0 -7
- data/lib/kl/lexer.rb +0 -186
- data/lib/kl/primitives/arithmetic.rb +0 -60
- data/lib/kl/primitives/assignments.rb +0 -15
- data/lib/kl/primitives/booleans.rb +0 -21
- data/lib/kl/primitives/error_handling.rb +0 -13
- data/lib/kl/primitives/extensions.rb +0 -12
- data/lib/kl/primitives/generic_functions.rb +0 -29
- data/lib/kl/primitives/lists.rb +0 -23
- data/lib/kl/primitives/streams.rb +0 -28
- data/lib/kl/primitives/strings.rb +0 -63
- data/lib/kl/primitives/symbols.rb +0 -18
- data/lib/kl/primitives/time.rb +0 -17
- data/lib/kl/primitives/vectors.rb +0 -36
- data/lib/kl/reader.rb +0 -46
- data/spec/kl/cons_spec.rb +0 -12
- data/spec/kl/environment_spec.rb +0 -282
- data/spec/kl/interop_spec.rb +0 -68
- data/spec/kl/lexer_spec.rb +0 -149
- data/spec/kl/primitives/generic_functions_spec.rb +0 -29
- data/spec/kl/primitives/symbols_spec.rb +0 -21
- 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
|
data/lib/kl/primitives/time.rb
DELETED
@@ -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
|
data/spec/kl/environment_spec.rb
DELETED
@@ -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
|
data/spec/kl/interop_spec.rb
DELETED
@@ -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
|