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