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