skeem 0.2.10 → 0.2.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|