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