skeem 0.2.21 → 0.2.22
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/.rubocop.yml +33 -337
- data/CHANGELOG.md +7 -0
- data/LICENSE.txt +1 -1
- data/lib/skeem/grammar.rb +13 -13
- data/lib/skeem/interpreter.rb +1 -1
- data/lib/skeem/primitive/primitive_builder.rb +1 -1
- data/lib/skeem/primitive/primitive_procedure.rb +1 -1
- data/lib/skeem/runtime.rb +2 -0
- data/lib/skeem/s_expr_nodes.rb +5 -3
- data/lib/skeem/tokenizer.rb +15 -20
- data/lib/skeem/version.rb +1 -1
- data/lib/skeem.rb +2 -2
- data/skeem.gemspec +8 -5
- data/spec/skeem/datum_dsl_spec.rb +50 -50
- data/spec/skeem/element_visitor_spec.rb +108 -108
- data/spec/skeem/interpreter_spec.rb +171 -169
- data/spec/skeem/lambda_spec.rb +27 -27
- data/spec/skeem/parser_spec.rb +27 -25
- data/spec/skeem/primitive/primitive_builder_spec.rb +127 -131
- data/spec/skeem/primitive/primitive_procedure_spec.rb +28 -28
- data/spec/skeem/runtime_spec.rb +52 -51
- data/spec/skeem/s_expr_nodes_spec.rb +31 -31
- data/spec/skeem/skm_compound_datum_spec.rb +36 -35
- data/spec/skeem/skm_element_spec.rb +35 -34
- data/spec/skeem/skm_empty_list_spec.rb +19 -19
- data/spec/skeem/skm_frame_spec.rb +49 -46
- data/spec/skeem/skm_pair_spec.rb +93 -93
- data/spec/skeem/skm_procedure_exec_spec.rb +11 -11
- data/spec/skeem/skm_simple_datum_spec.rb +102 -95
- data/spec/skeem/skm_unary_expression_spec.rb +60 -61
- data/spec/skeem/tokenizer_spec.rb +52 -52
- data/spec/skeem_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -2
- metadata +62 -18
@@ -5,46 +5,46 @@ require_relative '../../lib/skeem/skm_empty_list' # Load the class under test
|
|
5
5
|
|
6
6
|
module Skeem
|
7
7
|
describe SkmEmptyList do
|
8
|
-
subject {
|
8
|
+
subject(:empty_list) { described_class.instance }
|
9
9
|
|
10
10
|
context 'Initialization:' do
|
11
|
-
it '
|
12
|
-
expect {
|
11
|
+
it 'is initialized without argument' do
|
12
|
+
expect { described_class.instance }.not_to raise_error
|
13
13
|
end
|
14
14
|
|
15
15
|
# Default (overridable) behavior of SkmElement
|
16
|
-
it '
|
17
|
-
expect(
|
18
|
-
expect(
|
19
|
-
expect(
|
16
|
+
it 'reacts by default to predicates' do
|
17
|
+
expect(empty_list).to be_list
|
18
|
+
expect(empty_list).to be_null
|
19
|
+
expect(empty_list).not_to be_pair
|
20
20
|
end
|
21
21
|
end # context
|
22
22
|
|
23
23
|
context 'Provided services:' do
|
24
24
|
let(:runtime) { double('fake-runtime') }
|
25
25
|
|
26
|
-
it '
|
27
|
-
expect(
|
28
|
-
expect(
|
26
|
+
it 'is equivalent to itself' do
|
27
|
+
expect(empty_list).to be_eqv(described_class.instance)
|
28
|
+
expect(empty_list).not_to be_eqv('()')
|
29
29
|
end
|
30
30
|
|
31
|
-
it "
|
32
|
-
expect(
|
31
|
+
it "returns itself when receiving 'evaluate' message" do
|
32
|
+
expect(empty_list.evaluate(runtime)).to eq(empty_list)
|
33
33
|
end
|
34
34
|
|
35
|
-
it "
|
36
|
-
expect(
|
35
|
+
it "returns itself receiving 'quasiquote' message" do
|
36
|
+
expect(empty_list.quasiquote(runtime)).to eq(empty_list)
|
37
37
|
end
|
38
38
|
|
39
|
-
it "
|
39
|
+
it "replies to visitor's 'accept' message" do
|
40
40
|
visitor = double('fake-visitor')
|
41
|
-
|
42
|
-
expect {
|
41
|
+
allow(visitor).to receive(:visit_empty_list).with(empty_list)
|
42
|
+
expect { empty_list.accept(visitor) }.not_to raise_error
|
43
43
|
end
|
44
44
|
|
45
|
-
it '
|
45
|
+
it 'returns its representation upon inspection' do
|
46
46
|
predicted = '<Skeem::SkmEmptyList: ()>'
|
47
|
-
expect(
|
47
|
+
expect(empty_list.inspect).to eq(predicted)
|
48
48
|
end
|
49
49
|
end # context
|
50
50
|
end # describe
|
@@ -8,111 +8,114 @@ module Skeem
|
|
8
8
|
describe SkmFrame do
|
9
9
|
include DatumDSL
|
10
10
|
|
11
|
-
let(:sample_env) {
|
11
|
+
let(:sample_env) { described_class.new }
|
12
|
+
|
13
|
+
subject(:a_frame) { described_class.new }
|
14
|
+
|
12
15
|
context 'Initialization:' do
|
13
16
|
it 'could be initialized without argument' do
|
14
|
-
expect {
|
17
|
+
expect { described_class.new }.not_to raise_error
|
15
18
|
end
|
16
19
|
|
17
20
|
it 'could be initialized with optional argument' do
|
18
|
-
expect {
|
21
|
+
expect { described_class.new(sample_env) }.not_to raise_error
|
19
22
|
end
|
20
23
|
|
21
|
-
it '
|
22
|
-
expect(
|
24
|
+
it 'has no default bindings' do
|
25
|
+
expect(a_frame).to be_empty
|
23
26
|
end
|
24
27
|
|
25
|
-
it '
|
26
|
-
expect(
|
28
|
+
it 'has depth of zero or one' do
|
29
|
+
expect(a_frame.depth).to be_zero
|
27
30
|
|
28
|
-
instance =
|
31
|
+
instance = described_class.new(sample_env)
|
29
32
|
expect(instance.depth).to eq(1)
|
30
33
|
end
|
31
34
|
end # context
|
32
35
|
|
33
36
|
context 'Provided services:' do
|
34
|
-
it '
|
37
|
+
it 'adds binding' do
|
35
38
|
entry = double('original-dummy')
|
36
|
-
|
39
|
+
allow(entry).to receive(:bound!).with(a_frame)
|
37
40
|
|
38
|
-
|
39
|
-
expect(
|
40
|
-
expect(
|
41
|
-
expect(
|
41
|
+
a_frame.add_binding('dummy', entry)
|
42
|
+
expect(a_frame.size).to eq(1)
|
43
|
+
expect(a_frame.bindings['dummy']).not_to be_nil
|
44
|
+
expect(a_frame.bindings['dummy']).to eq(entry)
|
42
45
|
|
43
46
|
# A child frame may shadow a parent's variable
|
44
|
-
child =
|
47
|
+
child = described_class.new(a_frame)
|
45
48
|
entry2 = double('dummy')
|
46
|
-
|
49
|
+
allow(entry2).to receive(:bound!).with(child)
|
47
50
|
child.add_binding(identifier('dummy'), entry2)
|
48
51
|
|
49
52
|
expect(child.bindings['dummy']).to eq(entry2)
|
50
|
-
expect(
|
53
|
+
expect(a_frame.bindings['dummy']).to eq(entry)
|
51
54
|
end
|
52
55
|
|
53
|
-
it '
|
56
|
+
it 'updates bindings' do
|
54
57
|
entry1 = double('dummy')
|
55
|
-
|
58
|
+
allow(entry1).to receive(:bound!).with(a_frame)
|
56
59
|
|
57
60
|
# Case 1: entry defined in this frame
|
58
|
-
|
59
|
-
expect(
|
61
|
+
a_frame.add_binding('dummy', entry1)
|
62
|
+
expect(a_frame.bindings['dummy']).to eq(entry1)
|
60
63
|
|
61
64
|
entry2 = double('still-dummy')
|
62
|
-
|
63
|
-
|
64
|
-
expect(
|
65
|
+
allow(entry2).to receive(:bound!).with(a_frame)
|
66
|
+
a_frame.update_binding(identifier('dummy'), entry2)
|
67
|
+
expect(a_frame.bindings['dummy']).to eq(entry2)
|
65
68
|
|
66
69
|
# Case 2: entry defined in parent frame
|
67
|
-
child =
|
70
|
+
child = described_class.new(a_frame)
|
68
71
|
entry3 = double('still-dummy')
|
69
|
-
|
72
|
+
allow(entry3).to receive(:bound!).with(a_frame)
|
70
73
|
child.update_binding('dummy', entry3)
|
71
|
-
expect(
|
74
|
+
expect(a_frame.bindings['dummy']).to eq(entry3)
|
72
75
|
end
|
73
76
|
|
74
|
-
it '
|
77
|
+
it 'retrieves entries' do
|
75
78
|
# Case 1: non-existing entry
|
76
|
-
expect(
|
79
|
+
expect(a_frame.fetch('dummy')).to be_nil
|
77
80
|
|
78
81
|
# Case 2: existing entry
|
79
82
|
entry = double('dummy')
|
80
|
-
|
81
|
-
|
82
|
-
expect(
|
83
|
+
allow(entry).to receive(:bound!).with(a_frame)
|
84
|
+
a_frame.add_binding('dummy', entry)
|
85
|
+
expect(a_frame.fetch('dummy')).to eq(entry)
|
83
86
|
|
84
87
|
# Case 3: entry defined in parent frame
|
85
|
-
child =
|
88
|
+
child = described_class.new(a_frame)
|
86
89
|
expect(child.fetch(identifier('dummy'))).to eq(entry)
|
87
90
|
end
|
88
91
|
|
89
|
-
it '
|
92
|
+
it 'knows whether it is empty' do
|
90
93
|
# Case 1: no entry
|
91
|
-
expect(
|
94
|
+
expect(a_frame).to be_empty
|
92
95
|
|
93
96
|
# Case 2: existing entry
|
94
97
|
entry = double('dummy')
|
95
|
-
|
96
|
-
|
97
|
-
expect(
|
98
|
+
allow(entry).to receive(:bound!).with(a_frame)
|
99
|
+
a_frame.add_binding('dummy', entry)
|
100
|
+
expect(a_frame).not_to be_empty
|
98
101
|
|
99
102
|
# Case 3: entry defined in parent frame
|
100
|
-
nested =
|
101
|
-
expect(nested
|
103
|
+
nested = described_class.new(a_frame)
|
104
|
+
expect(nested).not_to be_empty
|
102
105
|
end
|
103
106
|
|
104
|
-
it '
|
107
|
+
it 'knows the total number of bindings' do
|
105
108
|
# Case 1: non-existing entry
|
106
|
-
expect(
|
109
|
+
expect(a_frame.size).to be_zero
|
107
110
|
|
108
111
|
# Case 2: existing entry
|
109
112
|
entry = double('dummy')
|
110
|
-
|
111
|
-
|
112
|
-
expect(
|
113
|
+
allow(entry).to receive(:bound!).with(a_frame)
|
114
|
+
a_frame.add_binding('dummy', entry)
|
115
|
+
expect(a_frame.size).to eq(1)
|
113
116
|
|
114
117
|
# Case 3: entry defined in parent environment
|
115
|
-
nested =
|
118
|
+
nested = described_class.new(a_frame)
|
116
119
|
expect(nested.size).to eq(1)
|
117
120
|
end
|
118
121
|
end # context
|
data/spec/skeem/skm_pair_spec.rb
CHANGED
@@ -12,44 +12,44 @@ module Skeem
|
|
12
12
|
let(:sample_cdr) { SkmEmptyList.instance }
|
13
13
|
|
14
14
|
# Default instance is proper list of length 1
|
15
|
-
subject {
|
15
|
+
subject(:a_pair) { described_class.new(sample_car, sample_cdr) }
|
16
16
|
|
17
17
|
context 'Initialization:' do
|
18
|
-
it '
|
19
|
-
expect {
|
18
|
+
it 'is initialized with two arguments' do
|
19
|
+
expect { described_class.new(sample_car, sample_cdr) }.not_to raise_error
|
20
20
|
end
|
21
21
|
|
22
|
-
it "
|
23
|
-
expect(
|
22
|
+
it "knows its 'car' field" do
|
23
|
+
expect(a_pair.car).to eq(sample_car)
|
24
24
|
end
|
25
25
|
|
26
|
-
it "
|
27
|
-
expect(
|
26
|
+
it "knows its 'cdr' field" do
|
27
|
+
expect(a_pair.cdr).to eq(sample_cdr)
|
28
28
|
end
|
29
29
|
|
30
30
|
# Default (overridable) behavior of SkmElement
|
31
|
-
it '
|
32
|
-
expect(
|
33
|
-
expect(
|
34
|
-
expect(
|
31
|
+
it 'reacts by default to predicates' do
|
32
|
+
expect(a_pair).to be_list
|
33
|
+
expect(a_pair).not_to be_null
|
34
|
+
expect(a_pair).to be_pair
|
35
35
|
end
|
36
36
|
end # context
|
37
37
|
|
38
38
|
context 'Provided services:' do
|
39
39
|
let(:runtime) { Runtime.new(SkmFrame.new) }
|
40
|
-
let(:list_length2) {
|
40
|
+
let(:list_length2) { described_class.new(integer(10), a_pair) }
|
41
41
|
let(:quirk_element) { double('three') }
|
42
42
|
let(:quirk_members) { [integer(10), quirk_element] }
|
43
43
|
|
44
|
-
it '
|
45
|
-
cloned =
|
46
|
-
expect(cloned.car).to eq(
|
47
|
-
expect(cloned.cdr).to eq(
|
44
|
+
it 'clones itself' do
|
45
|
+
cloned = a_pair.klone
|
46
|
+
expect(cloned.car).to eq(a_pair.car)
|
47
|
+
expect(cloned.cdr).to eq(a_pair.cdr)
|
48
48
|
end
|
49
49
|
|
50
|
-
it '
|
51
|
-
pair2 =
|
52
|
-
pair1 =
|
50
|
+
it 'clones a proper list' do
|
51
|
+
pair2 = described_class.new(identifier('b'), SkmEmptyList.instance)
|
52
|
+
pair1 = described_class.new(identifier('a'), pair2)
|
53
53
|
|
54
54
|
cloned = pair1.klone
|
55
55
|
expect(cloned.car).to eq(identifier('a'))
|
@@ -57,9 +57,9 @@ module Skeem
|
|
57
57
|
expect(cloned.cdr.cdr).to be_null
|
58
58
|
end
|
59
59
|
|
60
|
-
it '
|
61
|
-
pair2 =
|
62
|
-
pair1 =
|
60
|
+
it 'clones a improper list' do
|
61
|
+
pair2 = described_class.new(identifier('b'), identifier('c'))
|
62
|
+
pair1 = described_class.new(identifier('a'), pair2)
|
63
63
|
|
64
64
|
cloned = pair1.klone
|
65
65
|
expect(cloned.car).to eq(identifier('a'))
|
@@ -67,164 +67,164 @@ module Skeem
|
|
67
67
|
expect(cloned.cdr.cdr).to eq(identifier('c'))
|
68
68
|
end
|
69
69
|
|
70
|
-
it '
|
71
|
-
expect(
|
70
|
+
it 'knows its length' do
|
71
|
+
expect(a_pair.length).to eq(1)
|
72
72
|
|
73
73
|
# Use a list of length 2
|
74
74
|
expect(list_length2.length).to eq(2)
|
75
75
|
end
|
76
76
|
|
77
|
-
it '
|
78
|
-
expect(
|
77
|
+
it 'responds false to `eqv?` message' do
|
78
|
+
expect(a_pair.eqv?(a_pair)).to be(false)
|
79
79
|
end
|
80
80
|
|
81
|
-
it '
|
82
|
-
expect(
|
81
|
+
it 'is Skeem equal to itself' do
|
82
|
+
expect(a_pair.skm_equal?(a_pair)).to be(true)
|
83
83
|
end
|
84
84
|
|
85
85
|
|
86
|
-
it '
|
87
|
-
instance =
|
88
|
-
expect(
|
86
|
+
it 'is equal to other pair when their car and cdr match' do
|
87
|
+
instance = described_class.new(sample_car, sample_cdr)
|
88
|
+
expect(a_pair.skm_equal?(instance)).to be(true)
|
89
89
|
instance.car = integer(4)
|
90
|
-
expect(
|
90
|
+
expect(a_pair.skm_equal?(instance)).to be(false)
|
91
91
|
instance.car = sample_car
|
92
|
-
instance.cdr =
|
93
|
-
expect(
|
92
|
+
instance.cdr = a_pair
|
93
|
+
expect(a_pair.skm_equal?(instance)).to be(false)
|
94
94
|
end
|
95
95
|
|
96
|
-
it '
|
97
|
-
#
|
98
|
-
expect(
|
96
|
+
it 'clones itself after member evaluation' do
|
97
|
+
# a_pair contains self-evaluating members
|
98
|
+
expect(a_pair.clone_evaluate(runtime)).to eq(a_pair)
|
99
99
|
|
100
100
|
# Make pair improper...
|
101
|
-
|
102
|
-
expect(
|
101
|
+
a_pair.cdr = nil
|
102
|
+
expect(a_pair.clone_evaluate(runtime)).to eq(a_pair)
|
103
103
|
|
104
|
-
|
105
|
-
expect(
|
104
|
+
a_pair.cdr = integer(4)
|
105
|
+
expect(a_pair.clone_evaluate(runtime)).to eq(a_pair)
|
106
106
|
|
107
|
-
successor =
|
108
|
-
|
109
|
-
expect(
|
107
|
+
successor = described_class.new(string('Hi'), boolean(false))
|
108
|
+
a_pair.cdr = successor
|
109
|
+
expect(a_pair.clone_evaluate(runtime)).to eq(a_pair)
|
110
110
|
end
|
111
111
|
|
112
|
-
it '
|
113
|
-
expect(
|
112
|
+
it 'concerts itself into an array' do
|
113
|
+
expect(a_pair.to_a).to eq([sample_car])
|
114
114
|
|
115
115
|
# Use a list of length 2
|
116
116
|
expect(list_length2.to_a).to eq([integer(10), sample_car])
|
117
117
|
end
|
118
118
|
|
119
|
-
it '
|
120
|
-
expect(
|
119
|
+
it 'returns the last pair of a proper list' do
|
120
|
+
expect(a_pair.last_pair).to eq(a_pair)
|
121
121
|
|
122
|
-
pair2 =
|
123
|
-
pair1 =
|
122
|
+
pair2 = described_class.new(identifier('b'), SkmEmptyList.instance)
|
123
|
+
pair1 = described_class.new(identifier('a'), pair2)
|
124
124
|
expect(pair1.last_pair).to eq(pair1)
|
125
125
|
end
|
126
126
|
|
127
|
-
it '
|
128
|
-
pair3 =
|
129
|
-
pair2 =
|
130
|
-
pair1 =
|
127
|
+
it 'returns the last pair of an improper list' do
|
128
|
+
pair3 = described_class.new(identifier('c'), identifier('d'))
|
129
|
+
pair2 = described_class.new(identifier('b'), pair3)
|
130
|
+
pair1 = described_class.new(identifier('a'), pair2)
|
131
131
|
expect(pair1.last_pair).to eq(pair3)
|
132
132
|
end
|
133
133
|
|
134
|
-
it '
|
135
|
-
expect(
|
134
|
+
it 'returns the last element of a list' do
|
135
|
+
expect(a_pair.last).to eq(sample_car)
|
136
136
|
expect(list_length2.last).to eq(sample_car)
|
137
137
|
end
|
138
138
|
|
139
|
-
it '
|
140
|
-
|
141
|
-
expect(
|
142
|
-
expect(
|
139
|
+
it 'appends a new element to a list' do
|
140
|
+
a_pair.append(integer(4))
|
141
|
+
expect(a_pair.length).to eq(2)
|
142
|
+
expect(a_pair.to_a).to eq([3, 4])
|
143
143
|
end
|
144
144
|
|
145
|
-
it '
|
145
|
+
it 'creates a list from an array' do
|
146
146
|
# List of length 0
|
147
147
|
array0 = []
|
148
|
-
list =
|
148
|
+
list = described_class.create_from_a(array0)
|
149
149
|
expect(list).to be_list # It's a proper list...
|
150
150
|
expect(list.length).to eq(0)
|
151
151
|
expect(list.to_a).to eq(array0)
|
152
152
|
|
153
153
|
# List of length 1
|
154
154
|
array1 = [boolean(false)]
|
155
|
-
list =
|
155
|
+
list = described_class.create_from_a(array1)
|
156
156
|
expect(list).to be_list # It's a proper list...
|
157
157
|
expect(list.length).to eq(1)
|
158
158
|
expect(list.to_a).to eq(array1)
|
159
159
|
|
160
160
|
# List of length 2
|
161
161
|
array2 = [identifier('f'), identifier('g')]
|
162
|
-
list =
|
162
|
+
list = described_class.create_from_a(array2)
|
163
163
|
expect(list).to be_list # It's a proper list...
|
164
164
|
expect(list.length).to eq(2)
|
165
165
|
expect(list.to_a).to eq(array2)
|
166
166
|
|
167
167
|
# List of length 3
|
168
168
|
array3 = [integer(4), integer(5), integer(6)]
|
169
|
-
list =
|
169
|
+
list = described_class.create_from_a(array3)
|
170
170
|
expect(list).to be_list # It's a proper list...
|
171
171
|
expect(list.length).to eq(3)
|
172
172
|
expect(list.to_a).to eq([4, 5, 6])
|
173
173
|
end
|
174
174
|
|
175
|
-
it '
|
176
|
-
my_list =
|
175
|
+
it 'supports the each method' do
|
176
|
+
my_list = described_class.new('w', described_class.new('o', described_class.new('w', SkmEmptyList.instance)))
|
177
177
|
text = +''
|
178
178
|
my_list.each { |ch| text << ch.upcase }
|
179
179
|
expect(text).to eq('WOW')
|
180
180
|
end
|
181
181
|
|
182
|
-
it '
|
183
|
-
expect(
|
184
|
-
|
185
|
-
expect(
|
186
|
-
instance =
|
187
|
-
|
188
|
-
expect(
|
182
|
+
it 'implements the verbatim predicate' do
|
183
|
+
expect(a_pair).to be_verbatim
|
184
|
+
a_pair.cdr = nil
|
185
|
+
expect(a_pair).to be_verbatim
|
186
|
+
instance = described_class.new(string('Hi'), SkmEmptyList.instance)
|
187
|
+
a_pair.cdr = instance
|
188
|
+
expect(a_pair).to be_verbatim
|
189
189
|
bad_end = double('fake_end')
|
190
190
|
instance.cdr = bad_end
|
191
|
-
|
192
|
-
expect(
|
191
|
+
allow(bad_end).to receive(:verbatim?).and_return(false)
|
192
|
+
expect(a_pair).not_to be_verbatim
|
193
193
|
bad_datum = double('fake-datum')
|
194
|
-
|
194
|
+
allow(bad_datum).to receive(:verbatim?).and_return(false)
|
195
195
|
instance.car = bad_datum
|
196
|
-
expect(
|
196
|
+
expect(a_pair).not_to be_verbatim
|
197
197
|
end
|
198
198
|
|
199
|
-
it '
|
200
|
-
#
|
201
|
-
expect(
|
199
|
+
it 'evaluates its members' do
|
200
|
+
# a_pair contains simple literals
|
201
|
+
expect(a_pair.evaluate(runtime)).to eq(a_pair)
|
202
202
|
|
203
203
|
# Check that members receive the 'evaluate' message
|
204
|
-
|
205
|
-
instance =
|
204
|
+
allow(quirk_element).to receive(:evaluate).with(runtime).and_return(integer(3))
|
205
|
+
instance = described_class.create_from_a(quirk_members)
|
206
206
|
expect { instance.evaluate(runtime) }.not_to raise_error
|
207
207
|
end
|
208
208
|
|
209
|
-
it '
|
210
|
-
#
|
211
|
-
expect(
|
209
|
+
it 'quasiquote its members' do
|
210
|
+
# a_pair contains simple literals
|
211
|
+
expect(a_pair.quasiquote(runtime)).to eq(a_pair)
|
212
212
|
|
213
213
|
# Check that members receive the 'quasiquote' message
|
214
|
-
|
215
|
-
instance =
|
214
|
+
allow(quirk_element).to receive(:quasiquote).with(runtime).and_return(integer(3))
|
215
|
+
instance = described_class.create_from_a(quirk_members)
|
216
216
|
expect { instance.quasiquote(runtime) }.not_to raise_error
|
217
217
|
end
|
218
218
|
|
219
|
-
it "
|
219
|
+
it "replies to visitor's 'accept' message" do
|
220
220
|
visitor = double('fake-visitor')
|
221
|
-
|
222
|
-
expect {
|
221
|
+
allow(visitor).to receive(:visit_pair).with(a_pair)
|
222
|
+
expect { a_pair.accept(visitor) }.not_to raise_error
|
223
223
|
end
|
224
224
|
|
225
|
-
it '
|
225
|
+
it 'returns its representation upon inspection' do
|
226
226
|
predicted = '<Skeem::SkmPair: <Skeem::SkmInteger: 3>>'
|
227
|
-
expect(
|
227
|
+
expect(a_pair.inspect).to eq(predicted)
|
228
228
|
|
229
229
|
predicted = '<Skeem::SkmPair: <Skeem::SkmInteger: 10>, <Skeem::SkmInteger: 3>>'
|
230
230
|
expect(list_length2.inspect).to eq(predicted)
|
@@ -32,32 +32,32 @@ SKEEM
|
|
32
32
|
result.root
|
33
33
|
end
|
34
34
|
|
35
|
-
subject {
|
35
|
+
subject(:proc_exec) { described_class.new(sample_lamb) }
|
36
36
|
|
37
37
|
context 'Initialization:' do
|
38
|
-
it '
|
39
|
-
expect {
|
38
|
+
it 'is initialized with one lambda' do
|
39
|
+
expect { described_class.new(sample_lamb) }.not_to raise_error
|
40
40
|
end
|
41
41
|
|
42
|
-
it '
|
43
|
-
expect(
|
42
|
+
it 'knows the definition of the procedure' do
|
43
|
+
expect(proc_exec.definition).to eq(sample_lamb)
|
44
44
|
end
|
45
45
|
end # context
|
46
46
|
|
47
47
|
context 'Executing a compound procedure:' do
|
48
|
-
it '
|
49
|
-
|
48
|
+
it 'executes the procedure that is called' do
|
49
|
+
proc_exec
|
50
50
|
call_args = sample_call.operands.to_a
|
51
|
-
result =
|
51
|
+
result = proc_exec.run!(interpreter.runtime, call_args)
|
52
52
|
expect(result).to eq(9)
|
53
53
|
end
|
54
54
|
|
55
|
-
it '
|
56
|
-
|
55
|
+
it 'executes the procedure with a procedure call in argument' do
|
56
|
+
proc_exec
|
57
57
|
|
58
58
|
ptree = interpreter.parse('(square (+ (+ 2 1) 2))')
|
59
59
|
call_args = ptree.root.operands.to_a
|
60
|
-
result =
|
60
|
+
result = proc_exec.run!(interpreter.runtime, call_args)
|
61
61
|
expect(result).to eq(25)
|
62
62
|
end
|
63
63
|
end
|