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,40 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'Primitives for lists' do
|
4
|
-
describe '(cons Hd Tl)' do
|
5
|
-
it 'creates a list with Hd as the head and Tl as the tail' do
|
6
|
-
kl_eval('(cons a ())').should be_kind_of Kl::Cons
|
7
|
-
kl_eval('(hd (cons a ()))').should == :a
|
8
|
-
kl_eval('(tl (cons a (cons b ())))').should == kl_eval('(cons b ())')
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'allows Tl to be a non-list' do
|
12
|
-
kl_eval('(tl (cons a b))').should == :b
|
13
|
-
end
|
14
|
-
|
15
|
-
include_examples 'partially-applicable function', %w(cons a b)
|
16
|
-
include_examples 'applicative order evaluation', %w(cons a b)
|
17
|
-
end
|
18
|
-
|
19
|
-
describe '(hd L)' do
|
20
|
-
it 'returns the head of L' do
|
21
|
-
kl_eval('(hd (cons a b))').should == :a
|
22
|
-
end
|
23
|
-
|
24
|
-
include_examples 'argument types', [:hd, "(cons a b)"], 1 => [:list, :dotted_pair]
|
25
|
-
include_examples 'partially-applicable function', [:hd, "(cons a b)"]
|
26
|
-
end
|
27
|
-
|
28
|
-
describe '(tl L)' do
|
29
|
-
it 'returns the tail of L' do
|
30
|
-
kl_eval('(tl (cons a b))').should == :b
|
31
|
-
end
|
32
|
-
|
33
|
-
include_examples 'argument types', [:tl, "(cons a b)"], 1 => [:list, :dotted_pair]
|
34
|
-
include_examples 'partially-applicable function', [:tl, "(cons a b)"]
|
35
|
-
end
|
36
|
-
|
37
|
-
describe 'cons?' do
|
38
|
-
include_examples 'type predicate', 'cons?', [:list, :dotted_pair]
|
39
|
-
end
|
40
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'Primitives for strings' do
|
4
|
-
describe '(pos S N)' do
|
5
|
-
it 'returns the character at zero-based index N of S as a unit string' do
|
6
|
-
kl_eval('(pos "ABC" 1)').should == "B"
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'raises an error if N is negative' do
|
10
|
-
expect {
|
11
|
-
kl_eval('(pos "ABC" -1)')
|
12
|
-
}.to raise_error(Kl::Error, "out of bounds")
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'raises an error if N is >= the length of S' do
|
16
|
-
expect {
|
17
|
-
kl_eval('(pos "ABC" 3)')
|
18
|
-
}.to raise_error(Kl::Error, "out of bounds")
|
19
|
-
expect {
|
20
|
-
kl_eval('(pos "ABC" 99)')
|
21
|
-
}.to raise_error(Kl::Error, "out of bounds")
|
22
|
-
end
|
23
|
-
|
24
|
-
include_examples 'argument types', %w(pos "string" 1),
|
25
|
-
1 => [:string],
|
26
|
-
2 => [:integer]
|
27
|
-
include_examples 'partially-applicable function', %w(pos "string" 1)
|
28
|
-
include_examples 'applicative order evaluation', %w(pos "string" 1)
|
29
|
-
end
|
30
|
-
|
31
|
-
describe '(tlstr S)' do
|
32
|
-
it 'returns a string containing all but the first character of S' do
|
33
|
-
kl_eval('(tlstr "string")').should == "tring"
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'raises an error when S is the empty string' do
|
37
|
-
expect {
|
38
|
-
kl_eval('(tlstr "")')
|
39
|
-
}.to raise_error(Kl::Error, 'attempted to take tail of an empty string')
|
40
|
-
end
|
41
|
-
|
42
|
-
include_examples 'argument types', %w(tlstr "string"), 1 => [:string]
|
43
|
-
include_examples 'partially-applicable function', %w(tlstr "string")
|
44
|
-
end
|
45
|
-
|
46
|
-
describe 'string?' do
|
47
|
-
include_examples 'type predicate', 'string?', [:string]
|
48
|
-
end
|
49
|
-
|
50
|
-
describe '(n->string N)' do
|
51
|
-
it 'returns a unit string containing the character with ASCII code N' do
|
52
|
-
kl_eval('(n->string 65)').should == "A"
|
53
|
-
end
|
54
|
-
|
55
|
-
include_examples 'argument types', %w(n->string 65), 1 => [:integer]
|
56
|
-
include_examples 'partially-applicable function', %w(n->string 65)
|
57
|
-
end
|
58
|
-
|
59
|
-
describe '(string->n S)' do
|
60
|
-
it 'returns the ASCII code of the unit string S' do
|
61
|
-
kl_eval('(string->n "A")').should == 65
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'returns the ASCII code of the first character of non-unit string S' do
|
65
|
-
kl_eval('(string->n "AB")').should == 65
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'raises an error when S is the empty string' do
|
69
|
-
expect {
|
70
|
-
kl_eval('(string->n "")')
|
71
|
-
}.to raise_error(Kl::Error, 'attempted to get code point of empty string')
|
72
|
-
end
|
73
|
-
|
74
|
-
include_examples 'argument types', %w(string->n "A"), 1 => [:string]
|
75
|
-
include_examples 'partially-applicable function', %w(string->n "A")
|
76
|
-
end
|
77
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'Primitives for symbols' do
|
4
|
-
describe 'intern' do
|
5
|
-
it 'converts a string to its corresponding symbol' do
|
6
|
-
kl_eval('(intern "foo")').should == :foo
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'supports characters not allowed in symbol literals' do
|
10
|
-
kl_eval('(intern "[{|}]")').should == :"[{|}]"
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'converts the string "true" to boolean true' do
|
14
|
-
kl_eval('(intern "true")').should == true
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'converts the string "false" to boolean false' do
|
18
|
-
kl_eval('(intern "false")').should == false
|
19
|
-
end
|
20
|
-
|
21
|
-
include_examples 'argument types', %w(intern "foo"), 1 => [:string]
|
22
|
-
include_examples 'partially-applicable function', %w(intern "foo")
|
23
|
-
end
|
24
|
-
end
|
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'Primitive functions for vectors' do
|
4
|
-
describe '(absvector N)' do
|
5
|
-
it 'returns a new absolute vector of size N' do
|
6
|
-
kl_eval('(absvector 3)').should be_kind_of Kl::Absvector
|
7
|
-
end
|
8
|
-
|
9
|
-
include_examples 'argument types', %w(absvector 7), 1 => [:integer]
|
10
|
-
include_examples 'partially-applicable function', %w(absvector 7)
|
11
|
-
end
|
12
|
-
|
13
|
-
describe '(address-> V N Value)' do
|
14
|
-
before(:each) do
|
15
|
-
kl_eval('(set *vec* (absvector 5))')
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'returns the vector V updated with Value at index N' do
|
19
|
-
kl_eval('(address-> (value *vec*) 3 37)').should be_kind_of Kl::Absvector
|
20
|
-
kl_eval('(<-address (value *vec*) 3)').should == 37
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'raises an error if N is negative' do
|
24
|
-
expect {
|
25
|
-
kl_eval('(address-> (value *vec*) -1 37)')
|
26
|
-
}.to raise_error(Kl::Error, "out of bounds")
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'raises an error if N is >= the size of the vector' do
|
30
|
-
expect {
|
31
|
-
kl_eval('(address-> (value *vec*) 5 37)')
|
32
|
-
}.to raise_error(Kl::Error, "out of bounds")
|
33
|
-
expect {
|
34
|
-
kl_eval('(address-> (value *vec*) 99 37)')
|
35
|
-
}.to raise_error(Kl::Error, "out of bounds")
|
36
|
-
end
|
37
|
-
|
38
|
-
include_examples 'argument types',
|
39
|
-
['address->', '(value *vec*)', '0', '37'],
|
40
|
-
1 => [:vector],
|
41
|
-
2 => [:integer]
|
42
|
-
include_examples 'partially-applicable function',
|
43
|
-
['address->', '(value *vec*)', '0', '37']
|
44
|
-
include_examples 'applicative order evaluation',
|
45
|
-
['address->', '(value *vec*)', '0', '37']
|
46
|
-
end
|
47
|
-
|
48
|
-
describe '(<-address V N)' do
|
49
|
-
before(:each) do
|
50
|
-
kl_eval('(set *vec* (absvector 5))')
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'returns the value previously stored at index N in V' do
|
54
|
-
kl_eval('(address-> (value *vec*) 3 37)')
|
55
|
-
kl_eval('(<-address (value *vec*) 3)').should == 37
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'returns an unspecified value if index N has not been stored to' do
|
59
|
-
expect {
|
60
|
-
kl_eval('(<-address (value *vec*) 3)')
|
61
|
-
}.to_not raise_error
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'raises an error if N is negative' do
|
65
|
-
expect {
|
66
|
-
kl_eval('(<-address (value *vec*) -1)')
|
67
|
-
}.to raise_error(Kl::Error, "out of bounds")
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'raises an error if N is >= the size of the vector' do
|
71
|
-
expect {
|
72
|
-
kl_eval('(<-address (value *vec*) 5)')
|
73
|
-
}.to raise_error(Kl::Error, "out of bounds")
|
74
|
-
expect {
|
75
|
-
kl_eval('(<-address (value *vec*) 99)')
|
76
|
-
}.to raise_error(Kl::Error, "out of bounds")
|
77
|
-
end
|
78
|
-
|
79
|
-
include_examples 'argument types',
|
80
|
-
['<-address', '(value *vec*)', '0'],
|
81
|
-
1 => [:vector],
|
82
|
-
2 => [:integer]
|
83
|
-
include_examples 'partially-applicable function',
|
84
|
-
['address->', '(value *vec*)', '0', '37']
|
85
|
-
include_examples 'applicative order evaluation',
|
86
|
-
['address->', '(value *vec*)', '0', '37']
|
87
|
-
end
|
88
|
-
|
89
|
-
describe 'absvector?' do
|
90
|
-
include_examples 'type predicate', 'absvector?', [:vector]
|
91
|
-
end
|
92
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
lib_path = File.expand_path("../../lib", __FILE__)
|
2
|
-
$LOAD_PATH << lib_path unless $LOAD_PATH.include?(lib_path)
|
3
|
-
|
4
|
-
require 'kl'
|
5
|
-
require 'stringio'
|
6
|
-
|
7
|
-
# Load the support files
|
8
|
-
Dir["./k_lambda_spec/support/**/*.rb"].sort.each {|f| require f}
|
9
|
-
|
10
|
-
# Reset the K Lambda environment before every example
|
11
|
-
RSpec.configure do |config|
|
12
|
-
config.before(:each) do
|
13
|
-
@kl_env = Kl::Environment.new
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# Helper function that evaluates a string in the K Lambda environment and
|
18
|
-
# returns the result as a Ruby object.
|
19
|
-
def kl_eval(str)
|
20
|
-
form = Kl::Reader.new(StringIO.new(str)).next
|
21
|
-
@kl_env.__eval(form)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Defines the 'kl-do' function in the current K Lambda environment. This is
|
25
|
-
# used instead of 'do' because do is not an official K Lambda primitive
|
26
|
-
# and may not be found in all K Lambda implementations.
|
27
|
-
def define_kl_do
|
28
|
-
kl_eval('(defun kl-do (X Y) Y)')
|
29
|
-
end
|
@@ -1,124 +0,0 @@
|
|
1
|
-
# args should be an array containing the components of an example expression.
|
2
|
-
# E.g., to test partial application of +, you could use:
|
3
|
-
#
|
4
|
-
# include_examples "partially-applicable function", %w(+ 1 2)
|
5
|
-
#
|
6
|
-
# The expression will be evaluated in its fully-expanded form for reference
|
7
|
-
# and then compared against various partial application scenarios.
|
8
|
-
shared_examples "partially-applicable function" do |args|
|
9
|
-
full_expression = "(#{args.join(' ')})"
|
10
|
-
(0...(args.length - 1)).each do |arg_count|
|
11
|
-
description = "supports partial application of #{arg_count} argument"
|
12
|
-
description << "s" unless arg_count == 1
|
13
|
-
it description do
|
14
|
-
full_result = kl_eval(full_expression)
|
15
|
-
partial_expression = "((#{args[0..arg_count].join(' ')}) #{args[(arg_count + 1)..-1].join(' ')})"
|
16
|
-
kl_eval(partial_expression).should == full_result
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
shared_examples "non-partially-applicable function" do |args|
|
22
|
-
(0...(args.length - 1)).each do |arg_count|
|
23
|
-
description = "raises an error when given #{arg_count} argument"
|
24
|
-
description << "s" unless arg_count == 1
|
25
|
-
it description do
|
26
|
-
partial_expression = "(#{args[0..arg_count].join(' ')})"
|
27
|
-
expect {
|
28
|
-
kl_eval(partial_expression)
|
29
|
-
}.to raise_error(Kl::Error, "#{args[0]} expects #{args.length - 1} arguments but was given #{arg_count}")
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# args should be an array containing the components of an example expression.
|
35
|
-
# E.g., to test applicative order evaluation of +, you could use:
|
36
|
-
#
|
37
|
-
# include_examples "applicative order evaluation", %w(+ 1 2)
|
38
|
-
shared_examples 'applicative order evaluation' do |args|
|
39
|
-
it 'evaluates its arguments from left to right' do
|
40
|
-
operator = args.shift
|
41
|
-
arg_indexes = (0...args.size).to_a
|
42
|
-
instrumented_args = args.zip(arg_indexes).map do |(arg, idx)|
|
43
|
-
"(kl-do (set *arg-order* (cn (value *arg-order*) \"#{idx}\")) #{arg})"
|
44
|
-
end
|
45
|
-
expected = arg_indexes.join
|
46
|
-
|
47
|
-
define_kl_do
|
48
|
-
kl_eval('(set *arg-order* "")')
|
49
|
-
kl_eval("(#{operator} #{instrumented_args.join(' ')})")
|
50
|
-
kl_eval('(value *arg-order*)').should == expected
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
KL_TYPE_EXAMPLES = {
|
55
|
-
integer: '1',
|
56
|
-
real: '1.0',
|
57
|
-
string: '"a string"',
|
58
|
-
symbol: 'a-symbol',
|
59
|
-
boolean: 'true',
|
60
|
-
list: '(cons 1 ())',
|
61
|
-
dotted_pair: '(cons 1 2)',
|
62
|
-
empty_list: '()',
|
63
|
-
function: '(lambda X X)',
|
64
|
-
vector: '(absvector 3)'
|
65
|
-
}
|
66
|
-
|
67
|
-
def type_with_article(type)
|
68
|
-
name = type.to_s.gsub(/_/, ' ')
|
69
|
-
if [:integer, :empty_list].include?(type)
|
70
|
-
'an ' + name
|
71
|
-
else
|
72
|
-
'a ' + name
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
shared_examples 'type predicate' do |predicate, accepted_types|
|
77
|
-
accepted_types.each do |type|
|
78
|
-
it "returns true when its argument is #{type_with_article(type)}" do
|
79
|
-
kl_eval("(#{predicate} #{KL_TYPE_EXAMPLES[type]})").should == true
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'returns false when its argument is of any other type' do
|
84
|
-
rejected_types = KL_TYPE_EXAMPLES.keys - accepted_types
|
85
|
-
rejected_types.each do |type|
|
86
|
-
kl_eval("(#{predicate} #{KL_TYPE_EXAMPLES[type]})").should == false
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
POSITION_NAMES = { 1 => 'first', 2 => 'second', 3 => 'third' }
|
92
|
-
|
93
|
-
def types_to_s(types)
|
94
|
-
if types.length > 2
|
95
|
-
types[0..-2].map { |t| type_with_article(t) }.join(', ') +
|
96
|
-
', or ' + type_with_article(types[-1])
|
97
|
-
else
|
98
|
-
types.map { |t| type_with_article(t) }.join(' or ')
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
shared_examples 'argument types' do |expr, accepted_argument_types|
|
103
|
-
accepted_argument_types.to_a.sort.each do |(idx, accepted_types)|
|
104
|
-
type_str = types_to_s(accepted_types)
|
105
|
-
it "raises an error if its #{POSITION_NAMES[idx]} argument is not #{type_str}" do
|
106
|
-
accepted_types.each do |type|
|
107
|
-
other_expr = expr.dup
|
108
|
-
other_expr[idx] = KL_TYPE_EXAMPLES[type]
|
109
|
-
expect {
|
110
|
-
kl_eval("(#{other_expr.join(' ')})")
|
111
|
-
}.to_not raise_error
|
112
|
-
end
|
113
|
-
|
114
|
-
rejected_types = KL_TYPE_EXAMPLES.keys - accepted_types
|
115
|
-
rejected_types.each do |type|
|
116
|
-
other_expr = expr.dup
|
117
|
-
other_expr[idx] = KL_TYPE_EXAMPLES[type]
|
118
|
-
expect {
|
119
|
-
kl_eval("(#{other_expr.join(' ')})")
|
120
|
-
}.to raise_error(Kl::Error, /is not a/)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe 'Tail recursion' do
|
4
|
-
it 'does not consume stack space for self tail calls' do
|
5
|
-
kl_eval <<-EOS
|
6
|
-
(defun count-down (X)
|
7
|
-
(if (= X 0)
|
8
|
-
success
|
9
|
-
(count-down (- X 1))))
|
10
|
-
EOS
|
11
|
-
kl_eval('(count-down 10000)').should == :success
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'does not consume stack space for mutually recursive tail calls' do
|
15
|
-
kl_eval <<-EOS
|
16
|
-
(defun even? (X)
|
17
|
-
(if (= X 1)
|
18
|
-
false
|
19
|
-
(odd? (- X 1))))
|
20
|
-
EOS
|
21
|
-
kl_eval <<-EOS
|
22
|
-
(defun odd? (X)
|
23
|
-
(if (= X 1)
|
24
|
-
true
|
25
|
-
(even? (- X 1))))
|
26
|
-
EOS
|
27
|
-
kl_eval('(even? 100000)').should == true
|
28
|
-
kl_eval('(odd? 100000)').should == false
|
29
|
-
end
|
30
|
-
end
|
data/lib/kl.rb
DELETED
data/lib/kl/absvector.rb
DELETED