skeem 0.2.10 → 0.2.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 482a0c8f936db1cc3099e133dda1d42d685d5e3c7fe244bf98f0062ad1470bc1
4
- data.tar.gz: e950b89cf3a4bc7971a5263e96f7a8dbb670d926b03601d2c4116ccc03b613ec
3
+ metadata.gz: c08f4d71464aad98f53e99e6f66cd18e5961dbd1930353a560844b05d824e288
4
+ data.tar.gz: f38223cedadc6689670c1d4db901a25cf18caf5b2761519e866909575228b5d9
5
5
  SHA512:
6
- metadata.gz: a8a6cde2cd049ccdf7ac4256b2313a462990f355790e6a23ab78febaa9f2377a39914f169c213e5ec1b2342e6bc611eeddae6f8f806ac3ecff713a356765403c
7
- data.tar.gz: 6b9ea76b548deb643631515a755c431a30c915ad1db1dee609ceec1c03e17380d99f0fe33d1ab80a4eda4eec9de3a4acc55e03d6f8d4ebac800f650ad9695554
6
+ metadata.gz: 6618523bb5c1a4145b625ed5d264c1879f6980677df9c18e208f9a623652329cf952b4620a8c0c15c96cc38157e75f0590e9555535fa76b63a4361c866393bfb
7
+ data.tar.gz: 2b0ce438844db721e855dc9a805a66dcacac97240895d3be96e09e9634b8d80056e7dd4cdcb9e36c98896bb536f36ef0801ae830173a8b7ff0d1f032cfd3f18f
@@ -1,3 +1,14 @@
1
+ ## [0.2.11] - 2019-06-16
2
+ - Added procedures: `gcd`, `lcm`, `numerator`, `denominator`, `floor`, `ceiling`, `truncate`,
3
+ `round`.
4
+
5
+ ### Changed
6
+ - File `interpreter_spec.rb`: Refactoring by DRYing code
7
+ - File `primitive_builder_spec.rb`: Refactoring by DRYing code
8
+ - File `base.skm` added implementation of `truncate`
9
+ - File `primitive_builder.rb` Implemented primitive procedures `gcd`, `lcm`, `numerator`, `denominator`, `floor`, `ceiling`, `round`.
10
+ - File `README.md` Added mentions to new procedures.
11
+
1
12
  ## [0.2.10] - 2019-06-15
2
13
  - Skeem now supports rational numbers (fractions)
3
14
  - Added procedures: `max`, `min`, `floor/`, `floor-quotient`, `floor-remainder`, `truncate/`, `truncate-quotient`,
@@ -15,6 +26,7 @@
15
26
  `truncate-remainder`, `quotient`, `remainder`, `modulo`
16
27
  - Class Tokenizer updated to recognize rational numbers.
17
28
  - Test suite file `base_tests.scm` expanded.
29
+ - File `README.md` Added mentions to new procedures.
18
30
 
19
31
  ### Fixed
20
32
  - File `primitive_builder.rb` Fixed and extended implementation of `/`procedure
data/README.md CHANGED
@@ -254,7 +254,7 @@ This section lists the implemented standard procedures
254
254
  * Number-level: `number?`, `complex?`, `real?`, `rational?`, `integer?`, `zero?`, `exact?`, `inexact?`, `exact-integer?` , `+`, `-`, `*`, `/`,
255
255
  `=`, `square`, `number->string`
256
256
  * Real-level: `positive?`, `negative?`, `<`, `>`, `<=`, `>=`, `abs`, `max`, `min`, `floor/`, `floor-quotient`, `floor-remainder`, `truncate/`, `truncate-quotient`,
257
- `truncate-remainder`, `quotient`, `remainder`, `modulo`
257
+ `truncate-remainder`, `quotient`, `remainder`, `modulo`, `gcd`, `lcm`, `numerator`, `denominator`, `floor`, `ceiling`, `truncate`, `round`
258
258
  * Integer-level: `even?`, `odd?`
259
259
 
260
260
  #### List procedures
@@ -29,12 +29,12 @@ module Skeem
29
29
  @parser ||= Parser.new
30
30
  @ptree = parser.parse(source)
31
31
  # $stderr.puts @ptree.root.inspect if mode.nil?
32
- # require 'debug' unless mode.nil?
32
+ # require 'debug' unless mode.nil?
33
33
  end
34
-
34
+
35
35
  def run(source, mode = nil)
36
36
  parse(source, mode)
37
- # require 'debug' unless mode.nil?
37
+ # require 'debug' unless mode.nil?
38
38
  @ptree.root.evaluate(runtime)
39
39
  end
40
40
 
@@ -53,6 +53,13 @@ module Skeem
53
53
  create_divide(aRuntime)
54
54
  create_floor_slash(aRuntime)
55
55
  create_truncate_slash(aRuntime)
56
+ create_gcd(aRuntime)
57
+ create_lcm(aRuntime)
58
+ create_numerator(aRuntime)
59
+ create_denominator(aRuntime)
60
+ create_floor(aRuntime)
61
+ create_ceiling(aRuntime)
62
+ create_round(aRuntime)
56
63
  end
57
64
 
58
65
  def add_comparison(aRuntime)
@@ -252,6 +259,94 @@ module Skeem
252
259
  define_primitive_proc(aRuntime, 'truncate/', binary, primitive)
253
260
  end
254
261
 
262
+ def create_gcd(aRuntime)
263
+ primitive = ->(_runtime, arglist) do
264
+ if arglist.empty?
265
+ integer(0)
266
+ else
267
+ first_one = arglist.shift
268
+ divisor = first_one.value
269
+
270
+ arglist.each do |elem|
271
+ divisor = divisor.gcd(elem.value)
272
+ break if divisor == 1
273
+ end
274
+
275
+ to_datum(divisor)
276
+ end
277
+ end
278
+ define_primitive_proc(aRuntime, 'gcd', zero_or_more, primitive)
279
+ end
280
+
281
+ def create_lcm(aRuntime)
282
+ primitive = ->(_runtime, arglist) do
283
+ if arglist.empty?
284
+ integer(1)
285
+ else
286
+ values = arglist.map(&:value)
287
+ multiple = values.reduce(1, :lcm)
288
+
289
+ to_datum(multiple)
290
+ end
291
+ end
292
+ define_primitive_proc(aRuntime, 'lcm', zero_or_more, primitive)
293
+ end
294
+
295
+ def create_numerator(aRuntime)
296
+ primitive = ->(_runtime, arg_evaluated) do
297
+ case arg_evaluated
298
+ when SkmInteger
299
+ result = arg_evaluated
300
+ when SkmRational, SkmReal
301
+ result = integer(arg_evaluated.value.numerator)
302
+ end
303
+ result
304
+ end
305
+
306
+ define_primitive_proc(aRuntime, 'numerator', unary, primitive)
307
+ end
308
+
309
+ def create_denominator(aRuntime)
310
+ primitive = ->(_runtime, arg_evaluated) do
311
+ case arg_evaluated
312
+ when SkmInteger
313
+ result = 1
314
+ when SkmRational, SkmReal
315
+ result = arg_evaluated.value.denominator
316
+ end
317
+ integer(result)
318
+ end
319
+
320
+ define_primitive_proc(aRuntime, 'denominator', unary, primitive)
321
+ end
322
+
323
+ def create_floor(aRuntime)
324
+ primitive = ->(_runtime, arg_evaluated) do
325
+ result = arg_evaluated.value.floor
326
+ integer(result)
327
+ end
328
+
329
+ define_primitive_proc(aRuntime, 'floor', unary, primitive)
330
+ end
331
+
332
+ def create_ceiling(aRuntime)
333
+ primitive = ->(_runtime, arg_evaluated) do
334
+ result = arg_evaluated.value.ceil
335
+ integer(result)
336
+ end
337
+
338
+ define_primitive_proc(aRuntime, 'ceiling', unary, primitive)
339
+ end
340
+
341
+ def create_round(aRuntime)
342
+ primitive = ->(_runtime, arg_evaluated) do
343
+ result = arg_evaluated.value.round
344
+ integer(result)
345
+ end
346
+
347
+ define_primitive_proc(aRuntime, 'round', unary, primitive)
348
+ end
349
+
255
350
  def core_eqv?(eval_arg1, eval_arg2)
256
351
  raw_result = eval_arg1.eqv?(eval_arg2)
257
352
  boolean(raw_result)
@@ -3,9 +3,9 @@
3
3
  ;; (exact-integer? z)
4
4
  (define exact-integer?
5
5
  (lambda (z)
6
- (and
6
+ (and
7
7
  (exact? z)
8
- (integer? z))))
8
+ (integer? z))))
9
9
 
10
10
  ;; (zero? z)
11
11
  ;; Returns true iff z is zero
@@ -15,7 +15,7 @@
15
15
  #t
16
16
  #f)))
17
17
 
18
- ; (positive? x)
18
+ ; (positive? x)
19
19
  ; Return true if x greater than zero; false otherwise
20
20
  (define positive?
21
21
  (lambda (x)
@@ -24,7 +24,7 @@
24
24
  #f)))
25
25
 
26
26
  ; (negative? x)
27
- ; Returns true iff x < 0
27
+ ; Returns true iff x < 0
28
28
  (define negative?
29
29
  (lambda (x)
30
30
  (if (< x 0)
@@ -32,11 +32,11 @@
32
32
  #f)))
33
33
 
34
34
  ; (inexact? z)
35
- ; Returns true iff z is not an exact number
35
+ ; Returns true iff z is not an exact number
36
36
  (define inexact?
37
- (lambda (z)
37
+ (lambda (z)
38
38
  (not (exact? z))))
39
-
39
+
40
40
  (define floor-quotient
41
41
  (lambda (n1 n2)
42
42
  (car (floor/ n1 n2))))
@@ -44,7 +44,7 @@
44
44
  (define floor-remainder
45
45
  (lambda (n1 n2)
46
46
  (cdr (floor/ n1 n2))))
47
-
47
+
48
48
  (define truncate-quotient
49
49
  (lambda (n1 n2)
50
50
  (car (truncate/ n1 n2))))
@@ -57,17 +57,24 @@
57
57
  (define quotient
58
58
  (lambda (x y)
59
59
  (truncate-quotient x y)))
60
-
60
+
61
61
  ; For R5RS compatibility
62
62
  (define remainder
63
63
  (lambda (x y)
64
64
  (truncate-remainder x y)))
65
-
65
+
66
66
  ; For R5RS compatibility
67
67
  (define modulo
68
68
  (lambda (x y)
69
69
  (floor-remainder x y)))
70
70
 
71
+ (define truncate
72
+ (lambda (x)
73
+ (if (positive? x)
74
+ (floor x)
75
+ (ceiling x)
76
+ )))
77
+
71
78
  ; (odd? n)
72
79
  ; Returns true iff n is odd
73
80
  (define odd?
@@ -102,47 +109,47 @@
102
109
  (if obj #f #t))
103
110
 
104
111
  ; (list arg ...)
105
- ; Allocates and returns a new list from its arguments
112
+ ; Allocates and returns a new list from its arguments
106
113
  (define list
107
114
  (lambda args args))
108
-
109
- (define caar
115
+
116
+ (define caar
110
117
  (lambda (x)
111
118
  (car (car x))))
112
119
 
113
- (define cadr
114
- (lambda (x)
120
+ (define cadr
121
+ (lambda (x)
115
122
  (car (cdr x))))
116
123
 
117
- (define cdar
124
+ (define cdar
118
125
  (lambda(x)
119
126
  (cdr (car x))))
120
127
 
121
- (define cddr
122
- (lambda (x)
128
+ (define cddr
129
+ (lambda (x)
123
130
  (cdr (cdr x))))
124
131
 
125
- ;; (list-ref list n)
132
+ ;; (list-ref list n)
126
133
  ;; Return the nth (sero-based) element of list
127
134
  ;; n must be a nonnegative integer
128
135
  ;(define list-ref
129
136
  ; (lambda (ls n)
130
137
  ; (if (= n 0)
131
138
  ; (car ls)
132
- ; (list-ref (cdr ls) (- n 1)))))
133
-
139
+ ; (list-ref (cdr ls) (- n 1)))))
140
+
134
141
  (define symbol=? string=?)
135
142
 
136
143
  ;; Test the equivalence (with eqv? predicate) between an expected value and
137
144
  ;; an expression
138
145
  ;; (test-eqv expected test-expr)
139
- (define test-eqv
140
- (lambda (x y)
146
+ (define test-eqv
147
+ (lambda (x y)
141
148
  (test-assert (eqv? x y))))
142
149
 
143
150
  ;; Test the equality (with equal? predicate) between an expected value and
144
151
  ;; an expression
145
152
  ;; (test-equal expected test-expr)
146
- (define test-equal
147
- (lambda (x y)
153
+ (define test-equal
154
+ (lambda (x y)
148
155
  (test-assert (equal? x y))))
@@ -1,3 +1,3 @@
1
1
  module Skeem
2
- VERSION = '0.2.10'.freeze
2
+ VERSION = '0.2.11'.freeze
3
3
  end
@@ -5,6 +5,7 @@ require_relative '../../lib/skeem/interpreter' # Load the class under test
5
5
 
6
6
  module Skeem
7
7
  describe Interpreter do
8
+ include InterpreterSpec
8
9
  include DatumDSL
9
10
 
10
11
  context 'Initialization:' do
@@ -39,13 +40,12 @@ module Skeem
39
40
  context 'Interpreting self-evaluating expressions' do
40
41
  it 'should evaluate isolated booleans' do
41
42
  samples = [
42
- ['#f', false],
43
- ['#false', false],
44
- ['#t', true],
45
- ['#true', true]
46
- ]
47
- samples.each do |source, predicted|
48
- result = subject.run(source)
43
+ ['#f', false],
44
+ ['#false', false],
45
+ ['#t', true],
46
+ ['#true', true]
47
+ ]
48
+ compare_to_predicted(samples) do |result, predicted|
49
49
  expect(result).to be_kind_of(SkmBoolean)
50
50
  expect(result).to eq(predicted)
51
51
  end
@@ -59,8 +59,7 @@ module Skeem
59
59
  ['+12345', 12345],
60
60
  ['-12345', -12345]
61
61
  ]
62
- samples.each do |source, predicted|
63
- result = subject.run(source)
62
+ compare_to_predicted(samples) do |result, predicted|
64
63
  expect(result).to be_kind_of(SkmInteger)
65
64
  expect(result).to eq(predicted)
66
65
  end
@@ -74,8 +73,7 @@ module Skeem
74
73
  ['+123e+45', 123e+45],
75
74
  ['-123e-45', -123e-45]
76
75
  ]
77
- samples.each do |source, predicted|
78
- result = subject.run(source)
76
+ compare_to_predicted(samples) do |result, predicted|
79
77
  expect(result).to be_kind_of(SkmReal)
80
78
  expect(result).to eq(predicted)
81
79
  end
@@ -83,10 +81,9 @@ module Skeem
83
81
 
84
82
  it 'should evaluate isolated strings' do
85
83
  samples = [
86
- ['"Hello, world"', 'Hello, world']
87
- ]
88
- samples.each do |source, predicted|
89
- result = subject.run(source)
84
+ ['"Hello, world"', 'Hello, world']
85
+ ]
86
+ compare_to_predicted(samples) do |result, predicted|
90
87
  expect(result).to be_kind_of(SkmString)
91
88
  expect(result).to eq(predicted)
92
89
  end
@@ -132,10 +129,7 @@ SKEEM
132
129
  ['(if (> 3 2) "yes")', 'yes'],
133
130
  ['(if (> 2 3) "yes")', SkmUndefined.instance]
134
131
  ]
135
- checks.each do |(skeem_expr, expectation)|
136
- result = subject.run(skeem_expr)
137
- expect(result).to eq(expectation)
138
- end
132
+ compare_to_predicted(checks)
139
133
  end
140
134
 
141
135
  it 'should implement the complete conditional form' do
@@ -143,10 +137,7 @@ SKEEM
143
137
  ['(if (> 3 2) "yes" "no")', 'yes'],
144
138
  ['(if (> 2 3) "yes" "no")', 'no']
145
139
  ]
146
- checks.each do |(skeem_expr, expectation)|
147
- result = subject.run(skeem_expr)
148
- expect(result).to eq(expectation)
149
- end
140
+ compare_to_predicted(checks)
150
141
  source = <<-SKEEM
151
142
  ; Example from R7RS section 4.1.5
152
143
  (if (> 3 2)
@@ -156,7 +147,7 @@ SKEEM
156
147
  result = subject.run(source)
157
148
  expect(result).to eq(1)
158
149
  end
159
-
150
+
160
151
  it 'should implement the cond form' do
161
152
  source = <<-SKEEM
162
153
  (define signum (lambda (x)
@@ -166,17 +157,15 @@ SKEEM
166
157
  ((< x 0) -1)
167
158
  )))
168
159
  SKEEM
169
- result = subject.run(source)
170
- result = subject.run('(signum 3)')
171
- expect(result).to eq(1)
172
-
173
- result = subject.run('(signum 0)')
174
- expect(result).to eq(0)
175
-
176
- result = subject.run('(signum -3)')
177
- expect(result).to eq(-1)
160
+ result = subject.run(source)
161
+ checks = [
162
+ ['(signum 3)', 1],
163
+ ['(signum 0)', 0],
164
+ ['(signum -3)', -1]
165
+ ]
166
+ compare_to_predicted(checks)
178
167
  end
179
-
168
+
180
169
  it 'should implement the cond form with arrows' do
181
170
  source = <<-SKEEM
182
171
  (define signum (lambda (x)
@@ -186,16 +175,14 @@ SKEEM
186
175
  ((< x 0) => -1)
187
176
  )))
188
177
  SKEEM
189
- result = subject.run(source)
190
- result = subject.run('(signum 3)')
191
- expect(result).to eq(1)
192
-
193
- result = subject.run('(signum 0)')
194
- expect(result).to eq(0)
195
-
196
- result = subject.run('(signum -3)')
197
- expect(result).to eq(-1)
198
- end
178
+ result = subject.run(source)
179
+ checks = [
180
+ ['(signum 3)', 1],
181
+ ['(signum 0)', 0],
182
+ ['(signum -3)', -1]
183
+ ]
184
+ compare_to_predicted(checks)
185
+ end
199
186
 
200
187
  it 'should implement the cond ... else form' do
201
188
  source = <<-SKEEM
@@ -206,16 +193,22 @@ SKEEM
206
193
  (else -1)
207
194
  )))
208
195
  SKEEM
209
- result = subject.run(source)
210
- result = subject.run('(signum 3)')
211
- expect(result).to eq(1)
212
-
213
- result = subject.run('(signum 0)')
214
- expect(result).to eq(0)
196
+ result = subject.run(source)
197
+ checks = [
198
+ ['(signum 3)', 1],
199
+ ['(signum 0)', 0],
200
+ ['(signum -3)', -1]
201
+ ]
202
+ compare_to_predicted(checks)
203
+ end
215
204
 
216
- result = subject.run('(signum -3)')
217
- expect(result).to eq(-1)
218
- end
205
+ it 'should implement the truncate procedure' do
206
+ checks = [
207
+ ['(truncate -4.3)', -4],
208
+ ['(truncate 3.5)', 3]
209
+ ]
210
+ compare_to_predicted(checks)
211
+ end
219
212
 
220
213
  it 'should implement the quotation of constant literals' do
221
214
  checks = [
@@ -228,10 +221,7 @@ SKEEM
228
221
  ["'\"abc\"", 'abc'],
229
222
  ["'#t", true]
230
223
  ]
231
- checks.each do |(skeem_expr, expectation)|
232
- result = subject.run(skeem_expr)
233
- expect(result).to eq(expectation)
234
- end
224
+ compare_to_predicted(checks)
235
225
  end
236
226
 
237
227
  it 'should implement the quotation of vectors' do
@@ -280,12 +270,12 @@ SKEEM
280
270
  subject.run(source)
281
271
  procedure = subject.fetch('abs')
282
272
  expect(procedure.arity).to eq(1)
283
- result = subject.run('(abs -3)')
284
- expect(result).to eq(3)
285
- result = subject.run('(abs 0)')
286
- expect(result).to eq(0)
287
- result = subject.run('(abs 3)')
288
- expect(result).to eq(3)
273
+ checks = [
274
+ ['(abs -3)', 3],
275
+ ['(abs 0)', 0],
276
+ ['(abs 3)', 3]
277
+ ]
278
+ compare_to_predicted(checks)
289
279
  end
290
280
 
291
281
  it 'should implement the lambda function with two args' do
@@ -298,12 +288,12 @@ SKEEM
298
288
  subject.run(source)
299
289
  procedure = subject.fetch('min')
300
290
  expect(procedure.arity).to eq(2)
301
- result = subject.run('(min 1 2)')
302
- expect(result).to eq(1)
303
- result = subject.run('(min 2 1)')
304
- expect(result).to eq(1)
305
- result = subject.run('(min 2 2)')
306
- expect(result).to eq(2)
291
+ checks = [
292
+ ['(min 1 2)', 1],
293
+ ['(min 2 1)', 1],
294
+ ['(min 2 2)', 2]
295
+ ]
296
+ compare_to_predicted(checks)
307
297
  end
308
298
 
309
299
  it 'should implement recursive functions' do
@@ -377,8 +367,8 @@ SKEEM
377
367
  result = subject.run(source)
378
368
  expect(result.last.value).to eq(20)
379
369
  end
380
-
381
-
370
+
371
+
382
372
  end # context
383
373
 
384
374
  context 'Binding constructs:' do
@@ -412,8 +402,7 @@ SKEEM
412
402
  (z (+ x y)))
413
403
  (* z x)))
414
404
  SKEEM
415
- result = subject.run(source)
416
- expect(result).to eq(35)
405
+ expect_expr(source).to eq(35)
417
406
  end
418
407
 
419
408
  it 'should support the nesting of a lambda in a let expression' do
@@ -444,8 +433,7 @@ SKEEM
444
433
  (z (+ x y)))
445
434
  (* z x)))
446
435
  SKEEM
447
- result = subject.run(source)
448
- expect(result).to eq(70)
436
+ expect_expr(source).to eq(70)
449
437
  end
450
438
  end # context
451
439
 
@@ -470,7 +458,7 @@ SKEEM
470
458
  result = subject.run(source)
471
459
  expect(result).to eq(7)
472
460
  end
473
-
461
+
474
462
  it 'should support begin as lambda body' do
475
463
  source = <<-SKEEM
476
464
  (define kube (lambda (x)
@@ -484,7 +472,7 @@ SKEEM
484
472
  SKEEM
485
473
  result = subject.run(source)
486
474
  expect(result.last).to eq(64)
487
- end
475
+ end
488
476
  end # context
489
477
 
490
478
  context 'Quasiquotation:' do
@@ -499,10 +487,7 @@ SKEEM
499
487
  ['`"abc"', 'abc'],
500
488
  ['`#t', true]
501
489
  ]
502
- checks.each do |(skeem_expr, expectation)|
503
- result = subject.run(skeem_expr)
504
- expect(result).to eq(expectation)
505
- end
490
+ compare_to_predicted(checks)
506
491
  end
507
492
 
508
493
  it 'should implement the quasiquotation of vectors' do
@@ -654,10 +639,7 @@ SKEEM
654
639
  ['(zero? 3)', false],
655
640
  ['(zero? -3)', false]
656
641
  ]
657
- checks.each do |(skeem_expr, expectation)|
658
- result = subject.run(skeem_expr)
659
- expect(result).to eq(expectation)
660
- end
642
+ compare_to_predicted(checks)
661
643
  end
662
644
 
663
645
  it 'should implement the positive? predicate' do
@@ -669,10 +651,7 @@ SKEEM
669
651
  ['(positive? 3)', true],
670
652
  ['(positive? -3)', false]
671
653
  ]
672
- checks.each do |(skeem_expr, expectation)|
673
- result = subject.run(skeem_expr)
674
- expect(result).to eq(expectation)
675
- end
654
+ compare_to_predicted(checks)
676
655
  end
677
656
 
678
657
  it 'should implement the negative? predicate' do
@@ -684,10 +663,7 @@ SKEEM
684
663
  ['(negative? 3)', false],
685
664
  ['(negative? -3)', true]
686
665
  ]
687
- checks.each do |(skeem_expr, expectation)|
688
- result = subject.run(skeem_expr)
689
- expect(result).to eq(expectation)
690
- end
666
+ compare_to_predicted(checks)
691
667
  end
692
668
 
693
669
  it 'should implement the even? predicate' do
@@ -697,10 +673,7 @@ SKEEM
697
673
  ['(even? 2.0)', true],
698
674
  ['(even? -120762398465)', false]
699
675
  ]
700
- checks.each do |(skeem_expr, expectation)|
701
- result = subject.run(skeem_expr)
702
- expect(result).to eq(expectation)
703
- end
676
+ compare_to_predicted(checks)
704
677
  end
705
678
 
706
679
  it 'should implement the odd? predicate' do
@@ -710,10 +683,7 @@ SKEEM
710
683
  ['(odd? 2.0)', false],
711
684
  ['(odd? -120762398465)', true]
712
685
  ]
713
- checks.each do |(skeem_expr, expectation)|
714
- result = subject.run(skeem_expr)
715
- expect(result).to eq(expectation)
716
- end
686
+ compare_to_predicted(checks)
717
687
  end
718
688
 
719
689
  it 'should implement the abs function' do
@@ -725,10 +695,7 @@ SKEEM
725
695
  ['(abs 3)', 3],
726
696
  ['(abs -7)', 7]
727
697
  ]
728
- checks.each do |(skeem_expr, expectation)|
729
- result = subject.run(skeem_expr)
730
- expect(result).to eq(expectation)
731
- end
698
+ compare_to_predicted(checks)
732
699
  end
733
700
 
734
701
  it 'should implement the square function' do
@@ -737,10 +704,7 @@ SKEEM
737
704
  ['(square 2.0)', 4.0],
738
705
  ['(square -7)', 49]
739
706
  ]
740
- checks.each do |(skeem_expr, expectation)|
741
- result = subject.run(skeem_expr)
742
- expect(result).to eq(expectation)
743
- end
707
+ compare_to_predicted(checks)
744
708
  end
745
709
 
746
710
  it 'should implement the not procedure' do
@@ -753,10 +717,7 @@ SKEEM
753
717
  ['(not (list))', false],
754
718
  ["(not 'nil)", false]
755
719
  ]
756
- checks.each do |(skeem_expr, expectation)|
757
- result = subject.run(skeem_expr)
758
- expect(result).to eq(expectation)
759
- end
720
+ compare_to_predicted(checks)
760
721
  end
761
722
 
762
723
  it 'should implement the list procedure' do
@@ -766,8 +727,7 @@ SKEEM
766
727
  ['(list 1 2 3 4)', [1, 2, 3, 4]],
767
728
  ["(list 'a (+ 3 4) 'c)", [identifier('a'), 7, identifier('c')]]
768
729
  ]
769
- checks.each do |(skeem_expr, expectation)|
770
- result = subject.run(skeem_expr)
730
+ compare_to_predicted(checks) do |result, expectation|
771
731
  expect(result.to_a).to eq(expectation)
772
732
  end
773
733
  end
@@ -777,10 +737,7 @@ SKEEM
777
737
  ["(caar '((a)))", 'a'],
778
738
  ["(caar '((1 2) 3 4))", 1]
779
739
  ]
780
- checks.each do |(skeem_expr, expectation)|
781
- result = subject.run(skeem_expr)
782
- expect(result).to eq(expectation)
783
- end
740
+ compare_to_predicted(checks)
784
741
  end
785
742
 
786
743
  it 'should implement the cadr procedure' do
@@ -788,18 +745,14 @@ SKEEM
788
745
  ["(cadr '(a b c))", 'b'],
789
746
  ["(cadr '((1 2) 3 4))", 3]
790
747
  ]
791
- checks.each do |(skeem_expr, expectation)|
792
- result = subject.run(skeem_expr)
793
- expect(result).to eq(expectation)
794
- end
748
+ compare_to_predicted(checks)
795
749
  end
796
750
 
797
751
  it 'should implement the cdar procedure' do
798
752
  checks = [
799
753
  ["(cdar '((7 6 5 4 3 2 1) 8 9))", [6, 5, 4, 3, 2, 1]]
800
754
  ]
801
- checks.each do |(skeem_expr, expectation)|
802
- result = subject.run(skeem_expr)
755
+ compare_to_predicted(checks) do |result, expectation|
803
756
  expect(result.to_a).to eq(expectation)
804
757
  end
805
758
  end
@@ -808,8 +761,7 @@ SKEEM
808
761
  checks = [
809
762
  ["(cddr '(2 1))", []]
810
763
  ]
811
- checks.each do |(skeem_expr, expectation)|
812
- result = subject.run(skeem_expr)
764
+ compare_to_predicted(checks) do |result, expectation|
813
765
  expect(result.to_a).to eq(expectation)
814
766
  end
815
767
  end
@@ -820,10 +772,7 @@ SKEEM
820
772
  ["(symbol=? 'a (string->symbol \"a\"))", true],
821
773
  ["(symbol=? 'a 'b)", false]
822
774
  ]
823
- checks.each do |(skeem_expr, expectation)|
824
- result = subject.run(skeem_expr)
825
- expect(result).to eq(expectation)
826
- end
775
+ compare_to_predicted(checks)
827
776
  end
828
777
 
829
778
  it 'should implement the floor-quotient procedure' do
@@ -833,12 +782,9 @@ SKEEM
833
782
  ['(floor-quotient 5 -2)', -3],
834
783
  ['(floor-quotient -5 -2)', 2]
835
784
  ]
836
- checks.each do |(skeem_expr, expectation)|
837
- result = subject.run(skeem_expr)
838
- expect(result).to eq(expectation)
839
- end
785
+ compare_to_predicted(checks)
840
786
  end
841
-
787
+
842
788
  it 'should implement the floor-remainder (modulo) procedure' do
843
789
  checks = [
844
790
  ['(floor-remainder 16 4)', 0],
@@ -850,14 +796,11 @@ SKEEM
850
796
  ['(modulo 5 2)', 1],
851
797
  ['(modulo -45.0 7)', 4.0],
852
798
  ['(modulo 10.0 -3.0)', -2.0],
853
- ['(modulo -17 -9)', -8]
799
+ ['(modulo -17 -9)', -8]
854
800
  ]
855
- checks.each do |(skeem_expr, expectation)|
856
- result = subject.run(skeem_expr)
857
- expect(result).to eq(expectation)
858
- end
801
+ compare_to_predicted(checks)
859
802
  end
860
-
803
+
861
804
  it 'should implement the truncate-quotient procedure' do
862
805
  checks = [
863
806
  ['(truncate-quotient 5 2)', 2],
@@ -867,12 +810,9 @@ SKEEM
867
810
  ['(quotient 5 2)', 2],
868
811
  ['(quotient -5 2)', -2],
869
812
  ['(quotient 5 -2)', -2],
870
- ['(quotient -5 -2)', 2]
813
+ ['(quotient -5 -2)', 2]
871
814
  ]
872
- checks.each do |(skeem_expr, expectation)|
873
- result = subject.run(skeem_expr)
874
- expect(result).to eq(expectation)
875
- end
815
+ compare_to_predicted(checks)
876
816
  end
877
817
 
878
818
  it 'should implement the truncate-remainder procedure' do
@@ -884,23 +824,17 @@ SKEEM
884
824
  ['(remainder 5 2)', 1],
885
825
  ['(remainder -5 2)', -1],
886
826
  ['(remainder 5 -2)', 1],
887
- ['(remainder -5 -2)', -1]
827
+ ['(remainder -5 -2)', -1]
888
828
  ]
889
- checks.each do |(skeem_expr, expectation)|
890
- result = subject.run(skeem_expr)
891
- expect(result).to eq(expectation)
892
- end
829
+ compare_to_predicted(checks)
893
830
  end
894
-
831
+
895
832
  it 'should implement the test-equal procedure' do
896
833
  checks = [
897
834
  ["(test-equal (cons 1 2) (cons 1 2))", true]
898
835
  ]
899
- checks.each do |(skeem_expr, expectation)|
900
- result = subject.run(skeem_expr)
901
- expect(result).to eq(expectation)
902
- end
903
- end
836
+ compare_to_predicted(checks)
837
+ end
904
838
  end # context
905
839
 
906
840
  context 'Second-order functions' do