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.
@@ -10,37 +10,39 @@ module Skeem
10
10
  include InterpreterSpec
11
11
  include DatumDSL
12
12
 
13
+ subject(:interpreter) { described_class.new }
14
+
13
15
  context 'Initialization:' do
14
16
  it 'could be initialized without an argument' do
15
- expect { Interpreter.new }.not_to raise_error
17
+ expect { described_class.new }.not_to raise_error
16
18
  end
17
19
 
18
20
  it 'could be initialized with a block argument' do
19
- expect { Interpreter.new(&:runtime) }.not_to raise_error
21
+ expect { described_class.new(&:runtime) }.not_to raise_error
20
22
  end
21
23
 
22
- it 'should have a parser' do
23
- expect(subject.parser).not_to be_nil
24
+ it 'has a parser' do
25
+ expect(interpreter.parser).not_to be_nil
24
26
  end
25
27
 
26
- it 'should have a runtime object' do
27
- expect(subject.runtime).to be_kind_of(Runtime)
28
+ it 'has a runtime object' do
29
+ expect(interpreter.runtime).to be_a(Runtime)
28
30
  end
29
31
 
30
- it 'should come with built-in functions' do
31
- expect(subject.runtime.environment).not_to be_empty
32
+ it 'comes with built-in functions' do
33
+ expect(interpreter.runtime.environment).not_to be_empty
32
34
  end
33
35
 
34
- it 'should implement base bindings' do
35
- expect(subject.fetch('number?')).to be_kind_of(Primitive::PrimitiveProcedure)
36
- expect(subject.fetch('abs')).to be_kind_of(SkmLambda)
37
- expect(subject.fetch('abs').formals.arity).to eq(1)
38
- expect(subject.fetch('abs').formals.formals[0]).to eq('x')
36
+ it 'implements base bindings' do
37
+ expect(interpreter.fetch('number?')).to be_a(Primitive::PrimitiveProcedure)
38
+ expect(interpreter.fetch('abs')).to be_a(SkmLambda)
39
+ expect(interpreter.fetch('abs').formals.arity).to eq(1)
40
+ expect(interpreter.fetch('abs').formals.formals[0]).to eq('x')
39
41
  end
40
42
  end # context
41
43
 
42
44
  context 'Interpreting self-evaluating expressions' do
43
- it 'should evaluate isolated booleans' do
45
+ it 'evaluates isolated booleans' do
44
46
  samples = [
45
47
  ['#f', false],
46
48
  ['#false', false],
@@ -48,12 +50,12 @@ module Skeem
48
50
  ['#true', true]
49
51
  ]
50
52
  compare_to_predicted(samples) do |result, predicted|
51
- expect(result).to be_kind_of(SkmBoolean)
53
+ expect(result).to be_a(SkmBoolean)
52
54
  expect(result).to eq(predicted)
53
55
  end
54
56
  end
55
57
 
56
- it 'should evaluate isolated integers' do
58
+ it 'evaluates isolated integers' do
57
59
  samples = [
58
60
  ['0', 0],
59
61
  ['3', 3],
@@ -62,13 +64,13 @@ module Skeem
62
64
  ['-12345', -12345]
63
65
  ]
64
66
  compare_to_predicted(samples) do |result, predicted|
65
- expect(result).to be_kind_of(SkmInteger)
67
+ expect(result).to be_a(SkmInteger)
66
68
  expect(result).to eq(predicted)
67
69
  end
68
70
  end
69
71
 
70
72
  # rubocop: disable Style/ExponentialNotation
71
- it 'should evaluate isolated real numbers' do
73
+ it 'evaluates isolated real numbers' do
72
74
  samples = [
73
75
  ['0.0', 0.0],
74
76
  ['3.14', 3.14],
@@ -77,27 +79,27 @@ module Skeem
77
79
  ['-123e-45', -123e-45]
78
80
  ]
79
81
  compare_to_predicted(samples) do |result, predicted|
80
- expect(result).to be_kind_of(SkmReal)
82
+ expect(result).to be_a(SkmReal)
81
83
  expect(result).to eq(predicted)
82
84
  end
83
85
  end
84
86
  # rubocop: enable Style/ExponentialNotation
85
87
 
86
- it 'should evaluate isolated strings' do
88
+ it 'evaluates isolated strings' do
87
89
  samples = [
88
90
  ['"Hello, world"', 'Hello, world']
89
91
  ]
90
92
  compare_to_predicted(samples) do |result, predicted|
91
- expect(result).to be_kind_of(SkmString)
93
+ expect(result).to be_a(SkmString)
92
94
  expect(result).to eq(predicted)
93
95
  end
94
96
  end
95
97
 
96
- it 'should evaluate vector of constants' do
98
+ it 'evaluates vector of constants' do
97
99
  require 'benchmark'
98
100
  source = '#(2018 10 20 "Sat")'
99
- result = subject.run(source)
100
- expect(result).to be_kind_of(SkmVector)
101
+ result = interpreter.run(source)
102
+ expect(result).to be_a(SkmVector)
101
103
  predictions = [
102
104
  [SkmInteger, 2018],
103
105
  [SkmInteger, 10],
@@ -105,31 +107,31 @@ module Skeem
105
107
  [SkmString, 'Sat']
106
108
  ]
107
109
  predictions.each_with_index do |(type, value), index|
108
- expect(result.members[index]).to be_kind_of(type)
110
+ expect(result.members[index]).to be_a(type)
109
111
  expect(result.members[index]).to eq(value)
110
112
  end
111
113
  end
112
114
  end # context
113
115
 
114
116
  context 'Built-in primitives' do
115
- it 'should implement variable definition' do
116
- subject.run('(define x 28)')
117
- expect(subject.fetch('x')).to eq(28)
117
+ it 'implements variable definition' do
118
+ interpreter.run('(define x 28)')
119
+ expect(interpreter.fetch('x')).to eq(28)
118
120
  end
119
121
 
120
- it 'should implement variable reference' do
122
+ it 'implements variable reference' do
121
123
  source = <<-SKEEM
122
124
  ; Example from R7RS section 4.1.1
123
125
  (define x 28)
124
126
  x
125
127
  SKEEM
126
- result = subject.run(source)
128
+ result = interpreter.run(source)
127
129
  end_result = result.last
128
- expect(end_result).to be_kind_of(SkmInteger)
130
+ expect(end_result).to be_a(SkmInteger)
129
131
  expect(end_result).to eq(28)
130
132
  end
131
133
 
132
- it 'should implement the simple conditional form' do
134
+ it 'implements the simple conditional form' do
133
135
  checks = [
134
136
  ['(if (> 3 2) "yes")', 'yes'],
135
137
  ['(if (> 2 3) "yes")', SkmUndefined.instance]
@@ -137,7 +139,7 @@ SKEEM
137
139
  compare_to_predicted(checks)
138
140
  end
139
141
 
140
- it 'should implement the complete conditional form' do
142
+ it 'implements the complete conditional form' do
141
143
  checks = [
142
144
  ['(if (> 3 2) "yes" "no")', 'yes'],
143
145
  ['(if (> 2 3) "yes" "no")', 'no']
@@ -149,11 +151,11 @@ SKEEM
149
151
  (- 3 2)
150
152
  (+ 3 2))
151
153
  SKEEM
152
- result = subject.run(source)
154
+ result = interpreter.run(source)
153
155
  expect(result).to eq(1)
154
156
  end
155
157
 
156
- it 'should implement the cond form' do
158
+ it 'implements the cond form' do
157
159
  source = <<-SKEEM
158
160
  (define signum (lambda (x)
159
161
  (cond
@@ -162,7 +164,7 @@ SKEEM
162
164
  ((< x 0) -1)
163
165
  )))
164
166
  SKEEM
165
- subject.run(source)
167
+ interpreter.run(source)
166
168
  checks = [
167
169
  ['(signum 3)', 1],
168
170
  ['(signum 0)', 0],
@@ -171,7 +173,7 @@ SKEEM
171
173
  compare_to_predicted(checks)
172
174
  end
173
175
 
174
- it 'should implement the cond form with arrows' do
176
+ it 'implements the cond form with arrows' do
175
177
  source = <<-SKEEM
176
178
  (define signum (lambda (x)
177
179
  (cond
@@ -180,7 +182,7 @@ SKEEM
180
182
  ((< x 0) => -1)
181
183
  )))
182
184
  SKEEM
183
- subject.run(source)
185
+ interpreter.run(source)
184
186
  checks = [
185
187
  ['(signum 3)', 1],
186
188
  ['(signum 0)', 0],
@@ -189,7 +191,7 @@ SKEEM
189
191
  compare_to_predicted(checks)
190
192
  end
191
193
 
192
- it 'should implement the cond ... else form' do
194
+ it 'implements the cond ... else form' do
193
195
  source = <<-SKEEM
194
196
  (define signum (lambda (x)
195
197
  (cond
@@ -198,7 +200,7 @@ SKEEM
198
200
  (else -1)
199
201
  )))
200
202
  SKEEM
201
- subject.run(source)
203
+ interpreter.run(source)
202
204
  checks = [
203
205
  ['(signum 3)', 1],
204
206
  ['(signum 0)', 0],
@@ -207,7 +209,7 @@ SKEEM
207
209
  compare_to_predicted(checks)
208
210
  end
209
211
 
210
- it 'should implement the truncate procedure' do
212
+ it 'implements the truncate procedure' do
211
213
  checks = [
212
214
  ['(truncate -4.3)', -4],
213
215
  ['(truncate 3.5)', 3]
@@ -215,7 +217,7 @@ SKEEM
215
217
  compare_to_predicted(checks)
216
218
  end
217
219
 
218
- it 'should implement the quotation of constant literals' do
220
+ it 'implements the quotation of constant literals' do
219
221
  checks = [
220
222
  ['(quote a)', 'a'],
221
223
  ['(quote 145932)', 145932],
@@ -229,25 +231,25 @@ SKEEM
229
231
  compare_to_predicted(checks)
230
232
  end
231
233
 
232
- it 'should implement the quotation of vectors' do
234
+ it 'implements the quotation of vectors' do
233
235
  source = '(quote #(a b c))'
234
- result = subject.run(source)
235
- expect(result).to be_kind_of(SkmVector)
236
+ result = interpreter.run(source)
237
+ expect(result).to be_a(SkmVector)
236
238
  predictions = [
237
239
  [SkmIdentifier, 'a'],
238
240
  [SkmIdentifier, 'b'],
239
241
  [SkmIdentifier, 'c']
240
242
  ]
241
243
  predictions.each_with_index do |(type, value), index|
242
- expect(result.members[index]).to be_kind_of(type)
244
+ expect(result.members[index]).to be_a(type)
243
245
  expect(result.members[index]).to eq(value)
244
246
  end
245
247
  end
246
248
 
247
- it 'should implement the quotation of lists' do
249
+ it 'implements the quotation of lists' do
248
250
  source = '(quote (+ 1 2))'
249
- result = subject.run(source)
250
- expect(result).to be_kind_of(SkmPair)
251
+ result = interpreter.run(source)
252
+ expect(result).to be_a(SkmPair)
251
253
  predictions = [
252
254
  [SkmIdentifier, '+'],
253
255
  [SkmInteger, 1],
@@ -255,25 +257,25 @@ SKEEM
255
257
  ]
256
258
  members = result.to_a
257
259
  predictions.each_with_index do |(type, value), index|
258
- expect(members[index]).to be_kind_of(type)
260
+ expect(members[index]).to be_a(type)
259
261
  expect(members[index]).to eq(value)
260
262
  end
261
263
 
262
264
  source = "'()"
263
- result = subject.run(source)
264
- expect(result).to be_kind_of(SkmEmptyList)
265
+ result = interpreter.run(source)
266
+ expect(result).to be_a(SkmEmptyList)
265
267
  expect(result).to be_null
266
268
  end
267
269
 
268
- it 'should implement the lambda function with one arg' do
270
+ it 'implements the lambda function with one arg' do
269
271
  source = <<-SKEEM
270
272
  ; Simplified 'abs' function implementation
271
273
  (define abs
272
274
  (lambda (x)
273
275
  (if (< x 0) (- x) x)))
274
276
  SKEEM
275
- subject.run(source)
276
- procedure = subject.fetch('abs')
277
+ interpreter.run(source)
278
+ procedure = interpreter.fetch('abs')
277
279
  expect(procedure.arity).to eq(1)
278
280
  checks = [
279
281
  ['(abs -3)', 3],
@@ -283,15 +285,15 @@ SKEEM
283
285
  compare_to_predicted(checks)
284
286
  end
285
287
 
286
- it 'should implement the lambda function with two args' do
288
+ it 'implements the lambda function with two args' do
287
289
  source = <<-SKEEM
288
290
  ; Simplified 'min' function implementation
289
291
  (define min
290
292
  (lambda (x y)
291
293
  (if (< x y) x y)))
292
294
  SKEEM
293
- subject.run(source)
294
- procedure = subject.fetch('min')
295
+ interpreter.run(source)
296
+ procedure = interpreter.fetch('min')
295
297
  expect(procedure.arity).to eq(2)
296
298
  checks = [
297
299
  ['(min 1 2)', 1],
@@ -301,7 +303,7 @@ SKEEM
301
303
  compare_to_predicted(checks)
302
304
  end
303
305
 
304
- it 'should implement recursive functions' do
306
+ it 'implements recursive functions' do
305
307
  source = <<-SKEEM
306
308
  ; Example from R7RS section 4.1.5
307
309
  (define fact (lambda (n)
@@ -310,57 +312,57 @@ SKEEM
310
312
  (* n (fact (- n 1))))))
311
313
  (fact 10)
312
314
  SKEEM
313
- result = subject.run(source)
315
+ result = interpreter.run(source)
314
316
  expect(result.last.value).to eq(3628800)
315
317
  end
316
318
 
317
- it 'should accept calls to anonymous procedures' do
319
+ it 'accepts calls to anonymous procedures' do
318
320
  source = '((lambda (x) (+ x x)) 4)'
319
- result = subject.run(source)
321
+ result = interpreter.run(source)
320
322
  expect(result).to eq(8)
321
323
  end
322
324
 
323
- it 'should support procedures with variable number of arguments' do
325
+ it 'supports procedures with variable number of arguments' do
324
326
  # Example from R7RS section 4.1.4
325
327
  source = '((lambda x x) 3 4 5 6)'
326
- result = subject.run(source)
327
- expect(result).to be_kind_of(SkmPair)
328
+ result = interpreter.run(source)
329
+ expect(result).to be_a(SkmPair)
328
330
  expect(result.length).to eq(4)
329
331
  end
330
332
 
331
- it 'should support procedures with dotted pair arguments' do
333
+ it 'supports procedures with dotted pair arguments' do
332
334
  # Example from R7RS section 4.1.4
333
335
  source = '((lambda (x y . z) z) 3 4 5 6)'
334
- result = subject.run(source)
335
- expect(result).to be_kind_of(SkmPair)
336
+ result = interpreter.run(source)
337
+ expect(result).to be_a(SkmPair)
336
338
  expect(result.length).to eq(2)
337
339
  expect(result.first).to eq(5)
338
340
  expect(result.last).to eq(6)
339
341
  end
340
342
 
341
- it 'should implement the compact define + lambda syntax' do
343
+ it 'implements the compact define + lambda syntax' do
342
344
  source = <<-SKEEM
343
345
  ; Alternative syntax to: (define f (lambda x (+ x 42)))
344
346
  (define (f x)
345
347
  (+ x 42))
346
348
  (f 23)
347
349
  SKEEM
348
- result = subject.run(source)
350
+ result = interpreter.run(source)
349
351
  expect(result.last.value).to eq(65)
350
352
  end
351
353
 
352
- it 'should implement the compact define + pair syntax' do
354
+ it 'implements the compact define + pair syntax' do
353
355
  source = <<-SKEEM
354
356
  ; Alternative syntax to: (define nlist (lambda args args))
355
357
  (define (nlist . args)
356
358
  args)
357
359
  (nlist 0 1 2 3 4)
358
360
  SKEEM
359
- result = subject.run(source)
361
+ result = interpreter.run(source)
360
362
  expect(result.last.last.value).to eq(4)
361
363
  end
362
364
 
363
- it 'should support the nested define construct' do
365
+ it 'supports the nested define construct' do
364
366
  source = <<-SKEEM
365
367
  (define (quadruple x)
366
368
  (define (double x) ; define a local procedure double
@@ -369,23 +371,23 @@ SKEEM
369
371
 
370
372
  (quadruple 5) ; => 20
371
373
  SKEEM
372
- result = subject.run(source)
374
+ result = interpreter.run(source)
373
375
  expect(result.last.value).to eq(20)
374
376
  end
375
377
  end # context
376
378
 
377
379
  context 'Binding constructs:' do
378
- it 'should implement local bindings' do
380
+ it 'implements local bindings' do
379
381
  source = <<-SKEEM
380
382
  (let ((x 2)
381
383
  (y 3))
382
384
  (* x y))
383
385
  SKEEM
384
- result = subject.run(source)
386
+ result = interpreter.run(source)
385
387
  expect(result).to eq(6)
386
388
  end
387
389
 
388
- it 'should implement precedence of local bindings' do
390
+ it 'implements precedence of local bindings' do
389
391
  source = <<-SKEEM
390
392
  (define x 23)
391
393
  (define y 42)
@@ -394,11 +396,11 @@ SKEEM
394
396
  (let ((y 43))
395
397
  (+ x y))
396
398
  SKEEM
397
- result = subject.run(source)
399
+ result = interpreter.run(source)
398
400
  expect(result.last).to eq(66)
399
401
  end
400
402
 
401
- it 'should support the nesting of local bindings' do
403
+ it 'supports the nesting of local bindings' do
402
404
  source = <<-SKEEM
403
405
  (let ((x 2) (y 3))
404
406
  (let ((x 7)
@@ -408,7 +410,7 @@ SKEEM
408
410
  expect_expr(source).to eq(35)
409
411
  end
410
412
 
411
- it 'should support the nesting of a lambda in a let expression' do
413
+ it 'supports the nesting of a lambda in a let expression' do
412
414
  source = <<-SKEEM
413
415
  (define make-counter
414
416
  (lambda ()
@@ -425,11 +427,11 @@ SKEEM
425
427
  (c2)
426
428
  (c1)
427
429
  SKEEM
428
- result = subject.run(source)
430
+ result = interpreter.run(source)
429
431
  expect(result.last).to eq(3)
430
432
  end
431
433
 
432
- it 'should implement let* expression' do
434
+ it 'implements let* expression' do
433
435
  source = <<-SKEEM
434
436
  (let ((x 2) (y 3))
435
437
  (let* ((x 7)
@@ -441,28 +443,28 @@ SKEEM
441
443
  end # context
442
444
 
443
445
  context 'Sequencing constructs:' do
444
- it 'should implement begin as a sequence of expressions' do
446
+ it 'implements begin as a sequence of expressions' do
445
447
  source = <<-SKEEM
446
448
  (define x 0)
447
449
  (and (= x 0)
448
450
  (begin (set! x 5)
449
451
  (+ x 1))) ; => 6
450
452
  SKEEM
451
- result = subject.run(source)
453
+ result = interpreter.run(source)
452
454
  expect(result.last).to eq(6)
453
455
  end
454
456
 
455
- it 'should implement begin as a sequence of expressions' do
457
+ it 'implements begin as a sequence of expressions' do
456
458
  source = <<-SKEEM
457
459
  (let ()
458
460
  (begin (define x 3) (define y 4))
459
461
  (+ x y)) ; => 7
460
462
  SKEEM
461
- result = subject.run(source)
463
+ result = interpreter.run(source)
462
464
  expect(result).to eq(7)
463
465
  end
464
466
 
465
- it 'should support begin as lambda body' do
467
+ it 'supports begin as lambda body' do
466
468
  source = <<-SKEEM
467
469
  (define kube (lambda (x)
468
470
  (begin
@@ -473,13 +475,13 @@ SKEEM
473
475
  (kube 3)
474
476
  (kube 4)
475
477
  SKEEM
476
- result = subject.run(source)
478
+ result = interpreter.run(source)
477
479
  expect(result.last).to eq(64)
478
480
  end
479
481
  end # context
480
482
 
481
483
  context 'Quasiquotation:' do
482
- it 'should implement the quasiquotation of constant literals' do
484
+ it 'implements the quasiquotation of constant literals' do
483
485
  checks = [
484
486
  ['(quasiquote a)', 'a'],
485
487
  ['(quasiquote 145932)', 145932],
@@ -493,44 +495,44 @@ SKEEM
493
495
  compare_to_predicted(checks)
494
496
  end
495
497
 
496
- it 'should implement the quasiquotation of vectors' do
498
+ it 'implements the quasiquotation of vectors' do
497
499
  source = '(quasiquote #(a b c))'
498
- result = subject.run(source)
499
- expect(result).to be_kind_of(SkmVector)
500
+ result = interpreter.run(source)
501
+ expect(result).to be_a(SkmVector)
500
502
  predictions = [
501
503
  [SkmIdentifier, 'a'],
502
504
  [SkmIdentifier, 'b'],
503
505
  [SkmIdentifier, 'c']
504
506
  ]
505
507
  predictions.each_with_index do |(type, value), index|
506
- expect(result.members[index]).to be_kind_of(type)
508
+ expect(result.members[index]).to be_a(type)
507
509
  expect(result.members[index]).to eq(value)
508
510
  end
509
511
  end
510
512
 
511
- it 'should implement the unquote of vectors' do
513
+ it 'implements the unquote of vectors' do
512
514
  source = '`#( ,(+ 1 2) 4)'
513
- result = subject.run(source)
514
- expect(result).to be_kind_of(SkmVector)
515
+ result = interpreter.run(source)
516
+ expect(result).to be_a(SkmVector)
515
517
  predictions = [
516
518
  [SkmInteger, 3],
517
519
  [SkmInteger, 4]
518
520
  ]
519
521
  predictions.each_with_index do |(type, value), index|
520
- expect(result.members[index]).to be_kind_of(type)
522
+ expect(result.members[index]).to be_a(type)
521
523
  expect(result.members[index]).to eq(value)
522
524
  end
523
525
 
524
526
  source = '`#()'
525
- result = subject.run(source)
526
- expect(result).to be_kind_of(SkmVector)
527
+ result = interpreter.run(source)
528
+ expect(result).to be_a(SkmVector)
527
529
  expect(result).to be_empty
528
530
 
529
531
  # Nested vectors
530
532
  source = '`#(a b #(,(+ 2 3) c) d)'
531
- result = subject.run(source)
533
+ result = interpreter.run(source)
532
534
  # expected: #(a b #(5 c) d)
533
- expect(result).to be_kind_of(SkmVector)
535
+ expect(result).to be_a(SkmVector)
534
536
  predictions = [
535
537
  [SkmIdentifier, 'a'],
536
538
  [SkmIdentifier, 'b'],
@@ -538,57 +540,57 @@ SKEEM
538
540
  [SkmIdentifier, 'd']
539
541
  ]
540
542
  predictions.each_with_index do |(type, value), index|
541
- expect(result.members[index]).to be_kind_of(type)
543
+ expect(result.members[index]).to be_a(type)
542
544
  expect(result.members[index]).to eq(value)
543
545
  end
544
546
  end
545
547
 
546
- it 'should implement the quasiquotation of lists' do
548
+ it 'implements the quasiquotation of lists' do
547
549
  source = '(quasiquote (+ 1 2))'
548
- result = subject.run(source)
549
- expect(result).to be_kind_of(SkmPair)
550
+ result = interpreter.run(source)
551
+ expect(result).to be_a(SkmPair)
550
552
  predictions = [
551
553
  [SkmIdentifier, '+'],
552
554
  [SkmInteger, 1],
553
555
  [SkmInteger, 2]
554
556
  ]
555
557
  predictions.each do |(type, value)|
556
- expect(result.car).to be_kind_of(type)
558
+ expect(result.car).to be_a(type)
557
559
  expect(result.car).to eq(value)
558
560
  result = result.cdr
559
561
  end
560
562
 
561
563
  source = '`()'
562
- result = subject.run(source)
563
- expect(result).to be_kind_of(SkmEmptyList)
564
+ result = interpreter.run(source)
565
+ expect(result).to be_a(SkmEmptyList)
564
566
  expect(result).to be_null
565
567
  end
566
568
 
567
- it 'should implement the unquote of lists' do
569
+ it 'implements the unquote of lists' do
568
570
  source = '`(list ,(+ 1 2) 4)'
569
- result = subject.run(source)
570
- expect(result).to be_kind_of(SkmPair)
571
+ result = interpreter.run(source)
572
+ expect(result).to be_a(SkmPair)
571
573
  predictions = [
572
574
  [SkmIdentifier, 'list'],
573
575
  [SkmInteger, 3],
574
576
  [SkmInteger, 4]
575
577
  ]
576
578
  predictions.each do |(type, value)|
577
- expect(result.car).to be_kind_of(type)
579
+ expect(result.car).to be_a(type)
578
580
  expect(result.car).to eq(value)
579
581
  result = result.cdr
580
582
  end
581
583
 
582
584
  source = '`()'
583
- result = subject.run(source)
584
- expect(result).to be_kind_of(SkmEmptyList)
585
+ result = interpreter.run(source)
586
+ expect(result).to be_a(SkmEmptyList)
585
587
  expect(result).to be_null
586
588
 
587
589
  # nested lists
588
590
  source = '`(a b (,(+ 2 3) c) d)'
589
- result = subject.run(source)
591
+ result = interpreter.run(source)
590
592
  # expected: (a b (5 c) d)
591
- expect(result).to be_kind_of(SkmPair)
593
+ expect(result).to be_a(SkmPair)
592
594
  predictions = [
593
595
  [SkmIdentifier, 'a'],
594
596
  [SkmIdentifier, 'b'],
@@ -596,7 +598,7 @@ SKEEM
596
598
  [SkmIdentifier, 'd']
597
599
  ]
598
600
  predictions.each do |(type, value)|
599
- expect(result.car).to be_kind_of(type)
601
+ expect(result.car).to be_a(type)
600
602
  expect(result.car).to eq(value)
601
603
  result = result.cdr
602
604
  end
@@ -619,21 +621,21 @@ SKEEM
619
621
  end # context
620
622
 
621
623
  context 'Built-in primitive procedures' do
622
- it 'should implement the division of numbers' do
623
- result = subject.run('(/ 24 3)')
624
- expect(result).to be_kind_of(SkmInteger)
624
+ it 'implements the division of numbers' do
625
+ result = interpreter.run('(/ 24 3)')
626
+ expect(result).to be_a(SkmInteger)
625
627
  expect(result).to eq(8)
626
628
  end
627
629
 
628
- it 'should handle arithmetic expressions' do
629
- result = subject.run('(+ (* 2 100) (* 1 10))')
630
- expect(result).to be_kind_of(SkmInteger)
630
+ it 'handles arithmetic expressions' do
631
+ result = interpreter.run('(+ (* 2 100) (* 1 10))')
632
+ expect(result).to be_a(SkmInteger)
631
633
  expect(result).to eq(210)
632
634
  end
633
635
  end # context
634
636
 
635
637
  context 'Built-in standard procedures' do
636
- it 'should implement the zero? predicate' do
638
+ it 'implements the zero? predicate' do
637
639
  checks = [
638
640
  ['(zero? 3.1)', false],
639
641
  ['(zero? -3.1)', false],
@@ -645,7 +647,7 @@ SKEEM
645
647
  compare_to_predicted(checks)
646
648
  end
647
649
 
648
- it 'should implement the positive? predicate' do
650
+ it 'implements the positive? predicate' do
649
651
  checks = [
650
652
  ['(positive? 3.1)', true],
651
653
  ['(positive? -3.1)', false],
@@ -657,7 +659,7 @@ SKEEM
657
659
  compare_to_predicted(checks)
658
660
  end
659
661
 
660
- it 'should implement the negative? predicate' do
662
+ it 'implements the negative? predicate' do
661
663
  checks = [
662
664
  ['(negative? 3.1)', false],
663
665
  ['(negative? -3.1)', true],
@@ -669,7 +671,7 @@ SKEEM
669
671
  compare_to_predicted(checks)
670
672
  end
671
673
 
672
- it 'should implement the even? predicate' do
674
+ it 'implements the even? predicate' do
673
675
  checks = [
674
676
  ['(even? 0)', true],
675
677
  ['(even? 1)', false],
@@ -679,7 +681,7 @@ SKEEM
679
681
  compare_to_predicted(checks)
680
682
  end
681
683
 
682
- it 'should implement the odd? predicate' do
684
+ it 'implements the odd? predicate' do
683
685
  checks = [
684
686
  ['(odd? 0)', false],
685
687
  ['(odd? 1)', true],
@@ -689,7 +691,7 @@ SKEEM
689
691
  compare_to_predicted(checks)
690
692
  end
691
693
 
692
- it 'should implement the abs function' do
694
+ it 'implements the abs function' do
693
695
  checks = [
694
696
  ['(abs 3.1)', 3.1],
695
697
  ['(abs -3.1)', 3.1],
@@ -701,7 +703,7 @@ SKEEM
701
703
  compare_to_predicted(checks)
702
704
  end
703
705
 
704
- it 'should implement the square function' do
706
+ it 'implements the square function' do
705
707
  checks = [
706
708
  ['(square 42)', 1764],
707
709
  ['(square 2.0)', 4.0],
@@ -710,7 +712,7 @@ SKEEM
710
712
  compare_to_predicted(checks)
711
713
  end
712
714
 
713
- it 'should implement the not procedure' do
715
+ it 'implements the not procedure' do
714
716
  checks = [
715
717
  ['(not #t)', false],
716
718
  ['(not 3)', false],
@@ -723,7 +725,7 @@ SKEEM
723
725
  compare_to_predicted(checks)
724
726
  end
725
727
 
726
- it 'should implement the list procedure' do
728
+ it 'implements the list procedure' do
727
729
  checks = [
728
730
  ['(list)', []],
729
731
  ['(list 1)', [1]],
@@ -735,7 +737,7 @@ SKEEM
735
737
  end
736
738
  end
737
739
 
738
- it 'should implement the caar procedure' do
740
+ it 'implements the caar procedure' do
739
741
  checks = [
740
742
  ["(caar '((a)))", 'a'],
741
743
  ["(caar '((1 2) 3 4))", 1]
@@ -743,7 +745,7 @@ SKEEM
743
745
  compare_to_predicted(checks)
744
746
  end
745
747
 
746
- it 'should implement the cadr procedure' do
748
+ it 'implements the cadr procedure' do
747
749
  checks = [
748
750
  ["(cadr '(a b c))", 'b'],
749
751
  ["(cadr '((1 2) 3 4))", 3]
@@ -751,7 +753,7 @@ SKEEM
751
753
  compare_to_predicted(checks)
752
754
  end
753
755
 
754
- it 'should implement the cdar procedure' do
756
+ it 'implements the cdar procedure' do
755
757
  checks = [
756
758
  ["(cdar '((7 6 5 4 3 2 1) 8 9))", [6, 5, 4, 3, 2, 1]]
757
759
  ]
@@ -760,7 +762,7 @@ SKEEM
760
762
  end
761
763
  end
762
764
 
763
- it 'should implement the cddr procedure' do
765
+ it 'implements the cddr procedure' do
764
766
  checks = [
765
767
  ["(cddr '(2 1))", []]
766
768
  ]
@@ -769,7 +771,7 @@ SKEEM
769
771
  end
770
772
  end
771
773
 
772
- it 'should implement the symbol=? procedure' do
774
+ it 'implements the symbol=? procedure' do
773
775
  checks = [
774
776
  ["(symbol=? 'a 'a)", true],
775
777
  ["(symbol=? 'a (string->symbol \"a\"))", true],
@@ -778,7 +780,7 @@ SKEEM
778
780
  compare_to_predicted(checks)
779
781
  end
780
782
 
781
- it 'should implement the floor-quotient procedure' do
783
+ it 'implements the floor-quotient procedure' do
782
784
  checks = [
783
785
  ['(floor-quotient 5 2)', 2],
784
786
  ['(floor-quotient -5 2)', -3],
@@ -788,7 +790,7 @@ SKEEM
788
790
  compare_to_predicted(checks)
789
791
  end
790
792
 
791
- it 'should implement the floor-remainder (modulo) procedure' do
793
+ it 'implements the floor-remainder (modulo) procedure' do
792
794
  checks = [
793
795
  ['(floor-remainder 16 4)', 0],
794
796
  ['(floor-remainder 5 2)', 1],
@@ -804,7 +806,7 @@ SKEEM
804
806
  compare_to_predicted(checks)
805
807
  end
806
808
 
807
- it 'should implement the truncate-quotient procedure' do
809
+ it 'implements the truncate-quotient procedure' do
808
810
  checks = [
809
811
  ['(truncate-quotient 5 2)', 2],
810
812
  ['(truncate-quotient -5 2)', -2],
@@ -818,7 +820,7 @@ SKEEM
818
820
  compare_to_predicted(checks)
819
821
  end
820
822
 
821
- it 'should implement the truncate-remainder procedure' do
823
+ it 'implements the truncate-remainder procedure' do
822
824
  checks = [
823
825
  ['(truncate-remainder 5 2)', 1],
824
826
  ['(truncate-remainder -5 2)', -1],
@@ -832,7 +834,7 @@ SKEEM
832
834
  compare_to_predicted(checks)
833
835
  end
834
836
 
835
- it 'should implement the test-equal procedure' do
837
+ it 'implements the test-equal procedure' do
836
838
  checks = [
837
839
  ['(test-equal (cons 1 2) (cons 1 2))', true]
838
840
  ]
@@ -841,27 +843,27 @@ SKEEM
841
843
  end # context
842
844
 
843
845
  context 'Input/output:' do
844
- it 'should implement the include expression' do
846
+ it 'implements the include expression' do
845
847
  initial_dir = Dir.pwd
846
848
  filedir = File.dirname(__FILE__)
847
849
  Dir.chdir(filedir)
848
850
  source = '(include "add4.skm")' # Path is assumed to be relative to pwd
849
- result = subject.run(source)
851
+ result = interpreter.run(source)
850
852
  expect(result.last).to eq(10)
851
853
  Dir.chdir(initial_dir)
852
854
  end
853
855
 
854
- it 'should implement the newline procedure' do
856
+ it 'implements the newline procedure' do
855
857
  default_stdout = $stdout
856
858
  $stdout = StringIO.new
857
- subject.run('(newline) (newline) (newline)')
859
+ interpreter.run('(newline) (newline) (newline)')
858
860
  expect($stdout.string).to match(/\n\n\n$/)
859
861
  $stdout = default_stdout
860
862
  end
861
863
  end # context
862
864
 
863
865
  context 'Second-order functions' do
864
- it 'should implement lambda that calls second-order function' do
866
+ it 'implements lambda that calls second-order function' do
865
867
  source = <<-SKEEM
866
868
  (define twice
867
869
  (lambda (x)
@@ -875,11 +877,11 @@ SKEEM
875
877
  (compose f f)))
876
878
  ((repeat twice) 5)
877
879
  SKEEM
878
- result = subject.run(source)
880
+ result = interpreter.run(source)
879
881
  expect(result.last).to eq(20)
880
882
  end
881
883
 
882
- it 'should implement the composition of second-order functions' do
884
+ it 'implements the composition of second-order functions' do
883
885
  source = <<-SKEEM
884
886
  (define twice
885
887
  (lambda (x)
@@ -893,20 +895,20 @@ SKEEM
893
895
  (compose f f)))
894
896
  ((repeat (repeat twice)) 5)
895
897
  SKEEM
896
- result = subject.run(source)
898
+ result = interpreter.run(source)
897
899
  expect(result.last).to eq(80)
898
900
  end
899
901
  end # context
900
902
 
901
903
  context 'Derived expressions' do
902
- it 'should implement the do form' do
904
+ it 'implements the do form' do
903
905
  source = <<-SKEEM
904
906
  (do ((vec (make-vector 5))
905
907
  (i 0 (+ i 1)))
906
908
  ((= i 5) vec)
907
909
  (vector-set! vec i i)) ; => #(0 1 2 3 4)
908
910
  SKEEM
909
- result = subject.run(source)
911
+ result = interpreter.run(source)
910
912
  expect(result).to eq([0, 1, 2, 3, 4])
911
913
 
912
914
  source = <<-SKEEM
@@ -916,26 +918,26 @@ SKEEM
916
918
  (sum 0 (+ sum (car x))))
917
919
  ((null? x) sum))) ; => 25
918
920
  SKEEM
919
- result = subject.run(source)
921
+ result = interpreter.run(source)
920
922
  expect(result).to eq(25)
921
923
  end
922
924
  end # context
923
925
 
924
- context 'Macro processing:' do
925
- # it 'should parse macro expressions' do
926
- # source = <<-SKEEM
927
- # (define-syntax while
928
- # (syntax-rules ()
929
- # ((while condition body ...)
930
- # (let loop ()
931
- # (if condition
932
- # (begin
933
- # body ...
934
- # (loop))
935
- # #f)))))
936
- # SKEEM
937
- # ptree = subject.parse(source)
938
- # end
939
- end
926
+ # context 'Macro processing:' do
927
+ # # it 'parses macro expressions' do
928
+ # # source = <<-SKEEM
929
+ # # (define-syntax while
930
+ # # (syntax-rules ()
931
+ # # ((while condition body ...)
932
+ # # (let loop ()
933
+ # # (if condition
934
+ # # (begin
935
+ # # body ...
936
+ # # (loop))
937
+ # # #f)))))
938
+ # # SKEEM
939
+ # # ptree = interpreter.parse(source)
940
+ # # end
941
+ # end
940
942
  end # describe
941
943
  end # module