skeem 0.2.15 → 0.2.16
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/.rubocop.yml +17 -11
- data/CHANGELOG.md +5 -0
- data/Gemfile +2 -0
- data/README.md +3 -2
- data/Rakefile +2 -0
- data/appveyor.yml +3 -4
- data/bin/skeem +15 -15
- data/lib/skeem.rb +2 -0
- data/lib/skeem/datum_dsl.rb +12 -3
- data/lib/skeem/element_visitor.rb +5 -2
- data/lib/skeem/grammar.rb +86 -24
- data/lib/skeem/interpreter.rb +5 -3
- data/lib/skeem/parser.rb +6 -4
- data/lib/skeem/primitive/primitive_builder.rb +128 -115
- data/lib/skeem/primitive/primitive_procedure.rb +17 -20
- data/lib/skeem/runtime.rb +9 -5
- data/lib/skeem/s_expr_builder.rb +46 -104
- data/lib/skeem/s_expr_nodes.rb +116 -90
- data/lib/skeem/skeem_exception.rb +0 -0
- data/lib/skeem/skm_binding.rb +6 -7
- data/lib/skeem/skm_compound_datum.rb +8 -4
- data/lib/skeem/skm_element.rb +14 -12
- data/lib/skeem/skm_empty_list.rb +6 -4
- data/lib/skeem/skm_exception.rb +9 -0
- data/lib/skeem/skm_expression.rb +3 -1
- data/lib/skeem/skm_frame.rb +3 -2
- data/lib/skeem/skm_pair.rb +23 -18
- data/lib/skeem/skm_procedure_exec.rb +8 -6
- data/lib/skeem/skm_simple_datum.rb +13 -12
- data/lib/skeem/skm_unary_expression.rb +15 -17
- data/lib/skeem/tokenizer.rb +32 -25
- data/lib/skeem/version.rb +3 -1
- data/skeem.gemspec +6 -4
- data/spec/skeem/add4.skm +4 -0
- data/spec/skeem/datum_dsl_spec.rb +13 -12
- data/spec/skeem/element_visitor_spec.rb +12 -10
- data/spec/skeem/interpreter_spec.rb +74 -46
- data/spec/skeem/lambda_spec.rb +9 -7
- data/spec/skeem/parser_spec.rb +21 -19
- data/spec/skeem/primitive/primitive_builder_spec.rb +57 -48
- data/spec/skeem/primitive/primitive_procedure_spec.rb +15 -13
- data/spec/skeem/runtime_spec.rb +18 -16
- data/spec/skeem/s_expr_nodes_spec.rb +8 -6
- data/spec/skeem/skm_compound_datum_spec.rb +11 -9
- data/spec/skeem/skm_element_spec.rb +7 -5
- data/spec/skeem/skm_empty_list_spec.rb +7 -5
- data/spec/skeem/skm_frame_spec.rb +5 -4
- data/spec/skeem/skm_pair_spec.rb +4 -3
- data/spec/skeem/skm_procedure_exec_spec.rb +2 -0
- data/spec/skeem/skm_simple_datum_spec.rb +24 -22
- data/spec/skeem/skm_unary_expression_spec.rb +11 -9
- data/spec/skeem/tokenizer_spec.rb +53 -44
- data/spec/skeem_spec.rb +2 -0
- data/spec/spec_helper.rb +4 -2
- metadata +7 -4
data/lib/skeem/interpreter.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'parser'
|
2
4
|
require_relative 'skm_frame'
|
3
5
|
require_relative 'runtime'
|
@@ -9,7 +11,7 @@ module Skeem
|
|
9
11
|
attr_reader(:parser)
|
10
12
|
attr_reader(:runtime)
|
11
13
|
|
12
|
-
def initialize
|
14
|
+
def initialize
|
13
15
|
@runtime = Runtime.new(SkmFrame.new)
|
14
16
|
@parser = Parser.new
|
15
17
|
|
@@ -20,7 +22,7 @@ module Skeem
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
def add_default_procedures
|
25
|
+
def add_default_procedures
|
24
26
|
add_primitives(runtime)
|
25
27
|
add_standard(runtime)
|
26
28
|
end
|
@@ -57,4 +59,4 @@ module Skeem
|
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end # class
|
60
|
-
end # module
|
62
|
+
end # module
|
data/lib/skeem/parser.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'tokenizer'
|
2
4
|
require_relative 'grammar'
|
3
5
|
require_relative 's_expr_builder'
|
@@ -5,10 +7,10 @@ require_relative 's_expr_builder'
|
|
5
7
|
module Skeem
|
6
8
|
class Parser
|
7
9
|
attr_reader(:engine)
|
8
|
-
|
9
|
-
def initialize
|
10
|
+
|
11
|
+
def initialize
|
10
12
|
# Create a Rley facade object
|
11
|
-
@engine = Rley::Engine.new do |cfg|
|
13
|
+
@engine = Rley::Engine.new do |cfg|
|
12
14
|
cfg.diagnose = true
|
13
15
|
cfg.repr_builder = SkmBuilder
|
14
16
|
end
|
@@ -16,7 +18,7 @@ module Skeem
|
|
16
18
|
# Step 1. Load Skeem grammar
|
17
19
|
@engine.use_grammar(Skeem::Grammar)
|
18
20
|
end
|
19
|
-
|
21
|
+
|
20
22
|
# Parse the given Skeem expression into a parse tree.
|
21
23
|
# @param source [String] Skeem expression to parse
|
22
24
|
# @return [ParseTree] A regexp object equivalent to the Skeem expression.
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'primitive_procedure'
|
2
4
|
require_relative '../datum_dsl'
|
5
|
+
require_relative '../skm_exception'
|
3
6
|
require_relative '../skm_pair'
|
4
7
|
|
5
8
|
module Skeem
|
@@ -34,7 +37,7 @@ module Skeem
|
|
34
37
|
def binary
|
35
38
|
SkmArity.new(2, 2)
|
36
39
|
end
|
37
|
-
|
40
|
+
|
38
41
|
def ternary
|
39
42
|
SkmArity.new(3, 3)
|
40
43
|
end
|
@@ -158,11 +161,12 @@ module Skeem
|
|
158
161
|
create_map(aRuntime)
|
159
162
|
end
|
160
163
|
|
161
|
-
def add_io_procedures(aRuntime)
|
164
|
+
def add_io_procedures(aRuntime)
|
162
165
|
create_display(aRuntime)
|
163
166
|
end
|
164
167
|
|
165
168
|
def add_special_procedures(aRuntime)
|
169
|
+
create_error(aRuntime)
|
166
170
|
create_test_assert(aRuntime)
|
167
171
|
create_debug(aRuntime)
|
168
172
|
create_inspect(aRuntime)
|
@@ -170,7 +174,7 @@ module Skeem
|
|
170
174
|
|
171
175
|
def create_plus(aRuntime)
|
172
176
|
# arglist should be a Ruby Array
|
173
|
-
primitive =
|
177
|
+
primitive = lambda do |_runtime, arglist|
|
174
178
|
if arglist.empty?
|
175
179
|
integer(0)
|
176
180
|
else
|
@@ -184,7 +188,7 @@ module Skeem
|
|
184
188
|
end
|
185
189
|
|
186
190
|
def create_minus(aRuntime)
|
187
|
-
primitive =
|
191
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
188
192
|
raw_result = first_operand.value
|
189
193
|
if arglist.empty?
|
190
194
|
raw_result = -raw_result
|
@@ -198,7 +202,7 @@ module Skeem
|
|
198
202
|
end
|
199
203
|
|
200
204
|
def create_multiply(aRuntime)
|
201
|
-
primitive =
|
205
|
+
primitive = lambda do |_runtime, arglist|
|
202
206
|
if arglist.empty?
|
203
207
|
integer(1)
|
204
208
|
else
|
@@ -212,7 +216,6 @@ module Skeem
|
|
212
216
|
end
|
213
217
|
|
214
218
|
def reciprocal(aLiteral)
|
215
|
-
|
216
219
|
case aLiteral
|
217
220
|
when Integer
|
218
221
|
result = Rational(1, aLiteral)
|
@@ -226,29 +229,29 @@ module Skeem
|
|
226
229
|
end
|
227
230
|
|
228
231
|
def create_divide(aRuntime)
|
229
|
-
primitive =
|
232
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
230
233
|
raw_result = first_operand.value
|
231
234
|
if arglist.empty?
|
232
235
|
raw_result = reciprocal(raw_result)
|
233
236
|
else
|
234
237
|
# Ugly: Ruby version dependency: Rubies older than 2.4 have class Fixnum instead of Integer
|
235
|
-
int_class = (RUBY_VERSION[0..2] <
|
238
|
+
int_class = (RUBY_VERSION[0..2] < '2.4') ? Fixnum : Integer
|
236
239
|
|
237
240
|
arglist.each do |elem|
|
238
241
|
elem_value = elem.value
|
239
242
|
case [raw_result.class, elem_value.class]
|
240
243
|
when [int_class, int_class]
|
241
244
|
if raw_result.modulo(elem_value).zero?
|
242
|
-
raw_result
|
245
|
+
raw_result /= elem_value
|
243
246
|
else
|
244
247
|
raw_result = Rational(raw_result, elem_value)
|
245
248
|
end
|
246
249
|
|
247
250
|
when [int_class, Rational]
|
248
|
-
raw_result
|
251
|
+
raw_result *= reciprocal(elem_value)
|
249
252
|
|
250
253
|
when [Rational, Rational]
|
251
|
-
raw_result
|
254
|
+
raw_result *= reciprocal(elem_value)
|
252
255
|
else
|
253
256
|
raw_result = raw_result.to_f
|
254
257
|
raw_result /= elem_value
|
@@ -262,8 +265,8 @@ module Skeem
|
|
262
265
|
end
|
263
266
|
|
264
267
|
def create_floor_slash(aRuntime)
|
265
|
-
primitive =
|
266
|
-
(quotient, modulus) =
|
268
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
269
|
+
(quotient, modulus) = operand1.value.divmod(operand2.value)
|
267
270
|
SkmPair.new(to_datum(quotient), to_datum(modulus)) # improper list!
|
268
271
|
end
|
269
272
|
|
@@ -271,10 +274,10 @@ module Skeem
|
|
271
274
|
end
|
272
275
|
|
273
276
|
def create_truncate_slash(aRuntime)
|
274
|
-
primitive =
|
275
|
-
modulo_ =
|
276
|
-
modulo_ += 1 if modulo_
|
277
|
-
remainder_ =
|
277
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
278
|
+
modulo_ = operand1.value / operand2.value
|
279
|
+
modulo_ += 1 if modulo_.negative?
|
280
|
+
remainder_ = operand1.value.remainder(operand2.value)
|
278
281
|
SkmPair.new(to_datum(modulo_), to_datum(remainder_)) # improper list!
|
279
282
|
end
|
280
283
|
|
@@ -282,7 +285,7 @@ module Skeem
|
|
282
285
|
end
|
283
286
|
|
284
287
|
def create_gcd(aRuntime)
|
285
|
-
primitive =
|
288
|
+
primitive = lambda do |_runtime, arglist|
|
286
289
|
if arglist.empty?
|
287
290
|
integer(0)
|
288
291
|
else
|
@@ -301,7 +304,7 @@ module Skeem
|
|
301
304
|
end
|
302
305
|
|
303
306
|
def create_lcm(aRuntime)
|
304
|
-
primitive =
|
307
|
+
primitive = lambda do |_runtime, arglist|
|
305
308
|
if arglist.empty?
|
306
309
|
integer(1)
|
307
310
|
else
|
@@ -315,7 +318,7 @@ module Skeem
|
|
315
318
|
end
|
316
319
|
|
317
320
|
def create_numerator(aRuntime)
|
318
|
-
primitive =
|
321
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
319
322
|
case arg_evaluated
|
320
323
|
when SkmInteger
|
321
324
|
result = arg_evaluated
|
@@ -329,7 +332,7 @@ module Skeem
|
|
329
332
|
end
|
330
333
|
|
331
334
|
def create_denominator(aRuntime)
|
332
|
-
primitive =
|
335
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
333
336
|
case arg_evaluated
|
334
337
|
when SkmInteger
|
335
338
|
result = 1
|
@@ -343,7 +346,7 @@ module Skeem
|
|
343
346
|
end
|
344
347
|
|
345
348
|
def create_floor(aRuntime)
|
346
|
-
primitive =
|
349
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
347
350
|
result = arg_evaluated.value.floor
|
348
351
|
integer(result)
|
349
352
|
end
|
@@ -352,7 +355,7 @@ module Skeem
|
|
352
355
|
end
|
353
356
|
|
354
357
|
def create_ceiling(aRuntime)
|
355
|
-
primitive =
|
358
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
356
359
|
result = arg_evaluated.value.ceil
|
357
360
|
integer(result)
|
358
361
|
end
|
@@ -361,7 +364,7 @@ module Skeem
|
|
361
364
|
end
|
362
365
|
|
363
366
|
def create_round(aRuntime)
|
364
|
-
primitive =
|
367
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
365
368
|
result = arg_evaluated.value.round
|
366
369
|
integer(result)
|
367
370
|
end
|
@@ -375,8 +378,8 @@ module Skeem
|
|
375
378
|
end
|
376
379
|
|
377
380
|
def create_eqv?(aRuntime)
|
378
|
-
primitive =
|
379
|
-
core_eqv?(
|
381
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
382
|
+
core_eqv?(operand1, operand2)
|
380
383
|
end
|
381
384
|
|
382
385
|
define_primitive_proc(aRuntime, 'eqv?', binary, primitive)
|
@@ -388,7 +391,7 @@ module Skeem
|
|
388
391
|
end
|
389
392
|
|
390
393
|
def create_eq?(aRuntime)
|
391
|
-
primitive =
|
394
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
392
395
|
core_eq?(operand1, operand2)
|
393
396
|
end
|
394
397
|
|
@@ -396,8 +399,8 @@ module Skeem
|
|
396
399
|
end
|
397
400
|
|
398
401
|
def create_equal?(aRuntime)
|
399
|
-
primitive =
|
400
|
-
raw_result =
|
402
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
403
|
+
raw_result = operand1.skm_equal?(operand2)
|
401
404
|
boolean(raw_result)
|
402
405
|
end
|
403
406
|
|
@@ -405,7 +408,7 @@ module Skeem
|
|
405
408
|
end
|
406
409
|
|
407
410
|
def create_equal(aRuntime)
|
408
|
-
primitive =
|
411
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
409
412
|
if arglist.empty?
|
410
413
|
boolean(true)
|
411
414
|
else
|
@@ -419,11 +422,11 @@ module Skeem
|
|
419
422
|
end
|
420
423
|
|
421
424
|
def create_lt(aRuntime)
|
422
|
-
primitive =
|
425
|
+
primitive = lambda do |runtime, first_operand, arglist|
|
423
426
|
if arglist.empty?
|
424
427
|
result = false
|
425
428
|
else
|
426
|
-
result = primitive_comparison(:<,
|
429
|
+
result = primitive_comparison(:<, runtime, first_operand, arglist)
|
427
430
|
end
|
428
431
|
boolean(result)
|
429
432
|
end
|
@@ -432,11 +435,11 @@ module Skeem
|
|
432
435
|
end
|
433
436
|
|
434
437
|
def create_gt(aRuntime)
|
435
|
-
primitive =
|
438
|
+
primitive = lambda do |runtime, first_operand, arglist|
|
436
439
|
if arglist.empty?
|
437
440
|
result = false
|
438
441
|
else
|
439
|
-
result = primitive_comparison(:>,
|
442
|
+
result = primitive_comparison(:>, runtime, first_operand, arglist)
|
440
443
|
end
|
441
444
|
boolean(result)
|
442
445
|
end
|
@@ -445,11 +448,11 @@ module Skeem
|
|
445
448
|
end
|
446
449
|
|
447
450
|
def create_lte(aRuntime)
|
448
|
-
primitive =
|
451
|
+
primitive = lambda do |runtime, first_operand, arglist|
|
449
452
|
if arglist.empty?
|
450
453
|
result = true
|
451
454
|
else
|
452
|
-
result = primitive_comparison(:<=,
|
455
|
+
result = primitive_comparison(:<=, runtime, first_operand, arglist)
|
453
456
|
end
|
454
457
|
boolean(result)
|
455
458
|
end
|
@@ -458,11 +461,11 @@ module Skeem
|
|
458
461
|
end
|
459
462
|
|
460
463
|
def create_gte(aRuntime)
|
461
|
-
primitive =
|
464
|
+
primitive = lambda do |runtime, first_operand, arglist|
|
462
465
|
if arglist.empty?
|
463
466
|
result = true
|
464
467
|
else
|
465
|
-
result = primitive_comparison(:>=,
|
468
|
+
result = primitive_comparison(:>=, runtime, first_operand, arglist)
|
466
469
|
end
|
467
470
|
boolean(result)
|
468
471
|
end
|
@@ -481,7 +484,7 @@ module Skeem
|
|
481
484
|
end
|
482
485
|
|
483
486
|
def create_max(aRuntime)
|
484
|
-
primitive =
|
487
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
485
488
|
if arglist.empty?
|
486
489
|
result = first_operand
|
487
490
|
else
|
@@ -499,7 +502,7 @@ module Skeem
|
|
499
502
|
end
|
500
503
|
|
501
504
|
def create_min(aRuntime)
|
502
|
-
primitive =
|
505
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
503
506
|
if arglist.empty?
|
504
507
|
result = first_operand
|
505
508
|
else
|
@@ -518,7 +521,7 @@ module Skeem
|
|
518
521
|
|
519
522
|
def create_number2string(aRuntime)
|
520
523
|
# TODO: add support for radix argument
|
521
|
-
primitive =
|
524
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
522
525
|
check_argtype(arg_evaluated, SkmNumber, 'number', 'number->string')
|
523
526
|
string(arg_evaluated.value)
|
524
527
|
end
|
@@ -529,7 +532,7 @@ module Skeem
|
|
529
532
|
def create_and(aRuntime)
|
530
533
|
# arglist should be a Ruby Array
|
531
534
|
# Arguments aren't evaluated yet!...
|
532
|
-
primitive =
|
535
|
+
primitive = lambda do |runtime, arglist|
|
533
536
|
if arglist.empty?
|
534
537
|
boolean(true) # in conformance with 4.2.1
|
535
538
|
else
|
@@ -537,7 +540,7 @@ module Skeem
|
|
537
540
|
last_result = nil
|
538
541
|
# $stderr.puts arglist.inspect
|
539
542
|
arglist.each do |raw_arg|
|
540
|
-
argument = raw_arg.evaluate(
|
543
|
+
argument = raw_arg.evaluate(runtime)
|
541
544
|
last_result = argument
|
542
545
|
raw_result &&= !(argument.boolean? && !argument.value)
|
543
546
|
break unless raw_result # stop here, a false was found...
|
@@ -555,14 +558,14 @@ module Skeem
|
|
555
558
|
def create_or(aRuntime)
|
556
559
|
# arglist should be a Ruby Array
|
557
560
|
# Arguments aren't evaluated yet!...
|
558
|
-
primitive =
|
561
|
+
primitive = lambda do |runtime, arglist|
|
559
562
|
if arglist.empty?
|
560
563
|
boolean(false) # in conformance with 4.2.1
|
561
564
|
else
|
562
565
|
raw_result = false
|
563
566
|
last_result = nil
|
564
567
|
arglist.each do |raw_arg|
|
565
|
-
argument = raw_arg.evaluate(
|
568
|
+
argument = raw_arg.evaluate(runtime)
|
566
569
|
last_result = argument
|
567
570
|
raw_result ||= (!argument.boolean? || argument.value)
|
568
571
|
break if raw_result # stop here, a true was found...
|
@@ -602,7 +605,7 @@ module Skeem
|
|
602
605
|
end
|
603
606
|
|
604
607
|
def create_boolean_equal(aRuntime)
|
605
|
-
primitive =
|
608
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
606
609
|
compare_all(first_operand, arglist, :==)
|
607
610
|
end
|
608
611
|
|
@@ -610,7 +613,7 @@ module Skeem
|
|
610
613
|
end
|
611
614
|
|
612
615
|
def create_char2int(aRuntime)
|
613
|
-
primitive =
|
616
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
614
617
|
check_argtype(arg_evaluated, SkmChar, 'character', 'char->integer')
|
615
618
|
integer(arg_evaluated.value.ord)
|
616
619
|
end
|
@@ -619,7 +622,7 @@ module Skeem
|
|
619
622
|
end
|
620
623
|
|
621
624
|
def create_int2char(aRuntime)
|
622
|
-
primitive =
|
625
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
623
626
|
check_argtype(arg_evaluated, SkmInteger, 'integer', 'integer->char')
|
624
627
|
char(arg_evaluated.value.ord)
|
625
628
|
end
|
@@ -628,7 +631,7 @@ module Skeem
|
|
628
631
|
end
|
629
632
|
|
630
633
|
def create_char_equal(aRuntime)
|
631
|
-
primitive =
|
634
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
632
635
|
compare_all(first_operand, arglist, :==)
|
633
636
|
end
|
634
637
|
|
@@ -636,7 +639,7 @@ module Skeem
|
|
636
639
|
end
|
637
640
|
|
638
641
|
def create_char_lt(aRuntime)
|
639
|
-
primitive =
|
642
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
640
643
|
compare_all(first_operand, arglist, :<)
|
641
644
|
end
|
642
645
|
|
@@ -644,7 +647,7 @@ module Skeem
|
|
644
647
|
end
|
645
648
|
|
646
649
|
def create_char_gt(aRuntime)
|
647
|
-
primitive =
|
650
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
648
651
|
compare_all(first_operand, arglist, :>)
|
649
652
|
end
|
650
653
|
|
@@ -652,7 +655,7 @@ module Skeem
|
|
652
655
|
end
|
653
656
|
|
654
657
|
def create_char_lte(aRuntime)
|
655
|
-
primitive =
|
658
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
656
659
|
compare_all(first_operand, arglist, :<=)
|
657
660
|
end
|
658
661
|
|
@@ -660,16 +663,15 @@ module Skeem
|
|
660
663
|
end
|
661
664
|
|
662
665
|
def create_char_gte(aRuntime)
|
663
|
-
primitive =
|
666
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
664
667
|
compare_all(first_operand, arglist, :>=)
|
665
668
|
end
|
666
669
|
|
667
670
|
define_primitive_proc(aRuntime, 'char>=?', one_or_more, primitive)
|
668
671
|
end
|
669
672
|
|
670
|
-
|
671
673
|
def create_make_string(aRuntime)
|
672
|
-
primitive =
|
674
|
+
primitive = lambda do |_runtime, count_arg, arglist|
|
673
675
|
count = count_arg
|
674
676
|
check_argtype(count, SkmInteger, 'integer', 'make-string')
|
675
677
|
if arglist.empty?
|
@@ -685,11 +687,11 @@ module Skeem
|
|
685
687
|
end
|
686
688
|
|
687
689
|
def create_string_string(aRuntime)
|
688
|
-
primitive =
|
690
|
+
primitive = lambda do |_runtime, arglist|
|
689
691
|
if arglist.empty?
|
690
692
|
value = ''
|
691
693
|
else
|
692
|
-
value = arglist.reduce('') do |interim, some_char|
|
694
|
+
value = arglist.reduce(+'') do |interim, some_char|
|
693
695
|
check_argtype(some_char, SkmChar, 'character', 'string')
|
694
696
|
interim << some_char.value
|
695
697
|
end
|
@@ -702,7 +704,7 @@ module Skeem
|
|
702
704
|
end
|
703
705
|
|
704
706
|
def create_string_equal(aRuntime)
|
705
|
-
primitive =
|
707
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
706
708
|
all_same?(first_operand, arglist)
|
707
709
|
end
|
708
710
|
|
@@ -710,11 +712,11 @@ module Skeem
|
|
710
712
|
end
|
711
713
|
|
712
714
|
def create_string_append(aRuntime)
|
713
|
-
primitive =
|
715
|
+
primitive = lambda do |_runtime, arglist|
|
714
716
|
if arglist.empty?
|
715
717
|
value = ''
|
716
718
|
else
|
717
|
-
value = arglist.reduce('') { |interim, substr| interim << substr.value }
|
719
|
+
value = arglist.reduce(+'') { |interim, substr| interim << substr.value }
|
718
720
|
end
|
719
721
|
|
720
722
|
string(value)
|
@@ -724,7 +726,7 @@ module Skeem
|
|
724
726
|
end
|
725
727
|
|
726
728
|
def create_string_length(aRuntime)
|
727
|
-
primitive =
|
729
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
728
730
|
check_argtype(arg_evaluated, SkmString, 'string', 'string-length')
|
729
731
|
integer(arg_evaluated.length)
|
730
732
|
end
|
@@ -733,7 +735,7 @@ module Skeem
|
|
733
735
|
end
|
734
736
|
|
735
737
|
def create_string2symbol(aRuntime)
|
736
|
-
primitive =
|
738
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
737
739
|
check_argtype(arg_evaluated, SkmString, 'string', 'string->symbol')
|
738
740
|
identifier(arg_evaluated)
|
739
741
|
end
|
@@ -742,7 +744,7 @@ module Skeem
|
|
742
744
|
end
|
743
745
|
|
744
746
|
def create_symbol2string(aRuntime)
|
745
|
-
primitive =
|
747
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
746
748
|
check_argtype(arg_evaluated, SkmIdentifier, 'symbol', 'symbol->string')
|
747
749
|
string(arg_evaluated)
|
748
750
|
end
|
@@ -751,7 +753,7 @@ module Skeem
|
|
751
753
|
end
|
752
754
|
|
753
755
|
def create_car(aRuntime)
|
754
|
-
primitive =
|
756
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
755
757
|
check_argtype(arg_evaluated, SkmPair, 'pair', 'car')
|
756
758
|
arg_evaluated.car
|
757
759
|
end
|
@@ -760,7 +762,7 @@ module Skeem
|
|
760
762
|
end
|
761
763
|
|
762
764
|
def create_cdr(aRuntime)
|
763
|
-
primitive =
|
765
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
764
766
|
check_argtype(arg_evaluated, SkmPair, 'pair', 'cdr')
|
765
767
|
arg_evaluated.cdr
|
766
768
|
end
|
@@ -769,15 +771,15 @@ module Skeem
|
|
769
771
|
end
|
770
772
|
|
771
773
|
def create_cons(aRuntime)
|
772
|
-
primitive =
|
774
|
+
primitive = lambda do |_runtime, obj1, obj2|
|
773
775
|
SkmPair.new(obj1, obj2)
|
774
776
|
end
|
775
777
|
|
776
778
|
define_primitive_proc(aRuntime, 'cons', binary, primitive)
|
777
779
|
end
|
778
|
-
|
780
|
+
|
779
781
|
def create_make_list(aRuntime)
|
780
|
-
primitive =
|
782
|
+
primitive = lambda do |_runtime, count_arg, arglist|
|
781
783
|
count = count_arg
|
782
784
|
check_argtype(count, SkmInteger, 'integer', 'make-list')
|
783
785
|
if arglist.empty?
|
@@ -789,11 +791,11 @@ module Skeem
|
|
789
791
|
SkmPair.create_from_a(arr)
|
790
792
|
end
|
791
793
|
|
792
|
-
define_primitive_proc(aRuntime, 'make-list', one_or_two, primitive)
|
794
|
+
define_primitive_proc(aRuntime, 'make-list', one_or_two, primitive)
|
793
795
|
end
|
794
796
|
|
795
797
|
def create_length(aRuntime)
|
796
|
-
primitive =
|
798
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
797
799
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'length')
|
798
800
|
integer(arg_evaluated.length)
|
799
801
|
end
|
@@ -802,7 +804,7 @@ module Skeem
|
|
802
804
|
end
|
803
805
|
|
804
806
|
def create_list2vector(aRuntime)
|
805
|
-
primitive =
|
807
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
806
808
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'list->vector')
|
807
809
|
vector(arg_evaluated.to_a)
|
808
810
|
end
|
@@ -818,19 +820,17 @@ module Skeem
|
|
818
820
|
else
|
819
821
|
but_last = arglist.take(arglist.length - 1)
|
820
822
|
check_arguments(but_last, [SkmPair, SkmEmptyList], 'list', 'append')
|
821
|
-
result = arglist.shift.klone
|
823
|
+
result = arglist.shift.klone # First list is taken
|
822
824
|
arglist.each do |arg|
|
823
825
|
case arg
|
824
826
|
when SkmPair
|
825
827
|
cloned = arg.klone
|
826
828
|
if result.kind_of?(SkmEmptyList)
|
827
829
|
result = cloned
|
830
|
+
elsif result.kind_of?(SkmEmptyList)
|
831
|
+
result = SkmPair.new(arg, SkmEmptyList.instance)
|
828
832
|
else
|
829
|
-
|
830
|
-
result = SkmPair.new(arg, SkmEmptyList.instance)
|
831
|
-
else
|
832
|
-
result.append_list(cloned)
|
833
|
-
end
|
833
|
+
result.append_list(cloned)
|
834
834
|
end
|
835
835
|
when SkmEmptyList
|
836
836
|
# Do nothing
|
@@ -849,9 +849,9 @@ module Skeem
|
|
849
849
|
|
850
850
|
def create_append(aRuntime)
|
851
851
|
# Arguments aren't evaluated yet!...
|
852
|
-
primitive =
|
852
|
+
primitive = lambda do |runtime, arglist|
|
853
853
|
if arglist.size > 1
|
854
|
-
arguments = evaluate_arguments(arglist,
|
854
|
+
arguments = evaluate_arguments(arglist, runtime)
|
855
855
|
else
|
856
856
|
arguments = arglist
|
857
857
|
end
|
@@ -863,13 +863,14 @@ module Skeem
|
|
863
863
|
end
|
864
864
|
|
865
865
|
def create_reverse(aRuntime)
|
866
|
-
primitive =
|
866
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
867
867
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'reverse')
|
868
868
|
if arg_evaluated == SkmEmptyList.instance
|
869
869
|
result = arg_evaluated
|
870
870
|
else
|
871
871
|
err_msg = 'reverse procedure requires a proper list as argument'
|
872
|
-
raise StandardError, err_msg
|
872
|
+
raise StandardError, err_msg unless arg_evaluated.proper?
|
873
|
+
|
873
874
|
elems_reversed = arg_evaluated.to_a.reverse
|
874
875
|
result = SkmPair.create_from_a(elems_reversed)
|
875
876
|
end
|
@@ -881,7 +882,7 @@ module Skeem
|
|
881
882
|
|
882
883
|
def create_setcar(aRuntime)
|
883
884
|
# Arguments aren't evaluated yet!...
|
884
|
-
primitive =
|
885
|
+
primitive = lambda do |runtime, pair_arg, obj_arg|
|
885
886
|
case pair_arg
|
886
887
|
when SkmPair
|
887
888
|
pair = pair_arg
|
@@ -906,7 +907,7 @@ module Skeem
|
|
906
907
|
|
907
908
|
def create_setcdr(aRuntime)
|
908
909
|
# Arguments aren't evaluated yet!...
|
909
|
-
primitive =
|
910
|
+
primitive = lambda do |runtime, pair_arg, obj_arg|
|
910
911
|
case pair_arg
|
911
912
|
when SkmPair
|
912
913
|
pair = pair_arg
|
@@ -930,21 +931,22 @@ module Skeem
|
|
930
931
|
end
|
931
932
|
|
932
933
|
def create_assq(aRuntime)
|
933
|
-
primitive =
|
934
|
+
primitive = lambda do |runtime, obj_arg, alist_arg|
|
934
935
|
assoc_list = alist_arg.evaluate(runtime)
|
935
936
|
check_assoc_list(assoc_list, 'assq')
|
936
937
|
obj = obj_arg.evaluate(runtime)
|
937
938
|
result = boolean(false)
|
938
939
|
unless assoc_list.empty?
|
939
940
|
pair = assoc_list
|
940
|
-
|
941
|
+
loop do
|
941
942
|
are_equal = core_eq?(pair.car.car, obj)
|
942
943
|
if are_equal.value
|
943
944
|
result = pair.car
|
944
945
|
break
|
945
946
|
end
|
946
947
|
pair = pair.cdr
|
947
|
-
|
948
|
+
break unless pair&.kind_of?(SkmPair)
|
949
|
+
end
|
948
950
|
end
|
949
951
|
|
950
952
|
result
|
@@ -953,19 +955,20 @@ module Skeem
|
|
953
955
|
end
|
954
956
|
|
955
957
|
def create_assv(aRuntime)
|
956
|
-
primitive =
|
958
|
+
primitive = lambda do |_runtime, obj, assoc_list|
|
957
959
|
check_assoc_list(assoc_list, 'assq')
|
958
960
|
result = boolean(false)
|
959
961
|
unless assoc_list.empty?
|
960
962
|
pair = assoc_list
|
961
|
-
|
963
|
+
loop do
|
962
964
|
are_equal = core_eqv?(pair.car.car, obj)
|
963
965
|
if are_equal.value
|
964
966
|
result = pair.car
|
965
967
|
break
|
966
968
|
end
|
967
969
|
pair = pair.cdr
|
968
|
-
|
970
|
+
break unless pair&.kind_of?(SkmPair)
|
971
|
+
end
|
969
972
|
end
|
970
973
|
|
971
974
|
result
|
@@ -978,15 +981,16 @@ module Skeem
|
|
978
981
|
|
979
982
|
unless alist.empty?
|
980
983
|
cell = SkmPair.new(integer(1), alist)
|
981
|
-
|
984
|
+
loop do
|
982
985
|
cell = cell.cdr
|
983
986
|
check_argtype(cell, SkmPair, 'association list', proc_name)
|
984
|
-
|
987
|
+
break unless cell.cdr.kind_of?(SkmPair)
|
988
|
+
end
|
985
989
|
end
|
986
990
|
end
|
987
991
|
|
988
992
|
def create_list_copy(aRuntime)
|
989
|
-
primitive =
|
993
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
990
994
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'list-copy')
|
991
995
|
arg_evaluated.klone # Previously: arg.klone
|
992
996
|
end
|
@@ -995,7 +999,7 @@ module Skeem
|
|
995
999
|
end
|
996
1000
|
|
997
1001
|
def create_vector(aRuntime)
|
998
|
-
primitive =
|
1002
|
+
primitive = lambda do |_runtime, elements|
|
999
1003
|
vector(elements)
|
1000
1004
|
end
|
1001
1005
|
|
@@ -1003,7 +1007,7 @@ module Skeem
|
|
1003
1007
|
end
|
1004
1008
|
|
1005
1009
|
def create_vector_length(aRuntime)
|
1006
|
-
primitive =
|
1010
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1007
1011
|
check_argtype(arg_evaluated, SkmVector, 'vector', 'vector-length')
|
1008
1012
|
integer(arg_evaluated.length)
|
1009
1013
|
end
|
@@ -1012,7 +1016,7 @@ module Skeem
|
|
1012
1016
|
end
|
1013
1017
|
|
1014
1018
|
def create_make_vector(aRuntime)
|
1015
|
-
primitive =
|
1019
|
+
primitive = lambda do |runtime, count_arg, arglist|
|
1016
1020
|
count = count_arg.evaluate(runtime)
|
1017
1021
|
check_argtype(count, SkmInteger, 'integer', 'make_vector')
|
1018
1022
|
if arglist.empty?
|
@@ -1028,8 +1032,8 @@ module Skeem
|
|
1028
1032
|
end
|
1029
1033
|
|
1030
1034
|
def create_vector_ref(aRuntime)
|
1031
|
-
|
1032
|
-
|
1035
|
+
# argument 1: a vector, argument 2: an index(integer)
|
1036
|
+
primitive = lambda do |_runtime, vector, index|
|
1033
1037
|
check_argtype(vector, SkmVector, 'vector', 'vector-ref')
|
1034
1038
|
check_argtype(index, SkmInteger, 'integer', 'vector-ref')
|
1035
1039
|
# TODO: index checking
|
@@ -1039,10 +1043,10 @@ module Skeem
|
|
1039
1043
|
|
1040
1044
|
define_primitive_proc(aRuntime, 'vector-ref', binary, primitive)
|
1041
1045
|
end
|
1042
|
-
|
1046
|
+
|
1043
1047
|
def create_vector_set(aRuntime)
|
1044
|
-
|
1045
|
-
|
1048
|
+
# Arguments aren't evaluated yet!...
|
1049
|
+
primitive = lambda do |runtime, vector, k, object|
|
1046
1050
|
index = k.evaluate(runtime)
|
1047
1051
|
check_argtype(vector, SkmVector, 'vector', 'vector-set!')
|
1048
1052
|
check_argtype(index, SkmInteger, 'integer', 'vector-set!')
|
@@ -1050,12 +1054,12 @@ module Skeem
|
|
1050
1054
|
vector.members[index.value] = object
|
1051
1055
|
vector
|
1052
1056
|
end
|
1053
|
-
|
1057
|
+
|
1054
1058
|
define_primitive_proc(aRuntime, 'vector-set!', ternary, primitive)
|
1055
1059
|
end
|
1056
1060
|
|
1057
1061
|
def create_vector2list(aRuntime)
|
1058
|
-
primitive =
|
1062
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1059
1063
|
check_argtype(arg_evaluated, SkmVector, 'vector', 'vector->list')
|
1060
1064
|
SkmPair.create_from_a(arg_evaluated.members)
|
1061
1065
|
end
|
@@ -1064,7 +1068,7 @@ module Skeem
|
|
1064
1068
|
end
|
1065
1069
|
|
1066
1070
|
def create_apply(aRuntime)
|
1067
|
-
primitive =
|
1071
|
+
primitive = lambda do |runtime, proc_arg, arglist|
|
1068
1072
|
if arglist.empty?
|
1069
1073
|
result = SkmEmptyList.instance
|
1070
1074
|
else
|
@@ -1072,18 +1076,19 @@ module Skeem
|
|
1072
1076
|
invoke = ProcedureCall.new(nil, proc_arg, single_list.to_a)
|
1073
1077
|
result = invoke.evaluate(runtime)
|
1074
1078
|
end
|
1079
|
+
result
|
1075
1080
|
end
|
1076
1081
|
|
1077
1082
|
define_primitive_proc(aRuntime, 'apply', one_or_more, primitive)
|
1078
1083
|
end
|
1079
1084
|
|
1080
1085
|
def create_map(aRuntime)
|
1081
|
-
primitive =
|
1086
|
+
primitive = lambda do |runtime, proc_arg, arglist|
|
1082
1087
|
if arglist.empty?
|
1083
1088
|
result = SkmEmptyList.instance
|
1084
1089
|
else
|
1085
1090
|
curr_cells = arglist
|
1086
|
-
arity = curr_cells.size
|
1091
|
+
# arity = curr_cells.size
|
1087
1092
|
initial_result = nil
|
1088
1093
|
curr_result = nil
|
1089
1094
|
loop do
|
@@ -1099,7 +1104,7 @@ module Skeem
|
|
1099
1104
|
curr_result = new_result
|
1100
1105
|
|
1101
1106
|
curr_cells.map!(&:cdr)
|
1102
|
-
break if curr_cells.find { |cdr_entry| !
|
1107
|
+
break if curr_cells.find { |cdr_entry| !cdr_entry.kind_of?(SkmPair) }
|
1103
1108
|
end
|
1104
1109
|
|
1105
1110
|
result = initial_result
|
@@ -1110,19 +1115,27 @@ module Skeem
|
|
1110
1115
|
|
1111
1116
|
define_primitive_proc(aRuntime, 'map', one_or_more, primitive)
|
1112
1117
|
end
|
1113
|
-
|
1118
|
+
|
1114
1119
|
def create_display(aRuntime)
|
1115
|
-
primitive =
|
1120
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1116
1121
|
# @TODO: make output stream configurable
|
1117
1122
|
print arg_evaluated.value.to_s
|
1118
1123
|
SkmUndefined.instance
|
1119
1124
|
end
|
1120
|
-
|
1121
|
-
define_primitive_proc(aRuntime, 'display', unary, primitive)
|
1125
|
+
|
1126
|
+
define_primitive_proc(aRuntime, 'display', unary, primitive)
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
def create_error(aRuntime)
|
1130
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1131
|
+
raise SkmError, arg_evaluated.value
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
define_primitive_proc(aRuntime, 'error', unary, primitive)
|
1122
1135
|
end
|
1123
1136
|
|
1124
1137
|
def create_test_assert(aRuntime)
|
1125
|
-
primitive =
|
1138
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1126
1139
|
if arg_evaluated.boolean? && arg_evaluated.value == false
|
1127
1140
|
assert_call = aRuntime.caller
|
1128
1141
|
pos = assert_call.call_site
|
@@ -1141,7 +1154,7 @@ module Skeem
|
|
1141
1154
|
# DON'T USE IT
|
1142
1155
|
# Non-standard procedure reserved for internal testing/debugging purposes.
|
1143
1156
|
def create_debug(aRuntime)
|
1144
|
-
primitive =
|
1157
|
+
primitive = lambda do |_runtime|
|
1145
1158
|
require 'debug'
|
1146
1159
|
end
|
1147
1160
|
|
@@ -1151,7 +1164,7 @@ module Skeem
|
|
1151
1164
|
# DON'T USE IT
|
1152
1165
|
# Non-standard procedure reserved for internal testing/debugging purposes.
|
1153
1166
|
def create_inspect(aRuntime)
|
1154
|
-
primitive =
|
1167
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1155
1168
|
$stderr.puts 'INSPECT>' + arg_evaluated.inspect
|
1156
1169
|
Skeem::SkmUndefined.instance
|
1157
1170
|
end
|
@@ -1160,7 +1173,7 @@ module Skeem
|
|
1160
1173
|
|
1161
1174
|
def create_object_predicate(aRuntime, predicate_name, msg_name = nil)
|
1162
1175
|
msg_name = predicate_name if msg_name.nil?
|
1163
|
-
primitive =
|
1176
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1164
1177
|
to_datum(arg_evaluated.send(msg_name))
|
1165
1178
|
end
|
1166
1179
|
|
@@ -1234,4 +1247,4 @@ module Skeem
|
|
1234
1247
|
end
|
1235
1248
|
end # module
|
1236
1249
|
end # module
|
1237
|
-
end # module
|
1250
|
+
end # module
|