skeem 0.2.15 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +17 -11
- data/CHANGELOG.md +5 -0
- data/Gemfile +2 -0
- data/README.md +3 -2
- data/Rakefile +2 -0
- data/appveyor.yml +3 -4
- data/bin/skeem +15 -15
- data/lib/skeem.rb +2 -0
- data/lib/skeem/datum_dsl.rb +12 -3
- data/lib/skeem/element_visitor.rb +5 -2
- data/lib/skeem/grammar.rb +86 -24
- data/lib/skeem/interpreter.rb +5 -3
- data/lib/skeem/parser.rb +6 -4
- data/lib/skeem/primitive/primitive_builder.rb +128 -115
- data/lib/skeem/primitive/primitive_procedure.rb +17 -20
- data/lib/skeem/runtime.rb +9 -5
- data/lib/skeem/s_expr_builder.rb +46 -104
- data/lib/skeem/s_expr_nodes.rb +116 -90
- data/lib/skeem/skeem_exception.rb +0 -0
- data/lib/skeem/skm_binding.rb +6 -7
- data/lib/skeem/skm_compound_datum.rb +8 -4
- data/lib/skeem/skm_element.rb +14 -12
- data/lib/skeem/skm_empty_list.rb +6 -4
- data/lib/skeem/skm_exception.rb +9 -0
- data/lib/skeem/skm_expression.rb +3 -1
- data/lib/skeem/skm_frame.rb +3 -2
- data/lib/skeem/skm_pair.rb +23 -18
- data/lib/skeem/skm_procedure_exec.rb +8 -6
- data/lib/skeem/skm_simple_datum.rb +13 -12
- data/lib/skeem/skm_unary_expression.rb +15 -17
- data/lib/skeem/tokenizer.rb +32 -25
- data/lib/skeem/version.rb +3 -1
- data/skeem.gemspec +6 -4
- data/spec/skeem/add4.skm +4 -0
- data/spec/skeem/datum_dsl_spec.rb +13 -12
- data/spec/skeem/element_visitor_spec.rb +12 -10
- data/spec/skeem/interpreter_spec.rb +74 -46
- data/spec/skeem/lambda_spec.rb +9 -7
- data/spec/skeem/parser_spec.rb +21 -19
- data/spec/skeem/primitive/primitive_builder_spec.rb +57 -48
- data/spec/skeem/primitive/primitive_procedure_spec.rb +15 -13
- data/spec/skeem/runtime_spec.rb +18 -16
- data/spec/skeem/s_expr_nodes_spec.rb +8 -6
- data/spec/skeem/skm_compound_datum_spec.rb +11 -9
- data/spec/skeem/skm_element_spec.rb +7 -5
- data/spec/skeem/skm_empty_list_spec.rb +7 -5
- data/spec/skeem/skm_frame_spec.rb +5 -4
- data/spec/skeem/skm_pair_spec.rb +4 -3
- data/spec/skeem/skm_procedure_exec_spec.rb +2 -0
- data/spec/skeem/skm_simple_datum_spec.rb +24 -22
- data/spec/skeem/skm_unary_expression_spec.rb +11 -9
- data/spec/skeem/tokenizer_spec.rb +53 -44
- data/spec/skeem_spec.rb +2 -0
- data/spec/spec_helper.rb +4 -2
- metadata +7 -4
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative '../s_expr_nodes'
|
2
4
|
|
3
5
|
module Skeem
|
@@ -17,7 +19,7 @@ module Skeem
|
|
17
19
|
def callable?
|
18
20
|
true
|
19
21
|
end
|
20
|
-
|
22
|
+
|
21
23
|
def procedure?
|
22
24
|
true
|
23
25
|
end
|
@@ -76,10 +78,8 @@ module Skeem
|
|
76
78
|
if (anArity.low + 2) != count_param
|
77
79
|
discrepancy_arity_argument_count(anArity.low, count_param, 2)
|
78
80
|
end
|
79
|
-
|
80
|
-
|
81
|
-
discrepancy_arity_argument_count(anArity.high, count_param, 1)
|
82
|
-
end
|
81
|
+
elsif (anArity.high + 1) != count_param # fixed arity...
|
82
|
+
discrepancy_arity_argument_count(anArity.high, count_param, 1)
|
83
83
|
end
|
84
84
|
|
85
85
|
anArity
|
@@ -102,10 +102,8 @@ module Skeem
|
|
102
102
|
if count_actuals > arity.high
|
103
103
|
wrong_number_arguments(arity.high, count_actuals)
|
104
104
|
end
|
105
|
-
|
106
|
-
|
107
|
-
wrong_number_arguments(arity.high, count_actuals)
|
108
|
-
end
|
105
|
+
elsif count_actuals != arity.high # fixed non-zero arity...
|
106
|
+
wrong_number_arguments(arity.high, count_actuals)
|
109
107
|
end
|
110
108
|
end
|
111
109
|
|
@@ -114,11 +112,11 @@ module Skeem
|
|
114
112
|
result = code.call(aRuntime)
|
115
113
|
elsif arity.variadic? || (arity.low < arity.high)
|
116
114
|
if arity.low.zero?
|
117
|
-
if [
|
115
|
+
if %w[and or append].include? identifier
|
118
116
|
# Defer the evaluation of arguments to the primitive
|
119
117
|
result = code.call(aRuntime, operands)
|
120
118
|
else
|
121
|
-
evaluated_args = operands.map {|opernd| opernd.evaluate(aRuntime) }
|
119
|
+
evaluated_args = operands.map { |opernd| opernd.evaluate(aRuntime) }
|
122
120
|
result = code.call(aRuntime, evaluated_args)
|
123
121
|
end
|
124
122
|
else
|
@@ -134,14 +132,13 @@ module Skeem
|
|
134
132
|
# p args.inspect
|
135
133
|
result = code.send(:call, aRuntime, *args)
|
136
134
|
end
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
end
|
135
|
+
elsif identifier.value =~ /^set-[a-zA-Z]+!/ || identifier.value =~ /[a-zA-Z]+-set!/
|
136
|
+
# Fixed arity...
|
137
|
+
# Defer evaluation inside the primitive
|
138
|
+
result = code.send(:call, aRuntime, *operands)
|
139
|
+
else
|
140
|
+
evaluated_args = operands.map { |opernd| opernd.evaluate(aRuntime) }
|
141
|
+
result = code.send(:call, aRuntime, *evaluated_args)
|
145
142
|
end
|
146
143
|
|
147
144
|
result
|
@@ -166,4 +163,4 @@ module Skeem
|
|
166
163
|
end
|
167
164
|
end # class
|
168
165
|
end # module
|
169
|
-
end # module
|
166
|
+
end # module
|
data/lib/skeem/runtime.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 's_expr_nodes'
|
2
4
|
|
3
5
|
module Skeem
|
@@ -41,13 +43,12 @@ module Skeem
|
|
41
43
|
result = nil
|
42
44
|
begin
|
43
45
|
result = entry.evaluate(self)
|
44
|
-
|
45
|
-
rescue NoMethodError => exc
|
46
|
+
rescue NoMethodError => e
|
46
47
|
# $stderr.puts 'In rescue block'
|
47
48
|
# $stderr.puts key_value.inspect
|
48
49
|
# $stderr.puts entry.inspect
|
49
50
|
# $stderr.puts entry.expression.inspect
|
50
|
-
raise
|
51
|
+
raise e
|
51
52
|
end
|
52
53
|
result
|
53
54
|
else
|
@@ -66,13 +67,14 @@ module Skeem
|
|
66
67
|
invokation.evaluate(self)
|
67
68
|
end
|
68
69
|
|
69
|
-
def nest
|
70
|
+
def nest
|
70
71
|
nested = SkmFrame.new(environment)
|
71
72
|
push(nested)
|
72
73
|
end
|
73
74
|
|
74
75
|
def unnest
|
75
76
|
raise StandardError, 'Cannot unnest environment' unless environment.parent
|
77
|
+
|
76
78
|
environment.bindings.clear
|
77
79
|
pop
|
78
80
|
end
|
@@ -90,6 +92,7 @@ module Skeem
|
|
90
92
|
if env_stack.empty?
|
91
93
|
raise StandardError, 'Skeem environment stack empty!'
|
92
94
|
end
|
95
|
+
|
93
96
|
env_stack.pop
|
94
97
|
end
|
95
98
|
|
@@ -110,6 +113,7 @@ module Skeem
|
|
110
113
|
if call_stack.empty?
|
111
114
|
raise StandardError, 'Skeem call stack empty!'
|
112
115
|
end
|
116
|
+
|
113
117
|
call_stack.pop
|
114
118
|
end
|
115
119
|
|
@@ -132,4 +136,4 @@ module Skeem
|
|
132
136
|
result
|
133
137
|
end
|
134
138
|
end # class
|
135
|
-
end # module
|
139
|
+
end # module
|
data/lib/skeem/s_expr_builder.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'stringio'
|
2
4
|
require_relative 'skm_pair'
|
3
5
|
require_relative 'skm_binding'
|
@@ -43,11 +45,23 @@ module Skeem
|
|
43
45
|
def reduce_main(_production, _range, _tokens, theChildren)
|
44
46
|
last_child = theChildren.last
|
45
47
|
# $stderr.puts last_child.inspect
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
if last_child.length == 1
|
49
|
+
last_child.car
|
50
|
+
else
|
51
|
+
last_child
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Default semantic action for rules of the form:
|
56
|
+
# rule 'some_symbol_star' => 'some_symbol_star some_symbol'
|
57
|
+
def reduce_star_default(_production, _range, _tokens, theChildren)
|
58
|
+
theChildren[0] << theChildren[1]
|
59
|
+
end
|
60
|
+
|
61
|
+
# Default semantic action for rules of the form:
|
62
|
+
# rule 'some_symbol_star' => []
|
63
|
+
def reduce_star_base(_production, _range, _tokens, _children)
|
64
|
+
[]
|
51
65
|
end
|
52
66
|
|
53
67
|
# rule('cmd_or_def_plus' => 'cmd_or_def_plus cmd_or_def').as 'multiple_cmd_def'
|
@@ -81,7 +95,7 @@ module Skeem
|
|
81
95
|
end
|
82
96
|
|
83
97
|
# rule('definition' => 'LPAREN BEGIN definition_star RPAREN').as 'definitions_within_begin'
|
84
|
-
def reduce_definitions_within_begin(_production,
|
98
|
+
def reduce_definitions_within_begin(_production, _range, _tokens, theChildren)
|
85
99
|
SkmSequencingBlock.new(SkmPair.create_from_a(theChildren[2]))
|
86
100
|
end
|
87
101
|
|
@@ -135,20 +149,10 @@ module Skeem
|
|
135
149
|
end
|
136
150
|
|
137
151
|
# rule('vector' => 'VECTOR_BEGIN datum_star RPAREN').as 'vector'
|
138
|
-
def reduce_vector(_production,
|
152
|
+
def reduce_vector(_production, _range, _tokens, theChildren)
|
139
153
|
SkmVector.new(theChildren[1])
|
140
154
|
end
|
141
155
|
|
142
|
-
# rule('datum_star' => 'datum_star datum').as 'datum_star'
|
143
|
-
def reduce_datum_star(_production, aRange, _tokens, theChildren)
|
144
|
-
theChildren[0] << theChildren[1]
|
145
|
-
end
|
146
|
-
|
147
|
-
# rule('datum_star' => []).as 'no_datum_yet'
|
148
|
-
def reduce_no_datum_yet(_production, aRange, _tokens, theChildren)
|
149
|
-
[]
|
150
|
-
end
|
151
|
-
|
152
156
|
# rule('procedure_call' => 'LPAREN operator RPAREN').as 'proc_call_nullary'
|
153
157
|
def reduce_proc_call_nullary(_production, aRange, _tokens, theChildren)
|
154
158
|
ProcedureCall.new(aRange, theChildren[1], [])
|
@@ -174,11 +178,6 @@ module Skeem
|
|
174
178
|
[theChildren.last]
|
175
179
|
end
|
176
180
|
|
177
|
-
# rule('operand_plus' => 'operand').as 'last_operand'
|
178
|
-
def reduce_last_operand(_production, _range, _tokens, theChildren)
|
179
|
-
[theChildren.last]
|
180
|
-
end
|
181
|
-
|
182
181
|
# rule('def_formals' => 'identifier_star').as 'def_formals'
|
183
182
|
def reduce_def_formals(_production, _range, _tokens, theChildren)
|
184
183
|
SkmFormals.new(theChildren[0], :fixed)
|
@@ -213,16 +212,6 @@ module Skeem
|
|
213
212
|
SkmFormals.new(formals, :variadic)
|
214
213
|
end
|
215
214
|
|
216
|
-
# rule('identifier_star' => 'identifier_star IDENTIFIER').as 'identifier_star'
|
217
|
-
def reduce_identifier_star(_production, _range, _tokens, theChildren)
|
218
|
-
theChildren[0] << theChildren[1]
|
219
|
-
end
|
220
|
-
|
221
|
-
# rule('identifier_star' => []).as 'no_identifier_yet'
|
222
|
-
def reduce_no_identifier_yet(_production, _range, _tokens, theChildren)
|
223
|
-
[]
|
224
|
-
end
|
225
|
-
|
226
215
|
# rule('identifier_plus' => 'identifier_plus IDENTIFIER').as 'multiple_identifiers'
|
227
216
|
def reduce_multiple_identifiers(_production, _range, _tokens, theChildren)
|
228
217
|
theChildren[0] << theChildren[1]
|
@@ -239,32 +228,11 @@ module Skeem
|
|
239
228
|
{ defs: definitions, sequence: theChildren[1] }
|
240
229
|
end
|
241
230
|
|
242
|
-
# rule('definition_star' => 'definition_star definition').as 'definition_star'
|
243
|
-
def reduce_definition_star(_production, _range, _tokens, theChildren)
|
244
|
-
theChildren[0] << theChildren[1]
|
245
|
-
end
|
246
|
-
|
247
|
-
|
248
|
-
# rule('definition_star' => []).as 'no_definition_yet'
|
249
|
-
def reduce_no_definition_yet(_production, _range, _tokens, theChildren)
|
250
|
-
[]
|
251
|
-
end
|
252
|
-
|
253
231
|
# rule('sequence' => 'command_star expression').as 'sequence'
|
254
232
|
def reduce_sequence(_production, _range, _tokens, theChildren)
|
255
233
|
SkmPair.create_from_a(theChildren[0] << theChildren[1])
|
256
234
|
end
|
257
235
|
|
258
|
-
# rule('command_star' => 'command_star command').as 'multiple_commands'
|
259
|
-
def reduce_multiple_commands(_production, _range, _tokens, theChildren)
|
260
|
-
theChildren[0] << theChildren[1]
|
261
|
-
end
|
262
|
-
|
263
|
-
# rule('command_star' => []).as 'no_command_yet'
|
264
|
-
def reduce_no_command_yet(_production, _range, _tokens, theChildren)
|
265
|
-
[]
|
266
|
-
end
|
267
|
-
|
268
236
|
# rule('conditional' => 'LPAREN IF test consequent alternate RPAREN').as 'conditional'
|
269
237
|
def reduce_conditional(_production, aRange, _tokens, theChildren)
|
270
238
|
SkmCondition.new(aRange, theChildren[2], theChildren[3], theChildren[4])
|
@@ -286,7 +254,7 @@ module Skeem
|
|
286
254
|
end
|
287
255
|
|
288
256
|
# rule('derived_expression' => 'LPAREN LET LPAREN binding_spec_star RPAREN body RPAREN').as 'short_let_form'
|
289
|
-
def reduce_short_let_form(_production,
|
257
|
+
def reduce_short_let_form(_production, _range, _tokens, theChildren)
|
290
258
|
SkmBindingBlock.new(:let, theChildren[3], theChildren[5])
|
291
259
|
end
|
292
260
|
|
@@ -309,9 +277,9 @@ module Skeem
|
|
309
277
|
|
310
278
|
# We reky on utility 'builder' object
|
311
279
|
worker = SkmDoExprBuilder.new(theChildren[3], theChildren[6],
|
312
|
-
|
280
|
+
theChildren[7], theChildren[9])
|
313
281
|
do_expression = worker.do_expression
|
314
|
-
body = { :
|
282
|
+
body = { defs: [], sequence: do_expression }
|
315
283
|
SkmBindingBlock.new(:let_star, worker.bindings, body)
|
316
284
|
end
|
317
285
|
|
@@ -325,16 +293,6 @@ module Skeem
|
|
325
293
|
[theChildren[0]]
|
326
294
|
end
|
327
295
|
|
328
|
-
# rule('cond_clause_star' => 'cond_clause_star cond_clause').as 'cond_clauses_star'
|
329
|
-
def reduce_cond_clauses_star(_production, _range, _tokens, theChildren)
|
330
|
-
theChildren[0] << theChildren[1]
|
331
|
-
end
|
332
|
-
|
333
|
-
# rule('cond_clause_star' => []).as 'last_cond_clauses_star'
|
334
|
-
def reduce_last_cond_clauses_star(_production, _range, _tokens, _children)
|
335
|
-
[]
|
336
|
-
end
|
337
|
-
|
338
296
|
# rule('cond_clause' => 'LPAREN test sequence RPAREN').as 'cond_clause'
|
339
297
|
def reduce_cond_clause(_production, _range, _tokens, theChildren)
|
340
298
|
[theChildren[1], SkmSequencingBlock.new(SkmPair.create_from_a(theChildren[2]))]
|
@@ -346,40 +304,20 @@ module Skeem
|
|
346
304
|
end
|
347
305
|
|
348
306
|
# rule('quasiquotation' => 'LPAREN QUASIQUOTE qq_template RPAREN').as 'quasiquotation'
|
349
|
-
def reduce_quasiquotation(_production,
|
307
|
+
def reduce_quasiquotation(_production, _range, _tokens, theChildren)
|
350
308
|
SkmQuasiquotation.new(theChildren[2])
|
351
309
|
end
|
352
310
|
|
353
311
|
# rule('quasiquotation' => 'GRAVE_ACCENT qq_template').as 'quasiquotation_short'
|
354
|
-
def reduce_quasiquotation_short(_production,
|
312
|
+
def reduce_quasiquotation_short(_production, _range, _tokens, theChildren)
|
355
313
|
SkmQuasiquotation.new(theChildren[1])
|
356
314
|
end
|
357
315
|
|
358
|
-
# rule('binding_spec_star' => 'binding_spec_star binding_spec').as 'multiple_binding_specs'
|
359
|
-
def reduce_multiple_binding_specs(_production, aRange, _tokens, theChildren)
|
360
|
-
theChildren[0] << theChildren[1]
|
361
|
-
end
|
362
|
-
|
363
|
-
# rule('binding_spec_star' => []).as 'no_binding_spec_yet'
|
364
|
-
def reduce_no_binding_spec_yet(_production, aRange, _tokens, _children)
|
365
|
-
[]
|
366
|
-
end
|
367
|
-
|
368
316
|
# rule('binding_spec' => 'LPAREN IDENTIFIER expression RPAREN').as 'binding_spec'
|
369
|
-
def reduce_binding_spec(
|
317
|
+
def reduce_binding_spec(_production, _range, _tokens, theChildren)
|
370
318
|
SkmBinding.new(theChildren[1], theChildren[2])
|
371
319
|
end
|
372
320
|
|
373
|
-
# rule('iteration_spec_star' => 'iteration_spec_star iteration_spec').as 'multiple_iter_specs'
|
374
|
-
def reduce_multiple_iter_specs(_production, _range, _tokens, theChildren)
|
375
|
-
theChildren[0] << theChildren[1]
|
376
|
-
end
|
377
|
-
|
378
|
-
# rule('iteration_spec_star' => []).as 'no_iter_spec_yet'
|
379
|
-
def reduce_no_iter_spec_yet(_production, _range, _tokens, _children)
|
380
|
-
[]
|
381
|
-
end
|
382
|
-
|
383
321
|
# rule('iteration_spec' => 'LPAREN IDENTIFIER init step RPAREN').as 'iteration_spec_long'
|
384
322
|
def reduce_iteration_spec_long(_production, _range, _tokens, theChildren)
|
385
323
|
SkmIterationSpec.new(theChildren[1], theChildren[2], theChildren[3])
|
@@ -391,10 +329,26 @@ module Skeem
|
|
391
329
|
end
|
392
330
|
|
393
331
|
# rule('do_result' => []).as 'empty_do_result'
|
394
|
-
def reduce_empty_do_result(_production, _range, _tokens,
|
332
|
+
def reduce_empty_do_result(_production, _range, _tokens, _children)
|
395
333
|
SkmEmptyList.instance
|
396
334
|
end
|
397
335
|
|
336
|
+
# rule('includer' => 'LPAREN INCLUDE string_plus RPAREN').as 'include'
|
337
|
+
def reduce_include(_production, _range, _tokens, theChildren)
|
338
|
+
includer = SkmIncluder.new(theChildren[2])
|
339
|
+
includer.build
|
340
|
+
end
|
341
|
+
|
342
|
+
# rule('string_plus' => 'string_plus STRING_LIT').as 'multiple_string'
|
343
|
+
def reduce_multiple_string(_production, _range, _tokens, theChildren)
|
344
|
+
theChildren[0] << theChildren[1]
|
345
|
+
end
|
346
|
+
|
347
|
+
# rule('string_plus' => 'STRING_LIT').as 'last_single_string'
|
348
|
+
def reduce_last_single_string(_production, _range, _tokens, theChildren)
|
349
|
+
[theChildren[0]]
|
350
|
+
end
|
351
|
+
|
398
352
|
# rule('list_qq_template' => 'LPAREN qq_template_or_splice_star RPAREN').as 'list_qq'
|
399
353
|
def reduce_list_qq(_production, _range, _tokens, theChildren)
|
400
354
|
SkmPair.create_from_a(theChildren[1])
|
@@ -406,21 +360,9 @@ module Skeem
|
|
406
360
|
end
|
407
361
|
|
408
362
|
# rule('unquotation' => 'COMMA qq_template').as 'unquotation_short'
|
409
|
-
def reduce_unquotation_short(_production,
|
363
|
+
def reduce_unquotation_short(_production, _range, _tokens, theChildren)
|
410
364
|
SkmUnquotation.new(theChildren[1])
|
411
365
|
end
|
412
|
-
|
413
|
-
# rule('qq_template_or_splice_star' => 'qq_template_or_splice_star qq_template_or_splice').as 'multiple_template_splice'
|
414
|
-
def reduce_multiple_template_splice(_production, _range, _tokens, theChildren)
|
415
|
-
theChildren[0] << theChildren[1]
|
416
|
-
end
|
417
|
-
|
418
|
-
# rule('qq_template_or_splice_star' => []).as 'no_template_splice_yet'
|
419
|
-
def reduce_no_template_splice_yet(_production, _range, _tokens, theChildren)
|
420
|
-
[]
|
421
|
-
end
|
422
|
-
|
423
|
-
|
424
366
|
end # class
|
425
367
|
end # module
|
426
|
-
# End of file
|
368
|
+
# End of file
|
data/lib/skeem/s_expr_nodes.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Classes that implement nodes of Abstract Syntax Trees (AST) representing
|
2
4
|
# Skeem parse results.
|
5
|
+
require 'forwardable'
|
3
6
|
require 'singleton'
|
4
7
|
|
5
8
|
require_relative 'datum_dsl'
|
6
9
|
require_relative 'skm_unary_expression'
|
10
|
+
require_relative 'skm_procedure_exec'
|
7
11
|
|
8
12
|
module Skeem
|
9
13
|
class SkmUndefined
|
@@ -20,7 +24,7 @@ module Skeem
|
|
20
24
|
private
|
21
25
|
|
22
26
|
def initialize
|
23
|
-
|
27
|
+
freeze
|
24
28
|
end
|
25
29
|
end # class
|
26
30
|
|
@@ -63,11 +67,11 @@ module Skeem
|
|
63
67
|
end
|
64
68
|
|
65
69
|
def evaluate(aRuntime)
|
66
|
-
frame_change = false
|
67
70
|
aRuntime.push_call(self)
|
71
|
+
# frame_change = false
|
68
72
|
# $stderr.puts "\n Start of ProcedureCall#evaluate #{object_id.to_s(16)}"
|
69
73
|
# $stderr.puts " environment: #{aRuntime.environment.object_id.to_s(16)}, "
|
70
|
-
if aRuntime.environment
|
74
|
+
if aRuntime.environment&.parent
|
71
75
|
# $stderr.puts "Parent environment #{aRuntime.environment.parent.object_id.to_s(16)}, "
|
72
76
|
# $stderr.puts aRuntime.environment.inspect
|
73
77
|
end
|
@@ -84,7 +88,6 @@ module Skeem
|
|
84
88
|
# end
|
85
89
|
# $stderr.puts ' callee: ' + callee.inspect
|
86
90
|
result = callee.call(aRuntime, actuals)
|
87
|
-
operands_consumed = true
|
88
91
|
# aRuntime.pop if frame_change
|
89
92
|
end
|
90
93
|
aRuntime.pop_call
|
@@ -94,9 +97,9 @@ module Skeem
|
|
94
97
|
|
95
98
|
def quasiquote(aRuntime)
|
96
99
|
quasi_operator = operator.quasiquote(aRuntime)
|
97
|
-
quasi_operands = operands.map { |oper
|
100
|
+
quasi_operands = operands.map { |oper| oper.quasiquote(aRuntime) }
|
98
101
|
|
99
|
-
|
102
|
+
self.class.new(position, quasi_operator, quasi_operands)
|
100
103
|
end
|
101
104
|
|
102
105
|
def inspect
|
@@ -106,7 +109,7 @@ module Skeem
|
|
106
109
|
end
|
107
110
|
|
108
111
|
def associations
|
109
|
-
[
|
112
|
+
%i[operator operands]
|
110
113
|
end
|
111
114
|
|
112
115
|
alias children operands
|
@@ -121,6 +124,7 @@ module Skeem
|
|
121
124
|
result = operator.evaluate(aRuntime)
|
122
125
|
# If child proc call consumes the parent's operand, then we're done
|
123
126
|
return [:result, result] unless result.callable? # if operands_consumed
|
127
|
+
|
124
128
|
callee = result
|
125
129
|
# callee = fetch_callee(aRuntime, result)
|
126
130
|
when Primitive::PrimitiveProcedure
|
@@ -144,14 +148,14 @@ module Skeem
|
|
144
148
|
def fetch_callee(aRuntime, var_key)
|
145
149
|
begin
|
146
150
|
aRuntime.include?(var_key.value)
|
147
|
-
rescue NoMethodError =>
|
151
|
+
rescue NoMethodError => e
|
148
152
|
# $stderr.puts "VVVVVVVVVVVVVVV"
|
149
153
|
# $stderr.puts 'var_key: ' + var_key.inspect
|
150
154
|
# $stderr.puts 'operator: ' + operator.inspect
|
151
155
|
# $stderr.puts 'operands: ' + operands.inspect
|
152
156
|
# $stderr.puts 'operands_consumed: ' + operands_consumed.inspect
|
153
157
|
# $stderr.puts "^^^^^^^^^^^^^^^"
|
154
|
-
raise
|
158
|
+
raise e
|
155
159
|
end
|
156
160
|
unless aRuntime.include?(var_key.value)
|
157
161
|
err = StandardError
|
@@ -172,6 +176,7 @@ module Skeem
|
|
172
176
|
|
173
177
|
def transform_operands(aRuntime)
|
174
178
|
return [] if operands == SkmEmptyList.instance
|
179
|
+
|
175
180
|
actuals = operands.to_a
|
176
181
|
|
177
182
|
result = actuals.map do |actual|
|
@@ -185,9 +190,6 @@ module Skeem
|
|
185
190
|
|
186
191
|
result.nil? ? [] : result
|
187
192
|
end
|
188
|
-
|
189
|
-
|
190
|
-
|
191
193
|
end # class
|
192
194
|
|
193
195
|
class SkmCondition < SkmMultiExpression
|
@@ -211,6 +213,7 @@ module Skeem
|
|
211
213
|
else
|
212
214
|
condition_result = consequent.evaluate(aRuntime)
|
213
215
|
end
|
216
|
+
condition_result
|
214
217
|
end
|
215
218
|
|
216
219
|
def quasiquote(aRuntime)
|
@@ -218,7 +221,7 @@ module Skeem
|
|
218
221
|
quasi_consequent = consequent.quasiquote(aRuntime)
|
219
222
|
quasi_alternate = alternate.quasiquote(aRuntime)
|
220
223
|
|
221
|
-
|
224
|
+
self.class.new(position, quasi_test, quasi_consequent, quasi_alternate)
|
222
225
|
end
|
223
226
|
|
224
227
|
def inspect
|
@@ -229,7 +232,7 @@ module Skeem
|
|
229
232
|
end
|
230
233
|
|
231
234
|
def associations
|
232
|
-
[
|
235
|
+
%i[test consequent alternate]
|
233
236
|
end
|
234
237
|
end # class
|
235
238
|
|
@@ -266,7 +269,7 @@ module Skeem
|
|
266
269
|
end
|
267
270
|
|
268
271
|
def quasiquote(aRuntime)
|
269
|
-
|
272
|
+
quasi_clauses = clauses.map do |(test, consequent)|
|
270
273
|
test_qq = test.quasiquote(aRuntime)
|
271
274
|
consequent_qq = consequent.quasiquote(aRuntime)
|
272
275
|
[test_qq, consequent_qq]
|
@@ -280,7 +283,7 @@ module Skeem
|
|
280
283
|
result = inspect_prefix + '@test ' + test.inspect + ', '
|
281
284
|
result << "@clauses \n"
|
282
285
|
clauses.each do |(test, consequent)|
|
283
|
-
result << ' '
|
286
|
+
result << ' ' << test.inspect << ' ' << consequent.inspect << "\n"
|
284
287
|
end
|
285
288
|
result << '@alternate ' + alternate.inspect + inspect_suffix
|
286
289
|
result
|
@@ -297,7 +300,8 @@ module Skeem
|
|
297
300
|
end
|
298
301
|
|
299
302
|
def ==(other)
|
300
|
-
return true if
|
303
|
+
return true if object_id == other.object_id
|
304
|
+
|
301
305
|
result = false
|
302
306
|
|
303
307
|
case other
|
@@ -325,61 +329,61 @@ module Skeem
|
|
325
329
|
end
|
326
330
|
end # class
|
327
331
|
|
328
|
-
class SkmDoExprBuilder
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
332
|
+
class SkmDoExprBuilder
|
333
|
+
attr_reader :bindings
|
334
|
+
attr_reader :update_steps
|
335
|
+
attr_reader :test
|
336
|
+
attr_reader :do_result
|
337
|
+
attr_reader :commands
|
334
338
|
|
335
|
-
|
339
|
+
# 3 => iteration_spec_star, 6 => test, 7 => do_result, 9 => command_star
|
336
340
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
341
|
+
def initialize(iterSpecs, aTest, doResult, theCommands)
|
342
|
+
iteration_specs_set(iterSpecs)
|
343
|
+
@test = aTest
|
344
|
+
@do_result = doResult
|
345
|
+
commands_set(theCommands)
|
346
|
+
end
|
343
347
|
|
344
|
-
|
345
|
-
|
346
|
-
|
348
|
+
def do_expression
|
349
|
+
DoExpression.new(test, do_result, commands, update_steps)
|
350
|
+
end
|
347
351
|
|
348
|
-
|
352
|
+
private
|
349
353
|
|
350
|
-
|
351
|
-
|
354
|
+
def iteration_specs_set(iterSpecs)
|
355
|
+
@bindings = iterSpecs.map do |iter_spec|
|
352
356
|
var = iter_spec.variable
|
353
357
|
val = iter_spec.init_expr
|
354
358
|
SkmBinding.new(var, val)
|
355
359
|
end
|
356
360
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
361
|
+
to_update = iterSpecs.select(&:step_expr)
|
362
|
+
if to_update
|
363
|
+
steps = to_update.map do |iter_spec|
|
364
|
+
SkmDelayedUpdateBinding.new(iter_spec.variable, iter_spec.step_expr)
|
365
|
+
end
|
366
|
+
if steps.size == 1
|
367
|
+
@update_steps = steps[0]
|
368
|
+
else
|
369
|
+
@update_steps = SkmPair.create_from_a(steps)
|
370
|
+
end
|
364
371
|
else
|
365
|
-
@update_steps =
|
372
|
+
@update_steps = SkmEmptyList.instance
|
366
373
|
end
|
367
|
-
else
|
368
|
-
@update_steps = SkmEmptyList.instance
|
369
374
|
end
|
370
|
-
end
|
371
375
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
376
|
+
def commands_set(theCommands)
|
377
|
+
case theCommands.size
|
378
|
+
when 0
|
379
|
+
@commands = SkmEmptyList.instance
|
380
|
+
when 1
|
381
|
+
@commands = theCommands[0]
|
382
|
+
else
|
383
|
+
@commands = SkmSequencingBlock.new(SkmPair.create_from_a(theCommands))
|
384
|
+
end
|
380
385
|
end
|
381
|
-
end
|
382
|
-
end # class
|
386
|
+
end # class
|
383
387
|
|
384
388
|
# Syntax outline:
|
385
389
|
# LPAREN DO LPAREN iteration_spec_star RPAREN
|
@@ -454,12 +458,12 @@ end # class
|
|
454
458
|
test_result = test.evaluate(aRuntime)
|
455
459
|
if test_result.boolean? && test_result.value == false
|
456
460
|
# Only #f is considered as false, everything else is true
|
457
|
-
commands
|
461
|
+
commands&.evaluate(aRuntime)
|
458
462
|
if update_steps
|
459
463
|
update_steps.evaluate(aRuntime)
|
460
464
|
case update_steps
|
461
465
|
when SkmEmptyList.instance
|
462
|
-
|
466
|
+
# Do nothing
|
463
467
|
when SkmPair
|
464
468
|
arr = update_steps.to_a
|
465
469
|
arr.each { |delayed_binding| delayed_binding.do_it!(aRuntime) }
|
@@ -476,6 +480,31 @@ end # class
|
|
476
480
|
end
|
477
481
|
end # class
|
478
482
|
|
483
|
+
class SkmIncluder
|
484
|
+
attr_reader :filenames
|
485
|
+
|
486
|
+
def initialize(theFilenames)
|
487
|
+
@filenames = theFilenames
|
488
|
+
end
|
489
|
+
|
490
|
+
def build
|
491
|
+
parser = Skeem::Parser.new
|
492
|
+
parse_results = filenames.map do |fname|
|
493
|
+
f_source = File.read(fname.value)
|
494
|
+
ptree = parser.parse(f_source)
|
495
|
+
ptree.root
|
496
|
+
end
|
497
|
+
|
498
|
+
if parse_results.size == 1
|
499
|
+
result = parse_results[0]
|
500
|
+
else
|
501
|
+
sequence = SkmPair.create_from_a(parse_results)
|
502
|
+
result = SkmSequencingBlock.new(sequence)
|
503
|
+
end
|
504
|
+
result
|
505
|
+
end
|
506
|
+
end # class
|
507
|
+
|
479
508
|
class SkmFormals
|
480
509
|
attr_reader :formals
|
481
510
|
attr_reader :arity
|
@@ -509,12 +538,10 @@ end # class
|
|
509
538
|
|
510
539
|
if arityKind == :fixed
|
511
540
|
@arity = SkmArity.new(fixed_arity, fixed_arity)
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
@arity = SkmArity.new(fixed_arity - 1, '*')
|
517
|
-
end
|
541
|
+
elsif formals.empty? # :variadic
|
542
|
+
raise StandardError, 'Internal error: inconsistent arity'
|
543
|
+
else
|
544
|
+
@arity = SkmArity.new(fixed_arity - 1, '*')
|
518
545
|
end
|
519
546
|
end
|
520
547
|
end # class
|
@@ -581,7 +608,7 @@ end # class
|
|
581
608
|
end
|
582
609
|
|
583
610
|
def associations
|
584
|
-
[
|
611
|
+
%i[formals definitions sequence]
|
585
612
|
end
|
586
613
|
|
587
614
|
def bind_locals(aRuntime, theActuals)
|
@@ -589,12 +616,14 @@ end # class
|
|
589
616
|
count_actuals = actuals.size
|
590
617
|
|
591
618
|
if (count_actuals < required_arity) ||
|
592
|
-
|
619
|
+
((count_actuals > required_arity) &&
|
620
|
+
!formals.variadic?)
|
593
621
|
# $stderr.puts "Error"
|
594
622
|
# $stderr.puts self.inspect
|
595
623
|
raise StandardError, msg_arity_mismatch(theActuals)
|
596
624
|
end
|
597
625
|
return if count_actuals.zero? && !formals.variadic?
|
626
|
+
|
598
627
|
bind_required_locals(aRuntime, theActuals)
|
599
628
|
if formals.variadic?
|
600
629
|
variadic_part_raw = actuals.drop(required_arity)
|
@@ -619,7 +648,7 @@ end # class
|
|
619
648
|
# $stderr.puts "Tef #{aProcedureCall.inspect}"
|
620
649
|
# a_def.evaluate(aRuntime)
|
621
650
|
end
|
622
|
-
#aProcedureCall.operands_consumed = true
|
651
|
+
# aProcedureCall.operands_consumed = true
|
623
652
|
end
|
624
653
|
|
625
654
|
private
|
@@ -660,14 +689,14 @@ end # class
|
|
660
689
|
|
661
690
|
def msg_arity_mismatch(actuals)
|
662
691
|
# *** ERROR: wrong number of arguments for #<closure morph> (required 2, got 1)
|
663
|
-
msg1 =
|
692
|
+
msg1 = 'Wrong number of arguments for procedure '
|
664
693
|
count_actuals = actuals.size
|
665
694
|
msg2 = "(required #{required_arity}, got #{count_actuals})"
|
666
695
|
msg1 + msg2
|
667
696
|
end
|
668
697
|
|
669
698
|
def inspect_specific
|
670
|
-
result = ''
|
699
|
+
result = +''
|
671
700
|
result << '@formals ' + formals.inspect + ', '
|
672
701
|
result << '@definitions ' + definitions.inspect + ', '
|
673
702
|
result << '@sequence ' + sequence.inspect + inspect_suffix
|
@@ -676,12 +705,6 @@ end # class
|
|
676
705
|
end
|
677
706
|
end # class
|
678
707
|
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
require 'forwardable'
|
683
|
-
require_relative 'skm_procedure_exec'
|
684
|
-
|
685
708
|
class SkmLambda < SkmMultiExpression
|
686
709
|
include DatumDSL
|
687
710
|
extend Forwardable
|
@@ -696,7 +719,7 @@ require_relative 'skm_procedure_exec'
|
|
696
719
|
@environment = aRuntime.environment
|
697
720
|
end
|
698
721
|
|
699
|
-
def evaluate(
|
722
|
+
def evaluate(_runtime)
|
700
723
|
self
|
701
724
|
end
|
702
725
|
|
@@ -746,7 +769,7 @@ require_relative 'skm_procedure_exec'
|
|
746
769
|
end
|
747
770
|
|
748
771
|
def associations
|
749
|
-
[
|
772
|
+
%i[formals definitions sequence]
|
750
773
|
end
|
751
774
|
|
752
775
|
def bind_locals(aRuntime, theActuals)
|
@@ -754,12 +777,14 @@ require_relative 'skm_procedure_exec'
|
|
754
777
|
count_actuals = actuals.size
|
755
778
|
|
756
779
|
if (count_actuals < required_arity) ||
|
757
|
-
|
780
|
+
((count_actuals > required_arity) &&
|
781
|
+
!formals.variadic?)
|
758
782
|
# $stderr.puts "Error"
|
759
783
|
# $stderr.puts self.inspect
|
760
784
|
raise StandardError, msg_arity_mismatch(theActuals)
|
761
785
|
end
|
762
786
|
return if count_actuals.zero? && !formals.variadic?
|
787
|
+
|
763
788
|
bind_required_locals(aRuntime, theActuals)
|
764
789
|
if formals.variadic?
|
765
790
|
variadic_part_raw = actuals.drop(required_arity)
|
@@ -784,7 +809,7 @@ require_relative 'skm_procedure_exec'
|
|
784
809
|
# $stderr.puts "Tef #{aProcedureCall.inspect}"
|
785
810
|
# a_def.evaluate(aRuntime)
|
786
811
|
end
|
787
|
-
#aProcedureCall.operands_consumed = true
|
812
|
+
# aProcedureCall.operands_consumed = true
|
788
813
|
end
|
789
814
|
|
790
815
|
def evaluate_sequence(aRuntime)
|
@@ -797,11 +822,11 @@ require_relative 'skm_procedure_exec'
|
|
797
822
|
else
|
798
823
|
result = cmd.evaluate(aRuntime)
|
799
824
|
end
|
800
|
-
rescue NoMethodError =>
|
801
|
-
$stderr.puts
|
825
|
+
rescue NoMethodError => e
|
826
|
+
$stderr.puts inspect
|
802
827
|
$stderr.puts sequence.inspect
|
803
828
|
$stderr.puts cmd.inspect
|
804
|
-
raise
|
829
|
+
raise e
|
805
830
|
end
|
806
831
|
end
|
807
832
|
end
|
@@ -813,7 +838,7 @@ require_relative 'skm_procedure_exec'
|
|
813
838
|
if environment
|
814
839
|
result = self
|
815
840
|
else
|
816
|
-
twin =
|
841
|
+
twin = dup
|
817
842
|
twin.set_cond_environment(aRuntime.environment)
|
818
843
|
result = twin
|
819
844
|
end
|
@@ -822,7 +847,7 @@ require_relative 'skm_procedure_exec'
|
|
822
847
|
end
|
823
848
|
|
824
849
|
def doppelganger(aRuntime)
|
825
|
-
twin =
|
850
|
+
twin = dup
|
826
851
|
twin.set_cond_environment(aRuntime.environment.dup)
|
827
852
|
result = twin
|
828
853
|
|
@@ -834,9 +859,10 @@ require_relative 'skm_procedure_exec'
|
|
834
859
|
# $stderr.puts " Runtime environment: #{theFrame.object_id.to_s(16)}"
|
835
860
|
# $stderr.puts " Called from #{caller(1, 1)}"
|
836
861
|
raise StandardError unless theFrame.kind_of?(SkmFrame)
|
862
|
+
|
837
863
|
unless environment
|
838
864
|
@environment = theFrame
|
839
|
-
|
865
|
+
freeze
|
840
866
|
# $stderr.puts " Lambda's environment updated!"
|
841
867
|
end
|
842
868
|
end
|
@@ -879,16 +905,16 @@ require_relative 'skm_procedure_exec'
|
|
879
905
|
|
880
906
|
def msg_arity_mismatch(actuals)
|
881
907
|
# *** ERROR: wrong number of arguments for #<closure morph> (required 2, got 1)
|
882
|
-
msg1 =
|
908
|
+
msg1 = 'Wrong number of arguments for procedure '
|
883
909
|
count_actuals = actuals.size
|
884
910
|
msg2 = "(required #{required_arity}, got #{count_actuals})"
|
885
911
|
msg1 + msg2
|
886
912
|
end
|
887
913
|
|
888
914
|
def inspect_specific
|
889
|
-
#result = "@environment #{environment.object_id.to_s(16)}, "
|
890
|
-
result = ''
|
891
|
-
if environment
|
915
|
+
# result = "@environment #{environment.object_id.to_s(16)}, "
|
916
|
+
result = +''
|
917
|
+
if environment&.parent
|
892
918
|
result << "Parent environment #{environment.parent.object_id.to_s(16)}, "
|
893
919
|
result << environment.inspect
|
894
920
|
end
|