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