skeem 0.2.15 → 0.2.19
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 +451 -195
- data/.travis.yml +27 -0
- data/CHANGELOG.md +26 -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/datum_dsl.rb +40 -30
- data/lib/skeem/element_visitor.rb +5 -2
- data/lib/skeem/grammar.rb +77 -54
- data/lib/skeem/interpreter.rb +9 -7
- data/lib/skeem/parser.rb +6 -4
- data/lib/skeem/primitive/primitive_builder.rb +130 -122
- data/lib/skeem/primitive/primitive_procedure.rb +23 -25
- data/lib/skeem/runtime.rb +17 -15
- data/lib/skeem/s_expr_builder.rb +39 -147
- data/lib/skeem/s_expr_nodes.rb +147 -132
- data/lib/skeem/skeem_exception.rb +1 -0
- data/lib/skeem/skm_binding.rb +9 -11
- data/lib/skeem/skm_compound_datum.rb +9 -6
- data/lib/skeem/skm_element.rb +15 -13
- 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 +26 -18
- data/lib/skeem/skm_procedure_exec.rb +11 -6
- data/lib/skeem/skm_simple_datum.rb +23 -20
- data/lib/skeem/skm_unary_expression.rb +34 -37
- data/lib/skeem/tokenizer.rb +40 -30
- data/lib/skeem/version.rb +3 -1
- data/lib/skeem.rb +2 -0
- data/skeem.gemspec +7 -5
- data/spec/skeem/add4.skm +4 -0
- data/spec/skeem/datum_dsl_spec.rb +13 -12
- data/spec/skeem/element_visitor_spec.rb +14 -10
- data/spec/skeem/interpreter_spec.rb +76 -46
- data/spec/skeem/lambda_spec.rb +13 -11
- data/spec/skeem/parser_spec.rb +23 -19
- data/spec/skeem/primitive/primitive_builder_spec.rb +55 -46
- data/spec/skeem/primitive/primitive_procedure_spec.rb +14 -12
- data/spec/skeem/runtime_spec.rb +20 -18
- data/spec/skeem/s_expr_nodes_spec.rb +8 -6
- data/spec/skeem/skm_compound_datum_spec.rb +12 -10
- 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 +9 -8
- 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 +54 -43
- data/spec/skeem_spec.rb +2 -0
- data/spec/spec_helper.rb +15 -10
- metadata +13 -9
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,16 +22,16 @@ 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
|
27
29
|
|
28
|
-
def parse(source,
|
30
|
+
def parse(source, _mode = nil)
|
29
31
|
@parser ||= Parser.new
|
30
32
|
@ptree = parser.parse(source)
|
31
|
-
# $stderr.puts @ptree.root.inspect if
|
32
|
-
# require 'debug' unless
|
33
|
+
# $stderr.puts @ptree.root.inspect if _mode.nil?
|
34
|
+
# require 'debug' unless _mode.nil?
|
33
35
|
end
|
34
36
|
|
35
37
|
def run(source, mode = nil)
|
@@ -43,7 +45,7 @@ module Skeem
|
|
43
45
|
end
|
44
46
|
|
45
47
|
def add_standard(_runtime)
|
46
|
-
std_pathname = File.dirname(__FILE__)
|
48
|
+
std_pathname = "#{File.dirname(__FILE__)}/standard/base.skm"
|
47
49
|
load_lib(std_pathname)
|
48
50
|
end
|
49
51
|
|
@@ -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,26 @@ 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
|
-
# Ugly: Ruby version dependency: Rubies older than 2.4 have class Fixnum instead of Integer
|
235
|
-
int_class = (RUBY_VERSION[0..2] < "2.4") ? Fixnum : Integer
|
236
|
-
|
237
237
|
arglist.each do |elem|
|
238
238
|
elem_value = elem.value
|
239
239
|
case [raw_result.class, elem_value.class]
|
240
|
-
when [
|
240
|
+
when [Integer, Integer]
|
241
241
|
if raw_result.modulo(elem_value).zero?
|
242
|
-
raw_result
|
242
|
+
raw_result /= elem_value
|
243
243
|
else
|
244
244
|
raw_result = Rational(raw_result, elem_value)
|
245
245
|
end
|
246
246
|
|
247
|
-
when [
|
248
|
-
raw_result
|
247
|
+
when [Integer, Rational]
|
248
|
+
raw_result *= reciprocal(elem_value)
|
249
249
|
|
250
250
|
when [Rational, Rational]
|
251
|
-
raw_result
|
251
|
+
raw_result *= reciprocal(elem_value)
|
252
252
|
else
|
253
253
|
raw_result = raw_result.to_f
|
254
254
|
raw_result /= elem_value
|
@@ -262,8 +262,8 @@ module Skeem
|
|
262
262
|
end
|
263
263
|
|
264
264
|
def create_floor_slash(aRuntime)
|
265
|
-
primitive =
|
266
|
-
(quotient, modulus) =
|
265
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
266
|
+
(quotient, modulus) = operand1.value.divmod(operand2.value)
|
267
267
|
SkmPair.new(to_datum(quotient), to_datum(modulus)) # improper list!
|
268
268
|
end
|
269
269
|
|
@@ -271,10 +271,10 @@ module Skeem
|
|
271
271
|
end
|
272
272
|
|
273
273
|
def create_truncate_slash(aRuntime)
|
274
|
-
primitive =
|
275
|
-
modulo_ =
|
276
|
-
modulo_ += 1 if modulo_
|
277
|
-
remainder_ =
|
274
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
275
|
+
modulo_ = operand1.value / operand2.value
|
276
|
+
modulo_ += 1 if modulo_.negative?
|
277
|
+
remainder_ = operand1.value.remainder(operand2.value)
|
278
278
|
SkmPair.new(to_datum(modulo_), to_datum(remainder_)) # improper list!
|
279
279
|
end
|
280
280
|
|
@@ -282,7 +282,7 @@ module Skeem
|
|
282
282
|
end
|
283
283
|
|
284
284
|
def create_gcd(aRuntime)
|
285
|
-
primitive =
|
285
|
+
primitive = lambda do |_runtime, arglist|
|
286
286
|
if arglist.empty?
|
287
287
|
integer(0)
|
288
288
|
else
|
@@ -301,7 +301,7 @@ module Skeem
|
|
301
301
|
end
|
302
302
|
|
303
303
|
def create_lcm(aRuntime)
|
304
|
-
primitive =
|
304
|
+
primitive = lambda do |_runtime, arglist|
|
305
305
|
if arglist.empty?
|
306
306
|
integer(1)
|
307
307
|
else
|
@@ -315,7 +315,7 @@ module Skeem
|
|
315
315
|
end
|
316
316
|
|
317
317
|
def create_numerator(aRuntime)
|
318
|
-
primitive =
|
318
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
319
319
|
case arg_evaluated
|
320
320
|
when SkmInteger
|
321
321
|
result = arg_evaluated
|
@@ -329,7 +329,7 @@ module Skeem
|
|
329
329
|
end
|
330
330
|
|
331
331
|
def create_denominator(aRuntime)
|
332
|
-
primitive =
|
332
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
333
333
|
case arg_evaluated
|
334
334
|
when SkmInteger
|
335
335
|
result = 1
|
@@ -343,7 +343,7 @@ module Skeem
|
|
343
343
|
end
|
344
344
|
|
345
345
|
def create_floor(aRuntime)
|
346
|
-
primitive =
|
346
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
347
347
|
result = arg_evaluated.value.floor
|
348
348
|
integer(result)
|
349
349
|
end
|
@@ -352,7 +352,7 @@ module Skeem
|
|
352
352
|
end
|
353
353
|
|
354
354
|
def create_ceiling(aRuntime)
|
355
|
-
primitive =
|
355
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
356
356
|
result = arg_evaluated.value.ceil
|
357
357
|
integer(result)
|
358
358
|
end
|
@@ -361,7 +361,7 @@ module Skeem
|
|
361
361
|
end
|
362
362
|
|
363
363
|
def create_round(aRuntime)
|
364
|
-
primitive =
|
364
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
365
365
|
result = arg_evaluated.value.round
|
366
366
|
integer(result)
|
367
367
|
end
|
@@ -375,8 +375,8 @@ module Skeem
|
|
375
375
|
end
|
376
376
|
|
377
377
|
def create_eqv?(aRuntime)
|
378
|
-
primitive =
|
379
|
-
core_eqv?(
|
378
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
379
|
+
core_eqv?(operand1, operand2)
|
380
380
|
end
|
381
381
|
|
382
382
|
define_primitive_proc(aRuntime, 'eqv?', binary, primitive)
|
@@ -388,7 +388,7 @@ module Skeem
|
|
388
388
|
end
|
389
389
|
|
390
390
|
def create_eq?(aRuntime)
|
391
|
-
primitive =
|
391
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
392
392
|
core_eq?(operand1, operand2)
|
393
393
|
end
|
394
394
|
|
@@ -396,8 +396,8 @@ module Skeem
|
|
396
396
|
end
|
397
397
|
|
398
398
|
def create_equal?(aRuntime)
|
399
|
-
primitive =
|
400
|
-
raw_result =
|
399
|
+
primitive = lambda do |_runtime, operand1, operand2|
|
400
|
+
raw_result = operand1.skm_equal?(operand2)
|
401
401
|
boolean(raw_result)
|
402
402
|
end
|
403
403
|
|
@@ -405,7 +405,7 @@ module Skeem
|
|
405
405
|
end
|
406
406
|
|
407
407
|
def create_equal(aRuntime)
|
408
|
-
primitive =
|
408
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
409
409
|
if arglist.empty?
|
410
410
|
boolean(true)
|
411
411
|
else
|
@@ -419,11 +419,11 @@ module Skeem
|
|
419
419
|
end
|
420
420
|
|
421
421
|
def create_lt(aRuntime)
|
422
|
-
primitive =
|
422
|
+
primitive = lambda do |runtime, first_operand, arglist|
|
423
423
|
if arglist.empty?
|
424
424
|
result = false
|
425
425
|
else
|
426
|
-
result = primitive_comparison(:<,
|
426
|
+
result = primitive_comparison(:<, runtime, first_operand, arglist)
|
427
427
|
end
|
428
428
|
boolean(result)
|
429
429
|
end
|
@@ -432,11 +432,11 @@ module Skeem
|
|
432
432
|
end
|
433
433
|
|
434
434
|
def create_gt(aRuntime)
|
435
|
-
primitive =
|
435
|
+
primitive = lambda do |runtime, first_operand, arglist|
|
436
436
|
if arglist.empty?
|
437
437
|
result = false
|
438
438
|
else
|
439
|
-
result = primitive_comparison(:>,
|
439
|
+
result = primitive_comparison(:>, runtime, first_operand, arglist)
|
440
440
|
end
|
441
441
|
boolean(result)
|
442
442
|
end
|
@@ -445,11 +445,11 @@ module Skeem
|
|
445
445
|
end
|
446
446
|
|
447
447
|
def create_lte(aRuntime)
|
448
|
-
primitive =
|
448
|
+
primitive = lambda do |runtime, first_operand, arglist|
|
449
449
|
if arglist.empty?
|
450
450
|
result = true
|
451
451
|
else
|
452
|
-
result = primitive_comparison(:<=,
|
452
|
+
result = primitive_comparison(:<=, runtime, first_operand, arglist)
|
453
453
|
end
|
454
454
|
boolean(result)
|
455
455
|
end
|
@@ -458,11 +458,11 @@ module Skeem
|
|
458
458
|
end
|
459
459
|
|
460
460
|
def create_gte(aRuntime)
|
461
|
-
primitive =
|
461
|
+
primitive = lambda do |runtime, first_operand, arglist|
|
462
462
|
if arglist.empty?
|
463
463
|
result = true
|
464
464
|
else
|
465
|
-
result = primitive_comparison(:>=,
|
465
|
+
result = primitive_comparison(:>=, runtime, first_operand, arglist)
|
466
466
|
end
|
467
467
|
boolean(result)
|
468
468
|
end
|
@@ -481,7 +481,7 @@ module Skeem
|
|
481
481
|
end
|
482
482
|
|
483
483
|
def create_max(aRuntime)
|
484
|
-
primitive =
|
484
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
485
485
|
if arglist.empty?
|
486
486
|
result = first_operand
|
487
487
|
else
|
@@ -499,7 +499,7 @@ module Skeem
|
|
499
499
|
end
|
500
500
|
|
501
501
|
def create_min(aRuntime)
|
502
|
-
primitive =
|
502
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
503
503
|
if arglist.empty?
|
504
504
|
result = first_operand
|
505
505
|
else
|
@@ -518,7 +518,7 @@ module Skeem
|
|
518
518
|
|
519
519
|
def create_number2string(aRuntime)
|
520
520
|
# TODO: add support for radix argument
|
521
|
-
primitive =
|
521
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
522
522
|
check_argtype(arg_evaluated, SkmNumber, 'number', 'number->string')
|
523
523
|
string(arg_evaluated.value)
|
524
524
|
end
|
@@ -529,7 +529,7 @@ module Skeem
|
|
529
529
|
def create_and(aRuntime)
|
530
530
|
# arglist should be a Ruby Array
|
531
531
|
# Arguments aren't evaluated yet!...
|
532
|
-
primitive =
|
532
|
+
primitive = lambda do |runtime, arglist|
|
533
533
|
if arglist.empty?
|
534
534
|
boolean(true) # in conformance with 4.2.1
|
535
535
|
else
|
@@ -537,7 +537,7 @@ module Skeem
|
|
537
537
|
last_result = nil
|
538
538
|
# $stderr.puts arglist.inspect
|
539
539
|
arglist.each do |raw_arg|
|
540
|
-
argument = raw_arg.evaluate(
|
540
|
+
argument = raw_arg.evaluate(runtime)
|
541
541
|
last_result = argument
|
542
542
|
raw_result &&= !(argument.boolean? && !argument.value)
|
543
543
|
break unless raw_result # stop here, a false was found...
|
@@ -555,14 +555,14 @@ module Skeem
|
|
555
555
|
def create_or(aRuntime)
|
556
556
|
# arglist should be a Ruby Array
|
557
557
|
# Arguments aren't evaluated yet!...
|
558
|
-
primitive =
|
558
|
+
primitive = lambda do |runtime, arglist|
|
559
559
|
if arglist.empty?
|
560
560
|
boolean(false) # in conformance with 4.2.1
|
561
561
|
else
|
562
562
|
raw_result = false
|
563
563
|
last_result = nil
|
564
564
|
arglist.each do |raw_arg|
|
565
|
-
argument = raw_arg.evaluate(
|
565
|
+
argument = raw_arg.evaluate(runtime)
|
566
566
|
last_result = argument
|
567
567
|
raw_result ||= (!argument.boolean? || argument.value)
|
568
568
|
break if raw_result # stop here, a true was found...
|
@@ -602,7 +602,7 @@ module Skeem
|
|
602
602
|
end
|
603
603
|
|
604
604
|
def create_boolean_equal(aRuntime)
|
605
|
-
primitive =
|
605
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
606
606
|
compare_all(first_operand, arglist, :==)
|
607
607
|
end
|
608
608
|
|
@@ -610,7 +610,7 @@ module Skeem
|
|
610
610
|
end
|
611
611
|
|
612
612
|
def create_char2int(aRuntime)
|
613
|
-
primitive =
|
613
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
614
614
|
check_argtype(arg_evaluated, SkmChar, 'character', 'char->integer')
|
615
615
|
integer(arg_evaluated.value.ord)
|
616
616
|
end
|
@@ -619,7 +619,7 @@ module Skeem
|
|
619
619
|
end
|
620
620
|
|
621
621
|
def create_int2char(aRuntime)
|
622
|
-
primitive =
|
622
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
623
623
|
check_argtype(arg_evaluated, SkmInteger, 'integer', 'integer->char')
|
624
624
|
char(arg_evaluated.value.ord)
|
625
625
|
end
|
@@ -628,7 +628,7 @@ module Skeem
|
|
628
628
|
end
|
629
629
|
|
630
630
|
def create_char_equal(aRuntime)
|
631
|
-
primitive =
|
631
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
632
632
|
compare_all(first_operand, arglist, :==)
|
633
633
|
end
|
634
634
|
|
@@ -636,7 +636,7 @@ module Skeem
|
|
636
636
|
end
|
637
637
|
|
638
638
|
def create_char_lt(aRuntime)
|
639
|
-
primitive =
|
639
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
640
640
|
compare_all(first_operand, arglist, :<)
|
641
641
|
end
|
642
642
|
|
@@ -644,7 +644,7 @@ module Skeem
|
|
644
644
|
end
|
645
645
|
|
646
646
|
def create_char_gt(aRuntime)
|
647
|
-
primitive =
|
647
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
648
648
|
compare_all(first_operand, arglist, :>)
|
649
649
|
end
|
650
650
|
|
@@ -652,7 +652,7 @@ module Skeem
|
|
652
652
|
end
|
653
653
|
|
654
654
|
def create_char_lte(aRuntime)
|
655
|
-
primitive =
|
655
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
656
656
|
compare_all(first_operand, arglist, :<=)
|
657
657
|
end
|
658
658
|
|
@@ -660,16 +660,15 @@ module Skeem
|
|
660
660
|
end
|
661
661
|
|
662
662
|
def create_char_gte(aRuntime)
|
663
|
-
primitive =
|
663
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
664
664
|
compare_all(first_operand, arglist, :>=)
|
665
665
|
end
|
666
666
|
|
667
667
|
define_primitive_proc(aRuntime, 'char>=?', one_or_more, primitive)
|
668
668
|
end
|
669
669
|
|
670
|
-
|
671
670
|
def create_make_string(aRuntime)
|
672
|
-
primitive =
|
671
|
+
primitive = lambda do |_runtime, count_arg, arglist|
|
673
672
|
count = count_arg
|
674
673
|
check_argtype(count, SkmInteger, 'integer', 'make-string')
|
675
674
|
if arglist.empty?
|
@@ -685,11 +684,11 @@ module Skeem
|
|
685
684
|
end
|
686
685
|
|
687
686
|
def create_string_string(aRuntime)
|
688
|
-
primitive =
|
687
|
+
primitive = lambda do |_runtime, arglist|
|
689
688
|
if arglist.empty?
|
690
689
|
value = ''
|
691
690
|
else
|
692
|
-
value = arglist.reduce('') do |interim, some_char|
|
691
|
+
value = arglist.reduce(+'') do |interim, some_char|
|
693
692
|
check_argtype(some_char, SkmChar, 'character', 'string')
|
694
693
|
interim << some_char.value
|
695
694
|
end
|
@@ -702,7 +701,7 @@ module Skeem
|
|
702
701
|
end
|
703
702
|
|
704
703
|
def create_string_equal(aRuntime)
|
705
|
-
primitive =
|
704
|
+
primitive = lambda do |_runtime, first_operand, arglist|
|
706
705
|
all_same?(first_operand, arglist)
|
707
706
|
end
|
708
707
|
|
@@ -710,11 +709,11 @@ module Skeem
|
|
710
709
|
end
|
711
710
|
|
712
711
|
def create_string_append(aRuntime)
|
713
|
-
primitive =
|
712
|
+
primitive = lambda do |_runtime, arglist|
|
714
713
|
if arglist.empty?
|
715
714
|
value = ''
|
716
715
|
else
|
717
|
-
value = arglist.reduce('') { |interim, substr| interim << substr.value }
|
716
|
+
value = arglist.reduce(+'') { |interim, substr| interim << substr.value }
|
718
717
|
end
|
719
718
|
|
720
719
|
string(value)
|
@@ -724,7 +723,7 @@ module Skeem
|
|
724
723
|
end
|
725
724
|
|
726
725
|
def create_string_length(aRuntime)
|
727
|
-
primitive =
|
726
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
728
727
|
check_argtype(arg_evaluated, SkmString, 'string', 'string-length')
|
729
728
|
integer(arg_evaluated.length)
|
730
729
|
end
|
@@ -733,7 +732,7 @@ module Skeem
|
|
733
732
|
end
|
734
733
|
|
735
734
|
def create_string2symbol(aRuntime)
|
736
|
-
primitive =
|
735
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
737
736
|
check_argtype(arg_evaluated, SkmString, 'string', 'string->symbol')
|
738
737
|
identifier(arg_evaluated)
|
739
738
|
end
|
@@ -742,7 +741,7 @@ module Skeem
|
|
742
741
|
end
|
743
742
|
|
744
743
|
def create_symbol2string(aRuntime)
|
745
|
-
primitive =
|
744
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
746
745
|
check_argtype(arg_evaluated, SkmIdentifier, 'symbol', 'symbol->string')
|
747
746
|
string(arg_evaluated)
|
748
747
|
end
|
@@ -751,7 +750,7 @@ module Skeem
|
|
751
750
|
end
|
752
751
|
|
753
752
|
def create_car(aRuntime)
|
754
|
-
primitive =
|
753
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
755
754
|
check_argtype(arg_evaluated, SkmPair, 'pair', 'car')
|
756
755
|
arg_evaluated.car
|
757
756
|
end
|
@@ -760,7 +759,7 @@ module Skeem
|
|
760
759
|
end
|
761
760
|
|
762
761
|
def create_cdr(aRuntime)
|
763
|
-
primitive =
|
762
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
764
763
|
check_argtype(arg_evaluated, SkmPair, 'pair', 'cdr')
|
765
764
|
arg_evaluated.cdr
|
766
765
|
end
|
@@ -769,15 +768,15 @@ module Skeem
|
|
769
768
|
end
|
770
769
|
|
771
770
|
def create_cons(aRuntime)
|
772
|
-
primitive =
|
771
|
+
primitive = lambda do |_runtime, obj1, obj2|
|
773
772
|
SkmPair.new(obj1, obj2)
|
774
773
|
end
|
775
774
|
|
776
775
|
define_primitive_proc(aRuntime, 'cons', binary, primitive)
|
777
776
|
end
|
778
|
-
|
777
|
+
|
779
778
|
def create_make_list(aRuntime)
|
780
|
-
primitive =
|
779
|
+
primitive = lambda do |_runtime, count_arg, arglist|
|
781
780
|
count = count_arg
|
782
781
|
check_argtype(count, SkmInteger, 'integer', 'make-list')
|
783
782
|
if arglist.empty?
|
@@ -789,11 +788,11 @@ module Skeem
|
|
789
788
|
SkmPair.create_from_a(arr)
|
790
789
|
end
|
791
790
|
|
792
|
-
define_primitive_proc(aRuntime, 'make-list', one_or_two, primitive)
|
791
|
+
define_primitive_proc(aRuntime, 'make-list', one_or_two, primitive)
|
793
792
|
end
|
794
793
|
|
795
794
|
def create_length(aRuntime)
|
796
|
-
primitive =
|
795
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
797
796
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'length')
|
798
797
|
integer(arg_evaluated.length)
|
799
798
|
end
|
@@ -802,7 +801,7 @@ module Skeem
|
|
802
801
|
end
|
803
802
|
|
804
803
|
def create_list2vector(aRuntime)
|
805
|
-
primitive =
|
804
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
806
805
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'list->vector')
|
807
806
|
vector(arg_evaluated.to_a)
|
808
807
|
end
|
@@ -818,7 +817,7 @@ module Skeem
|
|
818
817
|
else
|
819
818
|
but_last = arglist.take(arglist.length - 1)
|
820
819
|
check_arguments(but_last, [SkmPair, SkmEmptyList], 'list', 'append')
|
821
|
-
result = arglist.shift.klone
|
820
|
+
result = arglist.shift.klone # First list is taken
|
822
821
|
arglist.each do |arg|
|
823
822
|
case arg
|
824
823
|
when SkmPair
|
@@ -826,11 +825,7 @@ module Skeem
|
|
826
825
|
if result.kind_of?(SkmEmptyList)
|
827
826
|
result = cloned
|
828
827
|
else
|
829
|
-
|
830
|
-
result = SkmPair.new(arg, SkmEmptyList.instance)
|
831
|
-
else
|
832
|
-
result.append_list(cloned)
|
833
|
-
end
|
828
|
+
result.append_list(cloned)
|
834
829
|
end
|
835
830
|
when SkmEmptyList
|
836
831
|
# Do nothing
|
@@ -849,9 +844,9 @@ module Skeem
|
|
849
844
|
|
850
845
|
def create_append(aRuntime)
|
851
846
|
# Arguments aren't evaluated yet!...
|
852
|
-
primitive =
|
847
|
+
primitive = lambda do |runtime, arglist|
|
853
848
|
if arglist.size > 1
|
854
|
-
arguments = evaluate_arguments(arglist,
|
849
|
+
arguments = evaluate_arguments(arglist, runtime)
|
855
850
|
else
|
856
851
|
arguments = arglist
|
857
852
|
end
|
@@ -863,13 +858,14 @@ module Skeem
|
|
863
858
|
end
|
864
859
|
|
865
860
|
def create_reverse(aRuntime)
|
866
|
-
primitive =
|
861
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
867
862
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'reverse')
|
868
863
|
if arg_evaluated == SkmEmptyList.instance
|
869
864
|
result = arg_evaluated
|
870
865
|
else
|
871
866
|
err_msg = 'reverse procedure requires a proper list as argument'
|
872
|
-
raise StandardError, err_msg
|
867
|
+
raise StandardError, err_msg unless arg_evaluated.proper?
|
868
|
+
|
873
869
|
elems_reversed = arg_evaluated.to_a.reverse
|
874
870
|
result = SkmPair.create_from_a(elems_reversed)
|
875
871
|
end
|
@@ -881,7 +877,7 @@ module Skeem
|
|
881
877
|
|
882
878
|
def create_setcar(aRuntime)
|
883
879
|
# Arguments aren't evaluated yet!...
|
884
|
-
primitive =
|
880
|
+
primitive = lambda do |runtime, pair_arg, obj_arg|
|
885
881
|
case pair_arg
|
886
882
|
when SkmPair
|
887
883
|
pair = pair_arg
|
@@ -906,7 +902,7 @@ module Skeem
|
|
906
902
|
|
907
903
|
def create_setcdr(aRuntime)
|
908
904
|
# Arguments aren't evaluated yet!...
|
909
|
-
primitive =
|
905
|
+
primitive = lambda do |runtime, pair_arg, obj_arg|
|
910
906
|
case pair_arg
|
911
907
|
when SkmPair
|
912
908
|
pair = pair_arg
|
@@ -930,21 +926,22 @@ module Skeem
|
|
930
926
|
end
|
931
927
|
|
932
928
|
def create_assq(aRuntime)
|
933
|
-
primitive =
|
929
|
+
primitive = lambda do |runtime, obj_arg, alist_arg|
|
934
930
|
assoc_list = alist_arg.evaluate(runtime)
|
935
931
|
check_assoc_list(assoc_list, 'assq')
|
936
932
|
obj = obj_arg.evaluate(runtime)
|
937
933
|
result = boolean(false)
|
938
934
|
unless assoc_list.empty?
|
939
935
|
pair = assoc_list
|
940
|
-
|
936
|
+
loop do
|
941
937
|
are_equal = core_eq?(pair.car.car, obj)
|
942
938
|
if are_equal.value
|
943
939
|
result = pair.car
|
944
940
|
break
|
945
941
|
end
|
946
942
|
pair = pair.cdr
|
947
|
-
|
943
|
+
break unless pair.kind_of?(SkmPair)
|
944
|
+
end
|
948
945
|
end
|
949
946
|
|
950
947
|
result
|
@@ -953,19 +950,20 @@ module Skeem
|
|
953
950
|
end
|
954
951
|
|
955
952
|
def create_assv(aRuntime)
|
956
|
-
primitive =
|
953
|
+
primitive = lambda do |_runtime, obj, assoc_list|
|
957
954
|
check_assoc_list(assoc_list, 'assq')
|
958
955
|
result = boolean(false)
|
959
956
|
unless assoc_list.empty?
|
960
957
|
pair = assoc_list
|
961
|
-
|
958
|
+
loop do
|
962
959
|
are_equal = core_eqv?(pair.car.car, obj)
|
963
960
|
if are_equal.value
|
964
961
|
result = pair.car
|
965
962
|
break
|
966
963
|
end
|
967
964
|
pair = pair.cdr
|
968
|
-
|
965
|
+
break unless pair.kind_of?(SkmPair)
|
966
|
+
end
|
969
967
|
end
|
970
968
|
|
971
969
|
result
|
@@ -978,15 +976,16 @@ module Skeem
|
|
978
976
|
|
979
977
|
unless alist.empty?
|
980
978
|
cell = SkmPair.new(integer(1), alist)
|
981
|
-
|
979
|
+
loop do
|
982
980
|
cell = cell.cdr
|
983
981
|
check_argtype(cell, SkmPair, 'association list', proc_name)
|
984
|
-
|
982
|
+
break unless cell.cdr.kind_of?(SkmPair)
|
983
|
+
end
|
985
984
|
end
|
986
985
|
end
|
987
986
|
|
988
987
|
def create_list_copy(aRuntime)
|
989
|
-
primitive =
|
988
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
990
989
|
check_argtype(arg_evaluated, [SkmPair, SkmEmptyList], 'list', 'list-copy')
|
991
990
|
arg_evaluated.klone # Previously: arg.klone
|
992
991
|
end
|
@@ -995,7 +994,7 @@ module Skeem
|
|
995
994
|
end
|
996
995
|
|
997
996
|
def create_vector(aRuntime)
|
998
|
-
primitive =
|
997
|
+
primitive = lambda do |_runtime, elements|
|
999
998
|
vector(elements)
|
1000
999
|
end
|
1001
1000
|
|
@@ -1003,7 +1002,7 @@ module Skeem
|
|
1003
1002
|
end
|
1004
1003
|
|
1005
1004
|
def create_vector_length(aRuntime)
|
1006
|
-
primitive =
|
1005
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1007
1006
|
check_argtype(arg_evaluated, SkmVector, 'vector', 'vector-length')
|
1008
1007
|
integer(arg_evaluated.length)
|
1009
1008
|
end
|
@@ -1012,7 +1011,7 @@ module Skeem
|
|
1012
1011
|
end
|
1013
1012
|
|
1014
1013
|
def create_make_vector(aRuntime)
|
1015
|
-
primitive =
|
1014
|
+
primitive = lambda do |runtime, count_arg, arglist|
|
1016
1015
|
count = count_arg.evaluate(runtime)
|
1017
1016
|
check_argtype(count, SkmInteger, 'integer', 'make_vector')
|
1018
1017
|
if arglist.empty?
|
@@ -1028,8 +1027,8 @@ module Skeem
|
|
1028
1027
|
end
|
1029
1028
|
|
1030
1029
|
def create_vector_ref(aRuntime)
|
1031
|
-
|
1032
|
-
|
1030
|
+
# argument 1: a vector, argument 2: an index(integer)
|
1031
|
+
primitive = lambda do |_runtime, vector, index|
|
1033
1032
|
check_argtype(vector, SkmVector, 'vector', 'vector-ref')
|
1034
1033
|
check_argtype(index, SkmInteger, 'integer', 'vector-ref')
|
1035
1034
|
# TODO: index checking
|
@@ -1039,10 +1038,10 @@ module Skeem
|
|
1039
1038
|
|
1040
1039
|
define_primitive_proc(aRuntime, 'vector-ref', binary, primitive)
|
1041
1040
|
end
|
1042
|
-
|
1041
|
+
|
1043
1042
|
def create_vector_set(aRuntime)
|
1044
|
-
|
1045
|
-
|
1043
|
+
# Arguments aren't evaluated yet!...
|
1044
|
+
primitive = lambda do |runtime, vector, k, object|
|
1046
1045
|
index = k.evaluate(runtime)
|
1047
1046
|
check_argtype(vector, SkmVector, 'vector', 'vector-set!')
|
1048
1047
|
check_argtype(index, SkmInteger, 'integer', 'vector-set!')
|
@@ -1050,12 +1049,12 @@ module Skeem
|
|
1050
1049
|
vector.members[index.value] = object
|
1051
1050
|
vector
|
1052
1051
|
end
|
1053
|
-
|
1052
|
+
|
1054
1053
|
define_primitive_proc(aRuntime, 'vector-set!', ternary, primitive)
|
1055
1054
|
end
|
1056
1055
|
|
1057
1056
|
def create_vector2list(aRuntime)
|
1058
|
-
primitive =
|
1057
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1059
1058
|
check_argtype(arg_evaluated, SkmVector, 'vector', 'vector->list')
|
1060
1059
|
SkmPair.create_from_a(arg_evaluated.members)
|
1061
1060
|
end
|
@@ -1064,7 +1063,7 @@ module Skeem
|
|
1064
1063
|
end
|
1065
1064
|
|
1066
1065
|
def create_apply(aRuntime)
|
1067
|
-
primitive =
|
1066
|
+
primitive = lambda do |runtime, proc_arg, arglist|
|
1068
1067
|
if arglist.empty?
|
1069
1068
|
result = SkmEmptyList.instance
|
1070
1069
|
else
|
@@ -1072,18 +1071,19 @@ module Skeem
|
|
1072
1071
|
invoke = ProcedureCall.new(nil, proc_arg, single_list.to_a)
|
1073
1072
|
result = invoke.evaluate(runtime)
|
1074
1073
|
end
|
1074
|
+
result
|
1075
1075
|
end
|
1076
1076
|
|
1077
1077
|
define_primitive_proc(aRuntime, 'apply', one_or_more, primitive)
|
1078
1078
|
end
|
1079
1079
|
|
1080
1080
|
def create_map(aRuntime)
|
1081
|
-
primitive =
|
1081
|
+
primitive = lambda do |runtime, proc_arg, arglist|
|
1082
1082
|
if arglist.empty?
|
1083
1083
|
result = SkmEmptyList.instance
|
1084
1084
|
else
|
1085
1085
|
curr_cells = arglist
|
1086
|
-
arity = curr_cells.size
|
1086
|
+
# arity = curr_cells.size
|
1087
1087
|
initial_result = nil
|
1088
1088
|
curr_result = nil
|
1089
1089
|
loop do
|
@@ -1099,7 +1099,7 @@ module Skeem
|
|
1099
1099
|
curr_result = new_result
|
1100
1100
|
|
1101
1101
|
curr_cells.map!(&:cdr)
|
1102
|
-
break if curr_cells.find { |cdr_entry| !
|
1102
|
+
break if curr_cells.find { |cdr_entry| !cdr_entry.kind_of?(SkmPair) }
|
1103
1103
|
end
|
1104
1104
|
|
1105
1105
|
result = initial_result
|
@@ -1110,26 +1110,34 @@ module Skeem
|
|
1110
1110
|
|
1111
1111
|
define_primitive_proc(aRuntime, 'map', one_or_more, primitive)
|
1112
1112
|
end
|
1113
|
-
|
1113
|
+
|
1114
1114
|
def create_display(aRuntime)
|
1115
|
-
primitive =
|
1115
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1116
1116
|
# @TODO: make output stream configurable
|
1117
1117
|
print arg_evaluated.value.to_s
|
1118
1118
|
SkmUndefined.instance
|
1119
1119
|
end
|
1120
|
-
|
1121
|
-
define_primitive_proc(aRuntime, 'display', unary, primitive)
|
1120
|
+
|
1121
|
+
define_primitive_proc(aRuntime, 'display', unary, primitive)
|
1122
|
+
end
|
1123
|
+
|
1124
|
+
def create_error(aRuntime)
|
1125
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1126
|
+
raise SkmError, arg_evaluated.value
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
define_primitive_proc(aRuntime, 'error', unary, primitive)
|
1122
1130
|
end
|
1123
1131
|
|
1124
1132
|
def create_test_assert(aRuntime)
|
1125
|
-
primitive =
|
1133
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1126
1134
|
if arg_evaluated.boolean? && arg_evaluated.value == false
|
1127
1135
|
assert_call = aRuntime.caller
|
1128
1136
|
pos = assert_call.call_site
|
1129
1137
|
# Error: assertion failed: (> 1 2)
|
1130
1138
|
msg1 = "assertion failed on line #{pos.line}, column #{pos.column}"
|
1131
1139
|
msg2 = ", with #{arg_evaluated.inspect}"
|
1132
|
-
raise StandardError,
|
1140
|
+
raise StandardError, "Error: #{msg1}#{msg2}"
|
1133
1141
|
else
|
1134
1142
|
boolean(true)
|
1135
1143
|
end
|
@@ -1141,7 +1149,7 @@ module Skeem
|
|
1141
1149
|
# DON'T USE IT
|
1142
1150
|
# Non-standard procedure reserved for internal testing/debugging purposes.
|
1143
1151
|
def create_debug(aRuntime)
|
1144
|
-
primitive =
|
1152
|
+
primitive = lambda do |_runtime|
|
1145
1153
|
require 'debug'
|
1146
1154
|
end
|
1147
1155
|
|
@@ -1151,8 +1159,8 @@ module Skeem
|
|
1151
1159
|
# DON'T USE IT
|
1152
1160
|
# Non-standard procedure reserved for internal testing/debugging purposes.
|
1153
1161
|
def create_inspect(aRuntime)
|
1154
|
-
primitive =
|
1155
|
-
$stderr.puts
|
1162
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1163
|
+
$stderr.puts "INSPECT>#{arg_evaluated.inspect}"
|
1156
1164
|
Skeem::SkmUndefined.instance
|
1157
1165
|
end
|
1158
1166
|
define_primitive_proc(aRuntime, '_inspect', unary, primitive)
|
@@ -1160,7 +1168,7 @@ module Skeem
|
|
1160
1168
|
|
1161
1169
|
def create_object_predicate(aRuntime, predicate_name, msg_name = nil)
|
1162
1170
|
msg_name = predicate_name if msg_name.nil?
|
1163
|
-
primitive =
|
1171
|
+
primitive = lambda do |_runtime, arg_evaluated|
|
1164
1172
|
to_datum(arg_evaluated.send(msg_name))
|
1165
1173
|
end
|
1166
1174
|
|
@@ -1220,7 +1228,7 @@ module Skeem
|
|
1220
1228
|
else
|
1221
1229
|
msg2 = "but got #{argument.class}"
|
1222
1230
|
end
|
1223
|
-
raise StandardError, msg1
|
1231
|
+
raise StandardError, "#{msg1} #{msg2}"
|
1224
1232
|
end
|
1225
1233
|
|
1226
1234
|
def remaining_args(arglist, aRuntime)
|
@@ -1234,4 +1242,4 @@ module Skeem
|
|
1234
1242
|
end
|
1235
1243
|
end # module
|
1236
1244
|
end # module
|
1237
|
-
end # module
|
1245
|
+
end # module
|