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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +1 -1
- data/lib/skeem/interpreter.rb +3 -3
- data/lib/skeem/primitive/primitive_builder.rb +95 -0
- data/lib/skeem/standard/base.skm +32 -25
- data/lib/skeem/version.rb +1 -1
- data/spec/skeem/interpreter_spec.rb +92 -158
- data/spec/skeem/primitive/primitive_builder_spec.rb +134 -184
- data/spec/spec_helper.rb +24 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c08f4d71464aad98f53e99e6f66cd18e5961dbd1930353a560844b05d824e288
|
4
|
+
data.tar.gz: f38223cedadc6689670c1d4db901a25cf18caf5b2761519e866909575228b5d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6618523bb5c1a4145b625ed5d264c1879f6980677df9c18e208f9a623652329cf952b4620a8c0c15c96cc38157e75f0590e9555535fa76b63a4361c866393bfb
|
7
|
+
data.tar.gz: 2b0ce438844db721e855dc9a805a66dcacac97240895d3be96e09e9634b8d80056e7dd4cdcb9e36c98896bb536f36ef0801ae830173a8b7ff0d1f032cfd3f18f
|
data/CHANGELOG.md
CHANGED
@@ -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
|
data/lib/skeem/interpreter.rb
CHANGED
@@ -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)
|
data/lib/skeem/standard/base.skm
CHANGED
@@ -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))))
|
data/lib/skeem/version.rb
CHANGED
@@ -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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
samples
|
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
|
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
|
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
|
-
|
87
|
-
|
88
|
-
samples
|
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
|
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
|
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
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
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
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
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
|
-
|
217
|
-
|
218
|
-
|
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
|
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
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
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
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
900
|
-
|
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
|