-
Notifications
You must be signed in to change notification settings - Fork 0
/
if_spec.rb
371 lines (312 loc) · 8.23 KB
/
if_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
require_relative '../spec_helper'
describe "The if expression" do
describe "accepts multiple assignments in conditional expression" do
before(:each) { ScratchPad.record([]) }
after(:each) { ScratchPad.clear }
it 'with non-nil values' do
ary = [1, 2]
eval "if (a, b = ary); ScratchPad.record [a, b]; end"
ScratchPad.recorded.should == [1, 2]
end
it 'with nil values' do
ary = nil
eval "if (a, b = ary); else; ScratchPad.record [a, b]; end"
ScratchPad.recorded.should == [nil, nil]
end
end
it "evaluates body if expression is true" do
a = []
if true
a << 123
end
a.should == [123]
end
it "does not evaluate body if expression is false" do
a = []
if false
a << 123
end
a.should == []
end
it "does not evaluate body if expression is empty" do
a = []
if ()
a << 123
end
a.should == []
end
it "does not evaluate else-body if expression is true" do
a = []
if true
a << 123
else
a << 456
end
a.should == [123]
end
it "evaluates only else-body if expression is false" do
a = []
if false
a << 123
else
a << 456
end
a.should == [456]
end
it "returns result of then-body evaluation if expression is true" do
if true
123
end.should == 123
end
it "returns result of last statement in then-body if expression is true" do
if true
'foo'
'bar'
'baz'
end.should == 'baz'
end
it "returns result of then-body evaluation if expression is true and else part is present" do
if true
123
else
456
end.should == 123
end
it "returns result of else-body evaluation if expression is false" do
if false
123
else
456
end.should == 456
end
it "returns nil if then-body is empty and expression is true" do
if true
end.should == nil
end
it "returns nil if then-body is empty, expression is true and else part is present" do
if true
else
456
end.should == nil
end
it "returns nil if then-body is empty, expression is true and else part is empty" do
if true
else
end.should == nil
end
it "returns nil if else-body is empty and expression is false" do
if false
123
else
end.should == nil
end
it "returns nil if else-body is empty, expression is false and then-body is empty" do
if false
else
end.should == nil
end
it "considers an expression with nil result as false" do
if nil
123
else
456
end.should == 456
end
it "considers a non-nil and non-boolean object in expression result as true" do
if mock('x')
123
else
456
end.should == 123
end
it "considers a zero integer in expression result as true" do
if 0
123
else
456
end.should == 123
end
it "allows starting else-body on the same line" do
if false
123
else 456
end.should == 456
end
it "evaluates subsequent elsif statements and execute body of first matching" do
if false
123
elsif false
234
elsif true
345
elsif true
456
end.should == 345
end
it "evaluates else-body if no if/elsif statements match" do
if false
123
elsif false
234
elsif false
345
else
456
end.should == 456
end
it "allows 'then' after expression when then-body is on the next line" do
if true then
123
end.should == 123
if true then ; 123; end.should == 123
end
it "allows then-body on the same line separated with 'then'" do
if true then 123
end.should == 123
if true then 123; end.should == 123
end
it "returns nil when then-body on the same line separated with 'then' and expression is false" do
if false then 123
end.should == nil
if false then 123; end.should == nil
end
it "returns nil when then-body separated by 'then' is empty and expression is true" do
if true then
end.should == nil
if true then ; end.should == nil
end
it "returns nil when then-body separated by 'then', expression is false and no else part" do
if false then
end.should == nil
if false then ; end.should == nil
end
it "evaluates then-body when then-body separated by 'then', expression is true and else part is present" do
if true then 123
else 456
end.should == 123
if true then 123; else 456; end.should == 123
end
it "evaluates else-body when then-body separated by 'then' and expression is false" do
if false then 123
else 456
end.should == 456
if false then 123; else 456; end.should == 456
end
describe "with a boolean range ('flip-flop' operator)" do
before :each do
ScratchPad.record []
end
after :each do
ScratchPad.clear
end
it "mimics an awk conditional with a single-element inclusive-end range" do
10.times { |i| ScratchPad << i if (i == 4)..(i == 4) }
ScratchPad.recorded.should == [4]
end
it "mimics an awk conditional with a many-element inclusive-end range" do
10.times { |i| ScratchPad << i if (i == 4)..(i == 7) }
ScratchPad.recorded.should == [4, 5, 6, 7]
end
it "mimics a sed conditional with a zero-element exclusive-end range" do
eval "10.times { |i| ScratchPad << i if (i == 4)...(i == 4) }"
ScratchPad.recorded.should == [4, 5, 6, 7, 8, 9]
end
it "mimics a sed conditional with a many-element exclusive-end range" do
10.times { |i| ScratchPad << i if (i == 4)...(i == 5) }
ScratchPad.recorded.should == [4, 5]
end
it "allows combining two flip-flops" do
10.times { |i| ScratchPad << i if (i == 4)...(i == 5) or (i == 7)...(i == 8) }
ScratchPad.recorded.should == [4, 5, 7, 8]
end
it "evaluates the first conditions lazily with inclusive-end range" do
collector = proc { |i| ScratchPad << i }
eval "10.times { |i| i if collector[i]...false }"
ScratchPad.recorded.should == [0]
end
it "evaluates the first conditions lazily with exclusive-end range" do
collector = proc { |i| ScratchPad << i }
eval "10.times { |i| i if collector[i]..false }"
ScratchPad.recorded.should == [0]
end
it "evaluates the second conditions lazily with inclusive-end range" do
collector = proc { |i| ScratchPad << i }
10.times { |i| i if (i == 4)...collector[i] }
ScratchPad.recorded.should == [5]
end
it "evaluates the second conditions lazily with exclusive-end range" do
collector = proc { |i| ScratchPad << i }
10.times { |i| i if (i == 4)..collector[i] }
ScratchPad.recorded.should == [4]
end
it "scopes state by flip-flop" do
store_me = proc { |i| ScratchPad << i if (i == 4)..(i == 7) }
store_me[1]
store_me[4]
proc { store_me[1] }.call
store_me[7]
store_me[5]
ScratchPad.recorded.should == [4, 1, 7]
end
it "keeps flip-flops from interfering" do
a = eval "proc { |i| ScratchPad << i if (i == 4)..(i == 7) }"
b = eval "proc { |i| ScratchPad << i if (i == 4)..(i == 7) }"
6.times(&a)
6.times(&b)
ScratchPad.recorded.should == [4, 5, 4, 5]
end
end
end
describe "The postfix if form" do
it "evaluates statement if expression is true" do
a = []
a << 123 if true
a.should == [123]
end
it "does not evaluate statement if expression is false" do
a = []
a << 123 if false
a.should == []
end
it "returns result of expression if value is true" do
(123 if true).should == 123
end
it "returns nil if expression is false" do
(123 if false).should == nil
end
it "considers a nil expression as false" do
(123 if nil).should == nil
end
it "considers a non-nil object as true" do
(123 if mock('x')).should == 123
end
it "evaluates then-body in containing scope" do
a = 123
if true
b = a+1
end
b.should == 124
end
it "evaluates else-body in containing scope" do
a = 123
if false
b = a+1
else
b = a+2
end
b.should == 125
end
it "evaluates elsif-body in containing scope" do
a = 123
if false
b = a+1
elsif false
b = a+2
elsif true
b = a+3
else
b = a+4
end
b.should == 126
end
end