skeem 0.2.08 → 0.2.09
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +6 -1
- data/lib/skeem/primitive/primitive_builder.rb +87 -152
- data/lib/skeem/primitive/primitive_procedure.rb +23 -7
- data/lib/skeem/skm_simple_datum.rb +8 -0
- data/lib/skeem/standard/base.skm +12 -5
- data/lib/skeem/tokenizer.rb +40 -18
- data/lib/skeem/version.rb +1 -1
- data/spec/skeem/interpreter_spec.rb +2 -17
- data/spec/skeem/primitive/primitive_builder_spec.rb +1 -1
- data/spec/skeem/primitive/primitive_procedure_spec.rb +2 -1
- data/spec/skeem/tokenizer_spec.rb +28 -1
- 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: a85fc0a12d54eedba56c28e18d728d00ff35044c029e1a256d4381a98c6310a8
|
4
|
+
data.tar.gz: 934cc810162a891fdddffdbfb16466ed7d7c71da8d7c5cb77670c010b5bf83fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6dcdf9eb8d85abdcd4d2f416b9e9fa6ed1d9b399b92c9921ff59fb8dc6d6f047e5064fd7ccffde3ae000771079a0a7d9f64643e0585ba0c39b0566b345a5b994
|
7
|
+
data.tar.gz: 60347248374f6723c91edc3699b1306056b02bfc7a91a52e9dcfa15690f72294bf89cfd1ef8551218a6e67751bdde59f972c6ec1ea0e42733436d7caa5b26bac
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
## [0.2.09] - 2019-06-10
|
2
|
+
- New procedures: `complex?`, `exact-integer?`
|
3
|
+
- Support for `#| ... |#` block comments (including nesting)
|
4
|
+
|
5
|
+
### Added
|
6
|
+
- File `base.skm`: Added integer number predicate `exact-integer?`
|
7
|
+
- File `primitive_builder.rb`: Added numeric type predicate `complex?`
|
8
|
+
- New method `Tokenizer#skip_block_comment` to handle "| ... |#" comments (including their nesting)
|
9
|
+
- New folder `test_skeem` containing a test suite in `Skeem`
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
- Method 'PrimitiveProcedure#do_call' whenever possible, the arguments are evaluated before executing the primitive.
|
13
|
+
- File `primitive_builder.rb`: Lambda expression refactoring as most argument evaluations became redundant.
|
14
|
+
- Method `Tokenizer#_next_token` numeric literals with only zero(es) in their fractional part are implicitly converted to integers `3.0` => 3
|
15
|
+
- Method `Tokenizer#skip_whitespaces` refactoring & detection of block comments
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
- File `base.skm`: predicate `positive?` returned #t when argument was zero. Now: (positive? 0) returns #f as expected.
|
19
|
+
|
20
|
+
### Removed
|
21
|
+
- Empty method `PrimitiveBuilder#add_binding` removed.
|
22
|
+
|
23
|
+
|
1
24
|
## [0.2.08] - 2019-06-02
|
2
25
|
- New standard procedures implemented: `assq`, `assv`
|
3
26
|
|
data/README.md
CHANGED
@@ -166,6 +166,10 @@ Here are a few pointers for the Scheme programming language:
|
|
166
166
|
|
167
167
|
|
168
168
|
## Currently implemented R7RS features
|
169
|
+
### Comments
|
170
|
+
- Semi-colon delimited comments: `; This comment stops at the end of line`
|
171
|
+
- Block `#| ... |#` comments
|
172
|
+
|
169
173
|
### Data type literals
|
170
174
|
- Booleans: `#t`, `#true`, `#f`, `#false`
|
171
175
|
- Of the number hierarchy:
|
@@ -246,7 +250,8 @@ This section lists the implemented standard procedures
|
|
246
250
|
* `boolean?`, `and`, `or`, `not`
|
247
251
|
|
248
252
|
#### Numerical operations
|
249
|
-
* Number-level: `number?`, `real?`, `integer?`, `zero?`, `+`, `-`, `*`, `/`,
|
253
|
+
* Number-level: `number?`, `complex?`, `real?`, `integer?`, `zero?`, `exact?`, `inexact?`, `exact-integer?` , `+`, `-`, `*`, `/`,
|
254
|
+
`=`, `square`, `number->string`
|
250
255
|
* Real-level: `positive?`, `negative?`, `<`, `>`, `<=`, `>=`, `abs`, `floor-remainder`
|
251
256
|
* Integer-level: `even?`, `odd?`
|
252
257
|
|
@@ -1,14 +1,12 @@
|
|
1
1
|
require_relative 'primitive_procedure'
|
2
2
|
require_relative '../datum_dsl'
|
3
3
|
require_relative '../skm_pair'
|
4
|
-
# require_relative '../s_expr_nodes'
|
5
4
|
|
6
5
|
module Skeem
|
7
6
|
module Primitive
|
8
7
|
module PrimitiveBuilder
|
9
8
|
include DatumDSL
|
10
9
|
def add_primitives(aRuntime)
|
11
|
-
add_binding(aRuntime)
|
12
10
|
add_arithmetic(aRuntime)
|
13
11
|
add_comparison(aRuntime)
|
14
12
|
add_number_procedures(aRuntime)
|
@@ -48,9 +46,6 @@ module Skeem
|
|
48
46
|
SkmArity.new(1, '*')
|
49
47
|
end
|
50
48
|
|
51
|
-
def add_binding(aRuntime)
|
52
|
-
end
|
53
|
-
|
54
49
|
def add_arithmetic(aRuntime)
|
55
50
|
create_plus(aRuntime)
|
56
51
|
create_minus(aRuntime)
|
@@ -72,6 +67,7 @@ module Skeem
|
|
72
67
|
|
73
68
|
def add_number_procedures(aRuntime)
|
74
69
|
create_object_predicate(aRuntime, 'number?')
|
70
|
+
create_object_predicate(aRuntime, 'complex?')
|
75
71
|
create_object_predicate(aRuntime, 'real?')
|
76
72
|
create_object_predicate(aRuntime, 'integer?')
|
77
73
|
create_object_predicate(aRuntime, 'exact?')
|
@@ -141,14 +137,13 @@ module Skeem
|
|
141
137
|
|
142
138
|
def create_plus(aRuntime)
|
143
139
|
# arglist should be a Ruby Array
|
144
|
-
primitive = ->(
|
140
|
+
primitive = ->(_runtime, arglist) do
|
145
141
|
if arglist.empty?
|
146
142
|
integer(0)
|
147
143
|
else
|
148
|
-
first_one = arglist.
|
144
|
+
first_one = arglist.shift
|
149
145
|
raw_result = first_one.value
|
150
|
-
|
151
|
-
operands.each { |elem| raw_result += elem.value }
|
146
|
+
arglist.each { |elem| raw_result += elem.value }
|
152
147
|
to_datum(raw_result)
|
153
148
|
end
|
154
149
|
end
|
@@ -156,14 +151,12 @@ module Skeem
|
|
156
151
|
end
|
157
152
|
|
158
153
|
def create_minus(aRuntime)
|
159
|
-
primitive = ->(
|
160
|
-
|
161
|
-
raw_result = first_one.value
|
154
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
155
|
+
raw_result = first_operand.value
|
162
156
|
if arglist.empty?
|
163
157
|
raw_result = -raw_result
|
164
158
|
else
|
165
|
-
|
166
|
-
operands.each { |elem| raw_result -= elem.value }
|
159
|
+
arglist.each { |elem| raw_result -= elem.value }
|
167
160
|
end
|
168
161
|
to_datum(raw_result)
|
169
162
|
end
|
@@ -172,14 +165,13 @@ module Skeem
|
|
172
165
|
end
|
173
166
|
|
174
167
|
def create_multiply(aRuntime)
|
175
|
-
primitive = ->(
|
168
|
+
primitive = ->(_runtime, arglist) do
|
176
169
|
if arglist.empty?
|
177
170
|
integer(1)
|
178
171
|
else
|
179
|
-
first_one = arglist.
|
172
|
+
first_one = arglist.shift
|
180
173
|
raw_result = first_one.value
|
181
|
-
|
182
|
-
operands.each { |elem| raw_result *= elem.value }
|
174
|
+
arglist.each { |elem| raw_result *= elem.value }
|
183
175
|
to_datum(raw_result)
|
184
176
|
end
|
185
177
|
end
|
@@ -188,14 +180,12 @@ module Skeem
|
|
188
180
|
|
189
181
|
|
190
182
|
def create_divide(aRuntime)
|
191
|
-
primitive = ->(
|
192
|
-
|
193
|
-
raw_result = first_one.value
|
183
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
184
|
+
raw_result = first_operand.value
|
194
185
|
if arglist.empty?
|
195
186
|
raw_result = 1 / raw_result.to_f
|
196
187
|
else
|
197
|
-
|
198
|
-
operands.each do |elem|
|
188
|
+
arglist.each do |elem|
|
199
189
|
if raw_result > elem.value && raw_result.modulo(elem.value).zero?
|
200
190
|
raw_result /= elem.value
|
201
191
|
else
|
@@ -211,9 +201,7 @@ module Skeem
|
|
211
201
|
end
|
212
202
|
|
213
203
|
def create_modulo(aRuntime)
|
214
|
-
primitive = ->(
|
215
|
-
operand_1 = argument1.evaluate(runtime)
|
216
|
-
operand_2 = argument2.evaluate(runtime)
|
204
|
+
primitive = ->(_runtime, operand_1, operand_2) do
|
217
205
|
raw_result = operand_1.value.modulo(operand_2.value)
|
218
206
|
to_datum(raw_result)
|
219
207
|
end
|
@@ -227,9 +215,7 @@ module Skeem
|
|
227
215
|
end
|
228
216
|
|
229
217
|
def create_eqv?(aRuntime)
|
230
|
-
primitive = ->(runtime,
|
231
|
-
operand_1 = argument1.evaluate(runtime)
|
232
|
-
operand_2 = argument2.evaluate(runtime)
|
218
|
+
primitive = ->(runtime, operand_1, operand_2) do
|
233
219
|
core_eqv?(operand_1, operand_2)
|
234
220
|
end
|
235
221
|
|
@@ -242,9 +228,7 @@ module Skeem
|
|
242
228
|
end
|
243
229
|
|
244
230
|
def create_eq?(aRuntime)
|
245
|
-
primitive = ->(
|
246
|
-
operand_1 = argument1.evaluate(runtime)
|
247
|
-
operand_2 = argument2.evaluate(runtime)
|
231
|
+
primitive = ->(_runtime, operand_1, operand_2) do
|
248
232
|
core_eq?(operand1, operand2)
|
249
233
|
end
|
250
234
|
|
@@ -252,9 +236,7 @@ module Skeem
|
|
252
236
|
end
|
253
237
|
|
254
238
|
def create_equal?(aRuntime)
|
255
|
-
primitive = ->(
|
256
|
-
operand_1 = argument1.evaluate(runtime)
|
257
|
-
operand_2 = argument2.evaluate(runtime)
|
239
|
+
primitive = ->(_runtime, operand_1, operand_2) do
|
258
240
|
raw_result = operand_1.skm_equal?(operand_2)
|
259
241
|
boolean(raw_result)
|
260
242
|
end
|
@@ -263,14 +245,12 @@ module Skeem
|
|
263
245
|
end
|
264
246
|
|
265
247
|
def create_equal(aRuntime)
|
266
|
-
primitive = ->(
|
267
|
-
first_one = first_operand.evaluate(runtime)
|
248
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
268
249
|
if arglist.empty?
|
269
250
|
boolean(true)
|
270
251
|
else
|
271
|
-
|
272
|
-
|
273
|
-
all_equal = operands.all? { |elem| first_value == elem.value }
|
252
|
+
first_value = first_operand.value
|
253
|
+
all_equal = arglist.all? { |elem| first_value == elem.value }
|
274
254
|
boolean(all_equal)
|
275
255
|
end
|
276
256
|
end
|
@@ -279,82 +259,70 @@ module Skeem
|
|
279
259
|
end
|
280
260
|
|
281
261
|
def create_lt(aRuntime)
|
282
|
-
primitive = ->(
|
262
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
283
263
|
if arglist.empty?
|
284
|
-
|
264
|
+
result = false
|
285
265
|
else
|
286
|
-
|
287
|
-
operands.concat(arglist.evaluate(runtime).to_a)
|
288
|
-
result = true
|
289
|
-
operands.each_cons(2) do |(elem1, elem2)|
|
290
|
-
result &&= elem1.value < elem2.value
|
291
|
-
end
|
292
|
-
boolean(result)
|
266
|
+
result = primitive_comparison(:<, _runtime, first_operand, arglist)
|
293
267
|
end
|
268
|
+
boolean(result)
|
294
269
|
end
|
295
270
|
|
296
271
|
define_primitive_proc(aRuntime, '<', one_or_more, primitive)
|
297
272
|
end
|
298
273
|
|
299
274
|
def create_gt(aRuntime)
|
300
|
-
primitive = ->(
|
275
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
301
276
|
if arglist.empty?
|
302
|
-
|
277
|
+
result = false
|
303
278
|
else
|
304
|
-
|
305
|
-
operands.concat(arglist.evaluate(runtime).to_a)
|
306
|
-
result = true
|
307
|
-
operands.each_cons(2) do |(elem1, elem2)|
|
308
|
-
result &&= elem1.value > elem2.value
|
309
|
-
end
|
310
|
-
boolean(result)
|
279
|
+
result = primitive_comparison(:>, _runtime, first_operand, arglist)
|
311
280
|
end
|
281
|
+
boolean(result)
|
312
282
|
end
|
313
283
|
|
314
284
|
define_primitive_proc(aRuntime, '>', one_or_more, primitive)
|
315
285
|
end
|
316
286
|
|
317
287
|
def create_lte(aRuntime)
|
318
|
-
primitive = ->(
|
288
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
319
289
|
if arglist.empty?
|
320
|
-
boolean(true)
|
321
|
-
else
|
322
|
-
operands = [first_operand.evaluate(runtime)]
|
323
|
-
operands.concat(arglist.evaluate(runtime).to_a)
|
324
290
|
result = true
|
325
|
-
|
326
|
-
|
327
|
-
end
|
328
|
-
boolean(result)
|
291
|
+
else
|
292
|
+
result = primitive_comparison(:<=, _runtime, first_operand, arglist)
|
329
293
|
end
|
294
|
+
boolean(result)
|
330
295
|
end
|
331
296
|
|
332
297
|
define_primitive_proc(aRuntime, '<=', one_or_more, primitive)
|
333
298
|
end
|
334
299
|
|
335
300
|
def create_gte(aRuntime)
|
336
|
-
primitive = ->(
|
301
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
337
302
|
if arglist.empty?
|
338
|
-
boolean(true)
|
339
|
-
else
|
340
|
-
operands = [first_operand.evaluate(runtime)]
|
341
|
-
operands.concat(arglist.evaluate(runtime).to_a)
|
342
303
|
result = true
|
343
|
-
|
344
|
-
|
345
|
-
end
|
346
|
-
|
347
|
-
boolean(result)
|
304
|
+
else
|
305
|
+
result = primitive_comparison(:>=, _runtime, first_operand, arglist)
|
348
306
|
end
|
307
|
+
boolean(result)
|
349
308
|
end
|
350
309
|
|
351
310
|
define_primitive_proc(aRuntime, '>=', one_or_more, primitive)
|
352
311
|
end
|
312
|
+
|
313
|
+
def primitive_comparison(operator, _runtime, first_operand, arglist)
|
314
|
+
operands = [first_operand].concat(arglist)
|
315
|
+
result = true
|
316
|
+
operands.each_cons(2) do |(elem1, elem2)|
|
317
|
+
result &&= elem1.value.send(operator, elem2.value)
|
318
|
+
end
|
319
|
+
|
320
|
+
boolean(result)
|
321
|
+
end
|
353
322
|
|
354
323
|
def create_number2string(aRuntime)
|
355
324
|
# TODO: add support for radix argument
|
356
|
-
primitive = ->(
|
357
|
-
arg_evaluated = arg.evaluate(runtime)
|
325
|
+
primitive = ->(_runtime, arg_evaluated) do
|
358
326
|
check_argtype(arg_evaluated, SkmNumber, 'number', 'number->string')
|
359
327
|
string(arg_evaluated.value)
|
360
328
|
end
|
@@ -364,6 +332,7 @@ module Skeem
|
|
364
332
|
|
365
333
|
def create_and(aRuntime)
|
366
334
|
# arglist should be a Ruby Array
|
335
|
+
# Arguments aren't evaluated yet!...
|
367
336
|
primitive = ->(runtime, arglist) do
|
368
337
|
if arglist.empty?
|
369
338
|
boolean(true) # in conformance with 4.2.1
|
@@ -389,6 +358,7 @@ module Skeem
|
|
389
358
|
|
390
359
|
def create_or(aRuntime)
|
391
360
|
# arglist should be a Ruby Array
|
361
|
+
# Arguments aren't evaluated yet!...
|
392
362
|
primitive = ->(runtime, arglist) do
|
393
363
|
if arglist.empty?
|
394
364
|
boolean(false) # in conformance with 4.2.1
|
@@ -409,14 +379,12 @@ module Skeem
|
|
409
379
|
end
|
410
380
|
|
411
381
|
def create_string_equal(aRuntime)
|
412
|
-
primitive = ->(
|
413
|
-
first_one = first_operand.evaluate(runtime)
|
382
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
414
383
|
if arglist.empty?
|
415
384
|
boolean(true)
|
416
385
|
else
|
417
|
-
|
418
|
-
|
419
|
-
all_equal = operands.all? { |elem| first_value == elem.value }
|
386
|
+
first_value = first_operand.value
|
387
|
+
all_equal = arglist.all? { |elem| first_value == elem.value }
|
420
388
|
boolean(all_equal)
|
421
389
|
end
|
422
390
|
end
|
@@ -425,12 +393,11 @@ module Skeem
|
|
425
393
|
end
|
426
394
|
|
427
395
|
def create_string_append(aRuntime)
|
428
|
-
primitive = ->(
|
396
|
+
primitive = ->(_runtime, arglist) do
|
429
397
|
if arglist.empty?
|
430
398
|
value = ''
|
431
399
|
else
|
432
|
-
|
433
|
-
value = parts.reduce('') { |interim, substr| interim << substr.value }
|
400
|
+
value = arglist.reduce('') { |interim, substr| interim << substr.value }
|
434
401
|
end
|
435
402
|
|
436
403
|
string(value)
|
@@ -440,8 +407,7 @@ module Skeem
|
|
440
407
|
end
|
441
408
|
|
442
409
|
def create_string_length(aRuntime)
|
443
|
-
primitive = ->(runtime,
|
444
|
-
arg_evaluated = arg.evaluate(runtime)
|
410
|
+
primitive = ->(runtime, arg_evaluated) do
|
445
411
|
check_argtype(arg_evaluated, SkmString, 'string', 'string-length')
|
446
412
|
integer(arg_evaluated.length)
|
447
413
|
end
|
@@ -450,8 +416,7 @@ module Skeem
|
|
450
416
|
end
|
451
417
|
|
452
418
|
def create_string2symbol(aRuntime)
|
453
|
-
primitive = ->(runtime,
|
454
|
-
arg_evaluated = arg.evaluate(runtime)
|
419
|
+
primitive = ->(runtime, arg_evaluated) do
|
455
420
|
check_argtype(arg_evaluated, SkmString, 'string', 'string->symbol')
|
456
421
|
identifier(arg_evaluated)
|
457
422
|
end
|
@@ -460,8 +425,7 @@ module Skeem
|
|
460
425
|
end
|
461
426
|
|
462
427
|
def create_symbol2string(aRuntime)
|
463
|
-
primitive = ->(runtime,
|
464
|
-
arg_evaluated = arg.evaluate(runtime)
|
428
|
+
primitive = ->(runtime, arg_evaluated) do
|
465
429
|
check_argtype(arg_evaluated, SkmIdentifier, 'symbol', 'symbol->string')
|
466
430
|
string(arg_evaluated)
|
467
431
|
end
|
@@ -470,8 +434,7 @@ module Skeem
|
|
470
434
|
end
|
471
435
|
|
472
436
|
def create_car(aRuntime)
|
473
|
-
primitive = ->(runtime,
|
474
|
-
arg_evaluated = arg.evaluate(runtime)
|
437
|
+
primitive = ->(runtime, arg_evaluated) do
|
475
438
|
check_argtype(arg_evaluated, SkmPair, 'pair', 'car')
|
476
439
|
arg_evaluated.car
|
477
440
|
end
|
@@ -480,8 +443,7 @@ module Skeem
|
|
480
443
|
end
|
481
444
|
|
482
445
|
def create_cdr(aRuntime)
|
483
|
-
primitive = ->(
|
484
|
-
arg_evaluated = arg.evaluate(runtime)
|
446
|
+
primitive = ->(_runtime, arg_evaluated) do
|
485
447
|
check_argtype(arg_evaluated, SkmPair, 'pair', 'cdr')
|
486
448
|
arg_evaluated.cdr
|
487
449
|
end
|
@@ -490,16 +452,15 @@ module Skeem
|
|
490
452
|
end
|
491
453
|
|
492
454
|
def create_cons(aRuntime)
|
493
|
-
primitive = ->(
|
494
|
-
SkmPair.new(obj1
|
455
|
+
primitive = ->(_runtime, obj1, obj2) do
|
456
|
+
SkmPair.new(obj1, obj2)
|
495
457
|
end
|
496
458
|
|
497
459
|
define_primitive_proc(aRuntime, 'cons', binary, primitive)
|
498
460
|
end
|
499
461
|
|
500
462
|
def create_length(aRuntime)
|
501
|
-
primitive = ->(
|
502
|
-
arg_evaluated = arg.evaluate(runtime)
|
463
|
+
primitive = ->(_runtime, arg_evaluated) do
|
503
464
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'length')
|
504
465
|
integer(arg_evaluated.length)
|
505
466
|
end
|
@@ -508,8 +469,7 @@ module Skeem
|
|
508
469
|
end
|
509
470
|
|
510
471
|
def create_list2vector(aRuntime)
|
511
|
-
primitive = ->(
|
512
|
-
arg_evaluated = arg.evaluate(runtime)
|
472
|
+
primitive = ->(_runtime, arg_evaluated) do
|
513
473
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'list->vector')
|
514
474
|
vector(arg_evaluated.to_a)
|
515
475
|
end
|
@@ -555,6 +515,7 @@ module Skeem
|
|
555
515
|
end
|
556
516
|
|
557
517
|
def create_append(aRuntime)
|
518
|
+
# Arguments aren't evaluated yet!...
|
558
519
|
primitive = ->(runtime, arglist) do
|
559
520
|
if arglist.size > 1
|
560
521
|
arguments = evaluate_arguments(arglist, aRuntime)
|
@@ -569,6 +530,7 @@ module Skeem
|
|
569
530
|
end
|
570
531
|
|
571
532
|
def create_setcar(aRuntime)
|
533
|
+
# Arguments aren't evaluated yet!...
|
572
534
|
primitive = ->(runtime, pair_arg, obj_arg) do
|
573
535
|
case pair_arg
|
574
536
|
when SkmPair
|
@@ -593,6 +555,7 @@ module Skeem
|
|
593
555
|
end
|
594
556
|
|
595
557
|
def create_setcdr(aRuntime)
|
558
|
+
# Arguments aren't evaluated yet!...
|
596
559
|
primitive = ->(runtime, pair_arg, obj_arg) do
|
597
560
|
case pair_arg
|
598
561
|
when SkmPair
|
@@ -620,7 +583,7 @@ module Skeem
|
|
620
583
|
primitive = ->(runtime, obj_arg, alist_arg) do
|
621
584
|
assoc_list = alist_arg.evaluate(runtime)
|
622
585
|
check_assoc_list(assoc_list, 'assq')
|
623
|
-
obj = obj_arg.evaluate(runtime)
|
586
|
+
obj = obj_arg.evaluate(runtime)
|
624
587
|
result = boolean(false)
|
625
588
|
unless assoc_list.empty?
|
626
589
|
pair = assoc_list
|
@@ -638,12 +601,10 @@ module Skeem
|
|
638
601
|
end
|
639
602
|
define_primitive_proc(aRuntime, 'assq', binary, primitive)
|
640
603
|
end
|
641
|
-
|
604
|
+
|
642
605
|
def create_assv(aRuntime)
|
643
|
-
primitive = ->(runtime,
|
644
|
-
assoc_list = alist_arg.evaluate(runtime)
|
606
|
+
primitive = ->(runtime, obj, assoc_list) do
|
645
607
|
check_assoc_list(assoc_list, 'assq')
|
646
|
-
obj = obj_arg.evaluate(runtime)
|
647
608
|
result = boolean(false)
|
648
609
|
unless assoc_list.empty?
|
649
610
|
pair = assoc_list
|
@@ -659,8 +620,8 @@ module Skeem
|
|
659
620
|
|
660
621
|
result
|
661
622
|
end
|
662
|
-
define_primitive_proc(aRuntime, 'assv', binary, primitive)
|
663
|
-
end
|
623
|
+
define_primitive_proc(aRuntime, 'assv', binary, primitive)
|
624
|
+
end
|
664
625
|
|
665
626
|
def check_assoc_list(alist, proc_name)
|
666
627
|
check_argtype(alist, [SkmPair, SkmEmptyList], 'association list', proc_name)
|
@@ -675,24 +636,16 @@ module Skeem
|
|
675
636
|
end
|
676
637
|
|
677
638
|
def create_list_copy(aRuntime)
|
678
|
-
primitive = ->(runtime,
|
679
|
-
arg_evaluated = arg.evaluate(runtime)
|
639
|
+
primitive = ->(runtime, arg_evaluated) do
|
680
640
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'list-copy')
|
681
|
-
arg.klone
|
641
|
+
arg_evaluated.klone # Previously: arg.klone
|
682
642
|
end
|
683
643
|
|
684
644
|
define_primitive_proc(aRuntime, 'list-copy', unary, primitive)
|
685
645
|
end
|
686
646
|
|
687
|
-
|
688
647
|
def create_vector(aRuntime)
|
689
|
-
primitive = ->(
|
690
|
-
if arglist.empty?
|
691
|
-
elements = []
|
692
|
-
else
|
693
|
-
elements = evaluate_arguments(arglist, aRuntime)
|
694
|
-
end
|
695
|
-
|
648
|
+
primitive = ->(_runtime, elements) do
|
696
649
|
vector(elements)
|
697
650
|
end
|
698
651
|
|
@@ -700,8 +653,7 @@ module Skeem
|
|
700
653
|
end
|
701
654
|
|
702
655
|
def create_vector_length(aRuntime)
|
703
|
-
primitive = ->(
|
704
|
-
arg_evaluated = arg.evaluate(runtime)
|
656
|
+
primitive = ->(_runtime, arg_evaluated) do
|
705
657
|
check_argtype(arg_evaluated, SkmVector, 'vector', 'vector-length')
|
706
658
|
integer(arg_evaluated.length)
|
707
659
|
end
|
@@ -716,7 +668,7 @@ module Skeem
|
|
716
668
|
if arglist.empty?
|
717
669
|
filler = SkmUndefined.instance
|
718
670
|
else
|
719
|
-
filler = arglist.
|
671
|
+
filler = arglist.first.evaluate(runtime)
|
720
672
|
end
|
721
673
|
elements = Array.new(count.value, filler)
|
722
674
|
|
@@ -728,10 +680,8 @@ module Skeem
|
|
728
680
|
|
729
681
|
def create_vector_ref(aRuntime)
|
730
682
|
# argument 1: a vector, argument 2: an index(integer)
|
731
|
-
primitive = ->(runtime,
|
732
|
-
vector = aVector.evaluate(runtime)
|
683
|
+
primitive = ->(runtime, vector, index) do
|
733
684
|
check_argtype(vector, SkmVector, 'vector', 'vector-ref')
|
734
|
-
index = anIndex.evaluate(runtime)
|
735
685
|
check_argtype(index, SkmInteger, 'integer', 'vector-ref')
|
736
686
|
# TODO: index checking
|
737
687
|
raw_result = vector.members[index.value]
|
@@ -742,8 +692,7 @@ module Skeem
|
|
742
692
|
end
|
743
693
|
|
744
694
|
def create_vector2list(aRuntime)
|
745
|
-
primitive = ->(runtime,
|
746
|
-
arg_evaluated = arg.evaluate(runtime)
|
695
|
+
primitive = ->(runtime, arg_evaluated) do
|
747
696
|
check_argtype(arg_evaluated, SkmVector, 'vector', 'vector->list')
|
748
697
|
SkmPair.create_from_a(arg_evaluated.members)
|
749
698
|
end
|
@@ -752,13 +701,11 @@ module Skeem
|
|
752
701
|
end
|
753
702
|
|
754
703
|
def create_apply(aRuntime)
|
755
|
-
primitive = ->(runtime,
|
756
|
-
proc_arg = first_operand.evaluate(runtime)
|
704
|
+
primitive = ->(runtime, proc_arg, arglist) do
|
757
705
|
if arglist.empty?
|
758
706
|
result = SkmEmptyList.instance
|
759
707
|
else
|
760
|
-
|
761
|
-
single_list = append_core(arguments)
|
708
|
+
single_list = append_core(arglist)
|
762
709
|
invoke = ProcedureCall.new(nil, proc_arg, single_list.to_a)
|
763
710
|
result = invoke.evaluate(runtime)
|
764
711
|
end
|
@@ -768,13 +715,11 @@ module Skeem
|
|
768
715
|
end
|
769
716
|
|
770
717
|
def create_map(aRuntime)
|
771
|
-
primitive = ->(runtime,
|
772
|
-
|
773
|
-
if list_of_lists.empty?
|
718
|
+
primitive = ->(runtime, proc_arg, arglist) do
|
719
|
+
if arglist.empty?
|
774
720
|
result = SkmEmptyList.instance
|
775
721
|
else
|
776
|
-
|
777
|
-
curr_cells = arguments.to_a
|
722
|
+
curr_cells = arglist
|
778
723
|
arity = curr_cells.size
|
779
724
|
initial_result = nil
|
780
725
|
curr_result = nil
|
@@ -813,14 +758,13 @@ module Skeem
|
|
813
758
|
end
|
814
759
|
|
815
760
|
def create_test_assert(aRuntime)
|
816
|
-
primitive = ->(runtime,
|
817
|
-
arg_evaluated = arg.evaluate(runtime)
|
761
|
+
primitive = ->(runtime, arg_evaluated) do
|
818
762
|
if arg_evaluated.boolean? && arg_evaluated.value == false
|
819
763
|
assert_call = aRuntime.caller
|
820
764
|
pos = assert_call.call_site
|
821
765
|
# Error: assertion failed: (> 1 2)
|
822
766
|
msg1 = "assertion failed on line #{pos.line}, column #{pos.column}"
|
823
|
-
msg2 = ", with #{
|
767
|
+
msg2 = ", with #{arg_evaluated.inspect}"
|
824
768
|
raise StandardError, 'Error: ' + msg1 + msg2
|
825
769
|
else
|
826
770
|
boolean(true)
|
@@ -843,8 +787,7 @@ module Skeem
|
|
843
787
|
# DON'T USE IT
|
844
788
|
# Non-standard procedure reserved for internal testing/debugging purposes.
|
845
789
|
def create_inspect(aRuntime)
|
846
|
-
primitive = ->(runtime,
|
847
|
-
arg_evaluated = arg.evaluate(runtime)
|
790
|
+
primitive = ->(runtime, arg_evaluated) do
|
848
791
|
$stderr.puts 'INSPECT>' + arg_evaluated.inspect
|
849
792
|
Skeem::SkmUndefined.instance
|
850
793
|
end
|
@@ -853,21 +796,13 @@ module Skeem
|
|
853
796
|
|
854
797
|
def create_object_predicate(aRuntime, predicate_name, msg_name = nil)
|
855
798
|
msg_name = predicate_name if msg_name.nil?
|
856
|
-
primitive = ->(runtime,
|
857
|
-
arg_evaluated = arg.evaluate(runtime)
|
799
|
+
primitive = ->(runtime, arg_evaluated) do
|
858
800
|
to_datum(arg_evaluated.send(msg_name))
|
859
801
|
end
|
860
802
|
|
861
803
|
define_primitive_proc(aRuntime, predicate_name, unary, primitive)
|
862
804
|
end
|
863
805
|
|
864
|
-
# def def_procedure(aRuntime, pairs)
|
865
|
-
# pairs.each_slice(2) do |(name, code)|
|
866
|
-
# func = PrimitiveProcedure.new(name, code)
|
867
|
-
# define(aRuntime, func.identifier, func)
|
868
|
-
# end
|
869
|
-
# end
|
870
|
-
|
871
806
|
def define_primitive_proc(aRuntime, anIdentifier, anArity, aRubyLambda)
|
872
807
|
primitive = PrimitiveProcedure.new(anIdentifier, anArity, aRubyLambda)
|
873
808
|
@primitive_map = {} unless @primitives_map
|
@@ -114,19 +114,35 @@ module Skeem
|
|
114
114
|
result = code.call(aRuntime)
|
115
115
|
elsif arity.variadic? || (arity.low < arity.high)
|
116
116
|
if arity.low.zero?
|
117
|
-
|
117
|
+
if ['and', 'or', 'append'].include? identifier
|
118
|
+
# Defer the evaluation of arguments to the primitive
|
119
|
+
result = code.call(aRuntime, operands)
|
120
|
+
else
|
121
|
+
evaluated_args = operands.map {|opernd| opernd.evaluate(aRuntime) }
|
122
|
+
result = code.call(aRuntime, evaluated_args)
|
123
|
+
end
|
118
124
|
else
|
119
|
-
|
120
|
-
|
125
|
+
# require 'debug'
|
126
|
+
args = operands.take(arity.low)
|
127
|
+
args.map! { |arg| arg.evaluate(aRuntime) } unless args.empty?
|
121
128
|
count_delta = operands.size - arity.low
|
122
|
-
|
129
|
+
remaining = operands.slice(-count_delta, count_delta).map do |arg|
|
130
|
+
arg.evaluate(aRuntime)
|
131
|
+
end
|
132
|
+
args << remaining.flatten
|
123
133
|
# p operands.size
|
124
134
|
# p count_delta
|
125
|
-
# p
|
126
|
-
result = code.send(:call, aRuntime, *
|
135
|
+
# p args.inspect
|
136
|
+
result = code.send(:call, aRuntime, *args)
|
127
137
|
end
|
128
138
|
else # Fixed arity...
|
129
|
-
|
139
|
+
if identifier == 'set-car!' || identifier == 'set-cdr!'
|
140
|
+
# Defer evaluation inside the primitive
|
141
|
+
result = code.send(:call, aRuntime, *operands)
|
142
|
+
else
|
143
|
+
evaluated_args = operands.map {|opernd| opernd.evaluate(aRuntime) }
|
144
|
+
result = code.send(:call, aRuntime, *evaluated_args)
|
145
|
+
end
|
130
146
|
end
|
131
147
|
|
132
148
|
result
|
@@ -97,6 +97,10 @@ module Skeem
|
|
97
97
|
def number?
|
98
98
|
true
|
99
99
|
end
|
100
|
+
|
101
|
+
def complex?
|
102
|
+
false
|
103
|
+
end
|
100
104
|
|
101
105
|
def eqv?(other)
|
102
106
|
return true if self.equal?(other)
|
@@ -119,6 +123,10 @@ module Skeem
|
|
119
123
|
def real?
|
120
124
|
true
|
121
125
|
end
|
126
|
+
|
127
|
+
def complex?
|
128
|
+
true
|
129
|
+
end
|
122
130
|
|
123
131
|
def exact?
|
124
132
|
false
|
data/lib/skeem/standard/base.skm
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
; Standard R7RS procedures from section 6.2.6
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
;; (exact-integer? z)
|
4
|
+
(define exact-integer?
|
5
|
+
(lambda (z)
|
6
|
+
(and
|
7
|
+
(exact? z)
|
8
|
+
(integer? z))))
|
9
|
+
|
10
|
+
;; (zero? z)
|
11
|
+
;; Returns true iff z is zero
|
5
12
|
(define zero?
|
6
13
|
(lambda (z)
|
7
14
|
(if (= z 0)
|
@@ -9,10 +16,10 @@
|
|
9
16
|
#f)))
|
10
17
|
|
11
18
|
; (positive? x)
|
12
|
-
; Return true if x greater
|
19
|
+
; Return true if x greater than zero; false otherwise
|
13
20
|
(define positive?
|
14
21
|
(lambda (x)
|
15
|
-
(if (
|
22
|
+
(if (> x 0)
|
16
23
|
#t
|
17
24
|
#f)))
|
18
25
|
|
@@ -105,7 +112,7 @@
|
|
105
112
|
;; (test-eqv expected test-expr)
|
106
113
|
(define test-eqv
|
107
114
|
(lambda (x y)
|
108
|
-
(test-assert (
|
115
|
+
(test-assert (eqv? x y))))
|
109
116
|
|
110
117
|
;; Test the equality (with equal? predicate) between an expected value and
|
111
118
|
;; an expression
|
data/lib/skeem/tokenizer.rb
CHANGED
@@ -92,10 +92,10 @@ module Skeem
|
|
92
92
|
elsif (lexeme = scanner.scan(/(?:,@?)|(?:=>)/))
|
93
93
|
token = build_token(@@lexeme2name[lexeme], lexeme)
|
94
94
|
elsif (lexeme = scanner.scan(/#(?:(?:true)|(?:false)|(?:u8)|[\\\(tfeiodx]|(?:\d+[=#]))/))
|
95
|
-
token = cardinal_token(lexeme)
|
96
|
-
elsif (lexeme = scanner.scan(/[+-]?[0-9]+(?=\s|[|()";]|$)/))
|
95
|
+
token = cardinal_token(lexeme)
|
96
|
+
elsif (lexeme = scanner.scan(/[+-]?[0-9]+(?:.0+)?(?=\s|[|()";]|$)/))
|
97
97
|
token = build_token('INTEGER', lexeme) # Decimal radix
|
98
|
-
elsif (lexeme = scanner.scan(/[+-]?[0-9]+(?:\.[0-9]
|
98
|
+
elsif (lexeme = scanner.scan(/[+-]?[0-9]+(?:\.[0-9]*)?(?:(?:e|E)[+-]?[0-9]+)?/))
|
99
99
|
# Order dependency: must be tested after INTEGER case
|
100
100
|
token = build_token('REAL', lexeme)
|
101
101
|
elsif (lexeme = scanner.scan(/"(?:\\"|[^"])*"/)) # Double quotes literal?
|
@@ -124,7 +124,7 @@ module Skeem
|
|
124
124
|
|
125
125
|
return token
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
=begin
|
129
129
|
#t #f These are the boolean constants (section 6.3), along
|
130
130
|
with the alternatives #true and #false.
|
@@ -138,7 +138,7 @@ numbers (section 6.2.5).
|
|
138
138
|
#<n>= #<n># These are used for labeling and referencing
|
139
139
|
other literal data (section 2.4).
|
140
140
|
# token = build_token('BOOLEAN', lexeme)
|
141
|
-
=end
|
141
|
+
=end
|
142
142
|
def cardinal_token(aLexeme)
|
143
143
|
case aLexeme
|
144
144
|
when /^#true|false|t|f$/
|
@@ -146,7 +146,7 @@ other literal data (section 2.4).
|
|
146
146
|
when '#('
|
147
147
|
token = build_token(@@lexeme2name[aLexeme], aLexeme)
|
148
148
|
end
|
149
|
-
|
149
|
+
|
150
150
|
return token
|
151
151
|
end
|
152
152
|
|
@@ -175,7 +175,7 @@ other literal data (section 2.4).
|
|
175
175
|
when 'STRING_LIT'
|
176
176
|
value = to_string(aLexeme, aFormat)
|
177
177
|
when 'IDENTIFIER'
|
178
|
-
value = to_identifier(aLexeme, aFormat)
|
178
|
+
value = to_identifier(aLexeme, aFormat)
|
179
179
|
else
|
180
180
|
value = aLexeme
|
181
181
|
end
|
@@ -204,7 +204,7 @@ other literal data (section 2.4).
|
|
204
204
|
|
205
205
|
return value
|
206
206
|
end
|
207
|
-
|
207
|
+
|
208
208
|
def to_string(aLexeme, aFormat)
|
209
209
|
case aFormat
|
210
210
|
when :default
|
@@ -212,7 +212,7 @@ other literal data (section 2.4).
|
|
212
212
|
end
|
213
213
|
|
214
214
|
return value
|
215
|
-
end
|
215
|
+
end
|
216
216
|
|
217
217
|
def to_identifier(aLexeme, aFormat)
|
218
218
|
case aFormat
|
@@ -221,26 +221,27 @@ other literal data (section 2.4).
|
|
221
221
|
end
|
222
222
|
|
223
223
|
return value
|
224
|
-
end
|
225
|
-
|
224
|
+
end
|
225
|
+
|
226
226
|
def skip_whitespaces
|
227
227
|
pre_pos = scanner.pos
|
228
228
|
|
229
229
|
loop do
|
230
|
-
ws_found = false
|
231
|
-
|
232
|
-
|
233
|
-
ws_found = true if found
|
234
|
-
found = scanner.skip(/(?:\r\n)|\r|\n/)
|
235
|
-
if found
|
230
|
+
ws_found = scanner.skip(/[ \t\f]+/) ? true : false
|
231
|
+
nl_found = scanner.skip(/(?:\r\n)|\r|\n/)
|
232
|
+
if nl_found
|
236
233
|
ws_found = true
|
237
234
|
next_line
|
238
235
|
end
|
236
|
+
cmt_found = false
|
239
237
|
next_ch = scanner.peek(1)
|
240
238
|
if next_ch == ';'
|
241
239
|
cmt_found = true
|
242
240
|
scanner.skip(/;[^\r\n]*(?:(?:\r\n)|\r|\n)?/)
|
243
241
|
next_line
|
242
|
+
elsif scanner.peek(2) == '#|'
|
243
|
+
skip_block_comment
|
244
|
+
next
|
244
245
|
end
|
245
246
|
break unless ws_found or cmt_found
|
246
247
|
end
|
@@ -248,7 +249,28 @@ other literal data (section 2.4).
|
|
248
249
|
curr_pos = scanner.pos
|
249
250
|
return if curr_pos == pre_pos
|
250
251
|
end
|
251
|
-
|
252
|
+
|
253
|
+
def skip_block_comment()
|
254
|
+
# require 'debug'
|
255
|
+
scanner.skip(/#\|/)
|
256
|
+
nesting_level = 1
|
257
|
+
loop do
|
258
|
+
comment_part = scanner.scan_until(/(?:\|\#)|(?:\#\|)|(?:(?:\r\n)|\r|\n)/)
|
259
|
+
unless comment_part
|
260
|
+
raise ScanError, "Unterminated '#| ... |#' comment on line #{lineno}"
|
261
|
+
end
|
262
|
+
case scanner.matched
|
263
|
+
when /(?:(?:\r\n)|\r|\n)/
|
264
|
+
next_line
|
265
|
+
when '|#'
|
266
|
+
nesting_level -= 1
|
267
|
+
break if nesting_level.zero?
|
268
|
+
when '#|'
|
269
|
+
nesting_level += 1
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
252
274
|
def next_line
|
253
275
|
@lineno += 1
|
254
276
|
@line_start = scanner.pos
|
data/lib/skeem/version.rb
CHANGED
@@ -664,23 +664,8 @@ SKEEM
|
|
664
664
|
checks = [
|
665
665
|
['(positive? 3.1)', true],
|
666
666
|
['(positive? -3.1)', false],
|
667
|
-
['(positive? 0)',
|
668
|
-
['(positive? 0.0)',
|
669
|
-
['(positive? 3)', true],
|
670
|
-
['(positive? -3)', false]
|
671
|
-
]
|
672
|
-
checks.each do |(skeem_expr, expectation)|
|
673
|
-
result = subject.run(skeem_expr)
|
674
|
-
expect(result).to eq(expectation)
|
675
|
-
end
|
676
|
-
end
|
677
|
-
|
678
|
-
it 'should implement the positive? predicate' do
|
679
|
-
checks = [
|
680
|
-
['(positive? 3.1)', true],
|
681
|
-
['(positive? -3.1)', false],
|
682
|
-
['(positive? 0)', true],
|
683
|
-
['(positive? 0.0)', true],
|
667
|
+
['(positive? 0)', false],
|
668
|
+
['(positive? 0.0)', false],
|
684
669
|
['(positive? 3)', true],
|
685
670
|
['(positive? -3)', false]
|
686
671
|
]
|
@@ -146,7 +146,8 @@ module Skeem
|
|
146
146
|
no_arg = []
|
147
147
|
expect(pproc.call(rtime, no_arg)).to eq(0)
|
148
148
|
|
149
|
-
many = ['foo', 'bar',
|
149
|
+
many = [SkmString.create('foo'), SkmString.create('bar'),
|
150
|
+
SkmString.create('quux')]
|
150
151
|
expect( pproc.call(rtime, many)).to eq(3)
|
151
152
|
end
|
152
153
|
end # context
|
@@ -69,6 +69,7 @@ module Skeem
|
|
69
69
|
[' 3', 3],
|
70
70
|
['+3 ', +3],
|
71
71
|
['-3', -3],
|
72
|
+
['-3.0', -3],
|
72
73
|
['-1234', -1234]
|
73
74
|
]
|
74
75
|
|
@@ -167,7 +168,7 @@ module Skeem
|
|
167
168
|
end
|
168
169
|
end
|
169
170
|
|
170
|
-
context '
|
171
|
+
context 'Comments:' do
|
171
172
|
it 'should skip heading comments' do
|
172
173
|
input = "; Starting comment\n \"Some text\""
|
173
174
|
subject.reinitialize(input)
|
@@ -197,6 +198,32 @@ module Skeem
|
|
197
198
|
expect(token.terminal).to eq('STRING_LIT')
|
198
199
|
expect(token.lexeme).to eq('Second text')
|
199
200
|
end
|
201
|
+
|
202
|
+
it 'should skip block comments' do
|
203
|
+
input = '"First text" #| Middle comment |# "Second text"'
|
204
|
+
subject.reinitialize(input)
|
205
|
+
tokens = subject.tokens
|
206
|
+
expect(tokens.size).to eq(2)
|
207
|
+
token = tokens[0]
|
208
|
+
expect(token.terminal).to eq('STRING_LIT')
|
209
|
+
expect(token.lexeme).to eq('First text')
|
210
|
+
token = tokens[1]
|
211
|
+
expect(token.terminal).to eq('STRING_LIT')
|
212
|
+
expect(token.lexeme).to eq('Second text')
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should cope with nested block comments' do
|
216
|
+
input = '"First text" #| One #| Two |# comment #| Three |# |# "Second text"'
|
217
|
+
subject.reinitialize(input)
|
218
|
+
tokens = subject.tokens
|
219
|
+
expect(tokens.size).to eq(2)
|
220
|
+
token = tokens[0]
|
221
|
+
expect(token.terminal).to eq('STRING_LIT')
|
222
|
+
expect(token.lexeme).to eq('First text')
|
223
|
+
token = tokens[1]
|
224
|
+
expect(token.terminal).to eq('STRING_LIT')
|
225
|
+
expect(token.lexeme).to eq('Second text')
|
226
|
+
end
|
200
227
|
end
|
201
228
|
|
202
229
|
context 'Scanning Scheme sample code' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skeem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.09
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|