skeem 0.2.16 → 0.2.20
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 +283 -11
- data/.travis.yml +27 -0
- data/CHANGELOG.md +30 -1
- data/README.md +1 -1
- data/bin/skeem +4 -4
- data/lib/skeem/datum_dsl.rb +36 -35
- data/lib/skeem/grammar.rb +38 -77
- data/lib/skeem/interpreter.rb +8 -4
- data/lib/skeem/primitive/primitive_builder.rb +7 -15
- data/lib/skeem/primitive/primitive_procedure.rb +11 -5
- data/lib/skeem/runtime.rb +8 -10
- data/lib/skeem/s_expr_builder.rb +18 -57
- data/lib/skeem/s_expr_nodes.rb +46 -45
- data/lib/skeem/skeem_exception.rb +1 -0
- data/lib/skeem/skm_binding.rb +4 -5
- data/lib/skeem/skm_compound_datum.rb +2 -3
- data/lib/skeem/skm_element.rb +1 -1
- data/lib/skeem/skm_pair.rb +5 -2
- data/lib/skeem/skm_procedure_exec.rb +3 -0
- data/lib/skeem/skm_simple_datum.rb +12 -10
- data/lib/skeem/skm_unary_expression.rb +25 -26
- data/lib/skeem/tokenizer.rb +14 -7
- data/lib/skeem/version.rb +1 -1
- data/skeem.gemspec +5 -5
- data/spec/skeem/element_visitor_spec.rb +3 -1
- data/spec/skeem/interpreter_spec.rb +3 -1
- data/spec/skeem/lambda_spec.rb +4 -4
- data/spec/skeem/parser_spec.rb +2 -0
- data/spec/skeem/primitive/primitive_builder_spec.rb +5 -5
- data/spec/skeem/primitive/primitive_procedure_spec.rb +1 -1
- data/spec/skeem/runtime_spec.rb +2 -2
- data/spec/skeem/skm_compound_datum_spec.rb +1 -1
- data/spec/skeem/skm_pair_spec.rb +5 -5
- data/spec/skeem/tokenizer_spec.rb +4 -2
- data/spec/spec_helper.rb +13 -10
- metadata +10 -9
data/lib/skeem/s_expr_builder.rb
CHANGED
@@ -24,17 +24,6 @@ module Skeem
|
|
24
24
|
'STRING_LIT' => SkmString
|
25
25
|
}.freeze
|
26
26
|
|
27
|
-
# Create a new AST builder instance.
|
28
|
-
# @param theTokens [Array<Token>] The sequence of input tokens.
|
29
|
-
def initialize(theTokens)
|
30
|
-
super(theTokens)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Notification that the parse tree construction is complete.
|
34
|
-
def done!
|
35
|
-
super
|
36
|
-
end
|
37
|
-
|
38
27
|
protected
|
39
28
|
|
40
29
|
def terminal2node
|
@@ -168,16 +157,6 @@ module Skeem
|
|
168
157
|
pcall
|
169
158
|
end
|
170
159
|
|
171
|
-
# rule('operand_plus' => 'operand_plus operand').as 'multiple_operands'
|
172
|
-
def reduce_multiple_operands(_production, _range, _tokens, theChildren)
|
173
|
-
theChildren[0] << theChildren[1]
|
174
|
-
end
|
175
|
-
|
176
|
-
# rule('operand_plus' => 'operand').as 'last_operand'
|
177
|
-
def reduce_last_operand(_production, _range, _tokens, theChildren)
|
178
|
-
[theChildren.last]
|
179
|
-
end
|
180
|
-
|
181
160
|
# rule('def_formals' => 'identifier_star').as 'def_formals'
|
182
161
|
def reduce_def_formals(_production, _range, _tokens, theChildren)
|
183
162
|
SkmFormals.new(theChildren[0], :fixed)
|
@@ -191,9 +170,10 @@ module Skeem
|
|
191
170
|
|
192
171
|
# rule('lambda_expression' => 'LPAREN LAMBDA formals body RPAREN').as 'lambda_expression'
|
193
172
|
def reduce_lambda_expression(_production, aRange, _tokens, theChildren)
|
194
|
-
lmbd = SkmLambdaRep.new(aRange, theChildren[2], theChildren[3])
|
173
|
+
# lmbd = SkmLambdaRep.new(aRange, theChildren[2], theChildren[3])
|
195
174
|
# $stderr.puts lmbd.inspect
|
196
|
-
lmbd
|
175
|
+
# lmbd
|
176
|
+
SkmLambdaRep.new(aRange, theChildren[2], theChildren[3])
|
197
177
|
end
|
198
178
|
|
199
179
|
# rule('formals' => 'LPAREN identifier_star RPAREN').as 'fixed_arity_formals'
|
@@ -212,16 +192,6 @@ module Skeem
|
|
212
192
|
SkmFormals.new(formals, :variadic)
|
213
193
|
end
|
214
194
|
|
215
|
-
# rule('identifier_plus' => 'identifier_plus IDENTIFIER').as 'multiple_identifiers'
|
216
|
-
def reduce_multiple_identifiers(_production, _range, _tokens, theChildren)
|
217
|
-
theChildren[0] << theChildren[1]
|
218
|
-
end
|
219
|
-
|
220
|
-
# rule('identifier_plus' => 'IDENTIFIER').as 'last_identifier'
|
221
|
-
def reduce_last_identifier(_production, _range, _tokens, theChildren)
|
222
|
-
[theChildren[0]]
|
223
|
-
end
|
224
|
-
|
225
195
|
# rule('body' => 'definition_star sequence').as 'body'
|
226
196
|
def reduce_body(_production, _range, _tokens, theChildren)
|
227
197
|
definitions = theChildren[0].nil? ? [] : theChildren[0]
|
@@ -235,7 +205,8 @@ module Skeem
|
|
235
205
|
|
236
206
|
# rule('conditional' => 'LPAREN IF test consequent alternate RPAREN').as 'conditional'
|
237
207
|
def reduce_conditional(_production, aRange, _tokens, theChildren)
|
238
|
-
|
208
|
+
children = theChildren.flatten
|
209
|
+
SkmCondition.new(aRange, children[2], children[3], children[4])
|
239
210
|
end
|
240
211
|
|
241
212
|
# rule('assignment' => 'LPAREN SET! IDENTIFIER expression RPAREN').as 'assignment'
|
@@ -283,16 +254,6 @@ module Skeem
|
|
283
254
|
SkmBindingBlock.new(:let_star, worker.bindings, body)
|
284
255
|
end
|
285
256
|
|
286
|
-
# rule('cond_clause_plus' => 'cond_clause_plus cond_clause').as 'multiple_cond_clauses'
|
287
|
-
def reduce_multiple_cond_clauses(_production, _range, _tokens, theChildren)
|
288
|
-
theChildren[0] << theChildren[1]
|
289
|
-
end
|
290
|
-
|
291
|
-
# rule('cond_clause_plus' => 'cond_clause').as 'last_cond_clauses'
|
292
|
-
def reduce_last_cond_clauses(_production, _range, _tokens, theChildren)
|
293
|
-
[theChildren[0]]
|
294
|
-
end
|
295
|
-
|
296
257
|
# rule('cond_clause' => 'LPAREN test sequence RPAREN').as 'cond_clause'
|
297
258
|
def reduce_cond_clause(_production, _range, _tokens, theChildren)
|
298
259
|
[theChildren[1], SkmSequencingBlock.new(SkmPair.create_from_a(theChildren[2]))]
|
@@ -328,27 +289,27 @@ module Skeem
|
|
328
289
|
SkmIterationSpec.new(theChildren[1], theChildren[2], nil)
|
329
290
|
end
|
330
291
|
|
331
|
-
# rule('do_result' =>
|
332
|
-
def
|
333
|
-
|
292
|
+
# rule('do_result' => 'sequence?')
|
293
|
+
def reduce_do_result(_production, _range, _tokens, theChildren)
|
294
|
+
children = theChildren.flatten
|
295
|
+
if children.empty?
|
296
|
+
SkmEmptyList.instance
|
297
|
+
else
|
298
|
+
children[0]
|
299
|
+
end
|
334
300
|
end
|
335
301
|
|
302
|
+
# rule('do_result' => []).as 'empty_do_result'
|
303
|
+
# def reduce_empty_do_result(_production, _range, _tokens, _children)
|
304
|
+
# SkmEmptyList.instance
|
305
|
+
# end
|
306
|
+
|
336
307
|
# rule('includer' => 'LPAREN INCLUDE string_plus RPAREN').as 'include'
|
337
308
|
def reduce_include(_production, _range, _tokens, theChildren)
|
338
309
|
includer = SkmIncluder.new(theChildren[2])
|
339
310
|
includer.build
|
340
311
|
end
|
341
312
|
|
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
|
-
|
352
313
|
# rule('list_qq_template' => 'LPAREN qq_template_or_splice_star RPAREN').as 'list_qq'
|
353
314
|
def reduce_list_qq(_production, _range, _tokens, theChildren)
|
354
315
|
SkmPair.create_from_a(theChildren[1])
|
data/lib/skeem/s_expr_nodes.rb
CHANGED
@@ -9,6 +9,8 @@ require_relative 'datum_dsl'
|
|
9
9
|
require_relative 'skm_unary_expression'
|
10
10
|
require_relative 'skm_procedure_exec'
|
11
11
|
|
12
|
+
# rubocop: disable Style/AccessorGrouping
|
13
|
+
|
12
14
|
module Skeem
|
13
15
|
class SkmUndefined
|
14
16
|
include Singleton
|
@@ -103,8 +105,8 @@ module Skeem
|
|
103
105
|
end
|
104
106
|
|
105
107
|
def inspect
|
106
|
-
result = inspect_prefix
|
107
|
-
result <<
|
108
|
+
result = +"#{inspect_prefix}#{operator.inspect}, "
|
109
|
+
result << "@operands #{operands.inspect}#{inspect_suffix}"
|
108
110
|
result
|
109
111
|
end
|
110
112
|
|
@@ -127,12 +129,10 @@ module Skeem
|
|
127
129
|
|
128
130
|
callee = result
|
129
131
|
# callee = fetch_callee(aRuntime, result)
|
130
|
-
when Primitive::PrimitiveProcedure
|
132
|
+
when Primitive::PrimitiveProcedure, SkmLambda
|
131
133
|
callee = operator
|
132
134
|
when SkmLambdaRep
|
133
135
|
callee = operator.evaluate(aRuntime)
|
134
|
-
when SkmLambda
|
135
|
-
callee = operator
|
136
136
|
else
|
137
137
|
result = operator.evaluate(aRuntime)
|
138
138
|
if result.kind_of?(Primitive::PrimitiveProcedure)
|
@@ -145,6 +145,8 @@ module Skeem
|
|
145
145
|
[:callee, callee]
|
146
146
|
end
|
147
147
|
|
148
|
+
# rubocop: disable Style/RedundantAssignment
|
149
|
+
|
148
150
|
def fetch_callee(aRuntime, var_key)
|
149
151
|
begin
|
150
152
|
aRuntime.include?(var_key.value)
|
@@ -174,6 +176,8 @@ module Skeem
|
|
174
176
|
callee
|
175
177
|
end
|
176
178
|
|
179
|
+
# rubocop: enable Style/RedundantAssignment
|
180
|
+
|
177
181
|
def transform_operands(aRuntime)
|
178
182
|
return [] if operands == SkmEmptyList.instance
|
179
183
|
|
@@ -225,9 +229,9 @@ module Skeem
|
|
225
229
|
end
|
226
230
|
|
227
231
|
def inspect
|
228
|
-
result = inspect_prefix
|
229
|
-
result <<
|
230
|
-
result <<
|
232
|
+
result = +"#{inspect_prefix}@test #{test.inspect}, "
|
233
|
+
result << "@consequent #{consequent.inspect}, "
|
234
|
+
result << "@alternate #{alternate.inspect}#{inspect_suffix}"
|
231
235
|
result
|
232
236
|
end
|
233
237
|
|
@@ -236,7 +240,6 @@ module Skeem
|
|
236
240
|
end
|
237
241
|
end # class
|
238
242
|
|
239
|
-
|
240
243
|
class SkmConditional < SkmMultiExpression
|
241
244
|
# An array of couples [test, sequence]
|
242
245
|
attr_reader :clauses
|
@@ -280,20 +283,23 @@ module Skeem
|
|
280
283
|
end
|
281
284
|
|
282
285
|
def inspect
|
283
|
-
result = inspect_prefix
|
286
|
+
result = "#{inspect_prefix}@test #{test.inspect} , "
|
284
287
|
result << "@clauses \n"
|
285
288
|
clauses.each do |(test, consequent)|
|
286
289
|
result << ' ' << test.inspect << ' ' << consequent.inspect << "\n"
|
287
290
|
end
|
288
|
-
result <<
|
291
|
+
result << "@alternate #{alternate.inspect}#{inspect_suffix}"
|
289
292
|
result
|
290
293
|
end
|
291
294
|
end # class
|
292
295
|
|
293
296
|
SkmArity = Struct.new(:low, :high) do
|
297
|
+
# rubocop: disable Style/NumericPredicate
|
298
|
+
|
294
299
|
def nullary?
|
295
300
|
low.zero? && high == 0
|
296
301
|
end
|
302
|
+
# rubocop: enable Style/NumericPredicate
|
297
303
|
|
298
304
|
def variadic?
|
299
305
|
high == '*'
|
@@ -446,6 +452,7 @@ module Skeem
|
|
446
452
|
attr_reader :update_steps
|
447
453
|
|
448
454
|
def initialize(aTest, doResult, theCommands, theUpdates)
|
455
|
+
super(nil)
|
449
456
|
@test = aTest
|
450
457
|
@do_result = doResult
|
451
458
|
@commands = theCommands
|
@@ -546,7 +553,6 @@ module Skeem
|
|
546
553
|
end
|
547
554
|
end # class
|
548
555
|
|
549
|
-
|
550
556
|
# Parse tree representation of a Lambda
|
551
557
|
# - Not bound to a frame (aka environment)
|
552
558
|
# - Knows the parse representation of its embedded definitions
|
@@ -629,9 +635,7 @@ module Skeem
|
|
629
635
|
variadic_part_raw = actuals.drop(required_arity)
|
630
636
|
variadic_part = variadic_part_raw.map do |actual|
|
631
637
|
case actual
|
632
|
-
when ProcedureCall
|
633
|
-
actual.evaluate(aRuntime)
|
634
|
-
when SkmQuotation
|
638
|
+
when ProcedureCall, SkmQuotation
|
635
639
|
actual.evaluate(aRuntime)
|
636
640
|
else
|
637
641
|
to_datum(actual)
|
@@ -697,9 +701,9 @@ module Skeem
|
|
697
701
|
|
698
702
|
def inspect_specific
|
699
703
|
result = +''
|
700
|
-
result <<
|
701
|
-
result <<
|
702
|
-
result <<
|
704
|
+
result << "@formals #{formals.inspect}, "
|
705
|
+
result << "@definitions #{definitions.inspect}, "
|
706
|
+
result << "@sequence #{sequence.inspect}#{inspect_suffix}"
|
703
707
|
|
704
708
|
result
|
705
709
|
end
|
@@ -715,6 +719,7 @@ module Skeem
|
|
715
719
|
def_delegators(:@representation, :formals, :definitions, :sequence)
|
716
720
|
|
717
721
|
def initialize(aRepresentation, aRuntime)
|
722
|
+
super(nil)
|
718
723
|
@representation = aRepresentation
|
719
724
|
@environment = aRuntime.environment
|
720
725
|
end
|
@@ -790,9 +795,7 @@ module Skeem
|
|
790
795
|
variadic_part_raw = actuals.drop(required_arity)
|
791
796
|
variadic_part = variadic_part_raw.map do |actual|
|
792
797
|
case actual
|
793
|
-
when ProcedureCall
|
794
|
-
actual.evaluate(aRuntime)
|
795
|
-
when SkmQuotation
|
798
|
+
when ProcedureCall, SkmQuotation
|
796
799
|
actual.evaluate(aRuntime)
|
797
800
|
else
|
798
801
|
to_datum(actual)
|
@@ -814,21 +817,17 @@ module Skeem
|
|
814
817
|
|
815
818
|
def evaluate_sequence(aRuntime)
|
816
819
|
result = nil
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
else
|
823
|
-
result = cmd.evaluate(aRuntime)
|
824
|
-
end
|
825
|
-
rescue NoMethodError => e
|
826
|
-
$stderr.puts inspect
|
827
|
-
$stderr.puts sequence.inspect
|
828
|
-
$stderr.puts cmd.inspect
|
829
|
-
raise e
|
830
|
-
end
|
820
|
+
sequence&.each do |cmd|
|
821
|
+
if cmd.kind_of?(SkmLambda)
|
822
|
+
result = cmd.dup_cond(aRuntime)
|
823
|
+
else
|
824
|
+
result = cmd.evaluate(aRuntime)
|
831
825
|
end
|
826
|
+
rescue NoMethodError => e
|
827
|
+
$stderr.puts inspect
|
828
|
+
$stderr.puts sequence.inspect
|
829
|
+
$stderr.puts cmd.inspect
|
830
|
+
raise e
|
832
831
|
end
|
833
832
|
|
834
833
|
result
|
@@ -836,24 +835,22 @@ module Skeem
|
|
836
835
|
|
837
836
|
def dup_cond(aRuntime)
|
838
837
|
if environment
|
839
|
-
|
838
|
+
self
|
840
839
|
else
|
841
840
|
twin = dup
|
842
841
|
twin.set_cond_environment(aRuntime.environment)
|
843
|
-
|
842
|
+
twin
|
844
843
|
end
|
845
|
-
|
846
|
-
result
|
847
844
|
end
|
848
845
|
|
849
846
|
def doppelganger(aRuntime)
|
850
847
|
twin = dup
|
851
848
|
twin.set_cond_environment(aRuntime.environment.dup)
|
852
|
-
|
853
|
-
|
854
|
-
result
|
849
|
+
twin
|
855
850
|
end
|
856
851
|
|
852
|
+
# rubocop: disable Naming/AccessorMethodName
|
853
|
+
|
857
854
|
def set_cond_environment(theFrame)
|
858
855
|
# $stderr.puts "Lambda #{object_id.to_s(16)}, env [#{environment.object_id.to_s(16)}]"
|
859
856
|
# $stderr.puts " Runtime environment: #{theFrame.object_id.to_s(16)}"
|
@@ -867,6 +864,8 @@ module Skeem
|
|
867
864
|
end
|
868
865
|
end
|
869
866
|
|
867
|
+
# rubocop: enable Naming/AccessorMethodName
|
868
|
+
|
870
869
|
private
|
871
870
|
|
872
871
|
# Purpose: bind each formal from lambda to an actual value from the call
|
@@ -918,12 +917,14 @@ module Skeem
|
|
918
917
|
result << "Parent environment #{environment.parent.object_id.to_s(16)}, "
|
919
918
|
result << environment.inspect
|
920
919
|
end
|
921
|
-
result <<
|
922
|
-
result <<
|
923
|
-
result <<
|
920
|
+
result << "@formals #{formals.inspect}, "
|
921
|
+
result << "@definitions #{definitions.inspect}, "
|
922
|
+
result << "@sequence #{sequence.inspect}#{inspect_suffix}"
|
924
923
|
|
925
924
|
result
|
926
925
|
end
|
927
926
|
end # class
|
928
927
|
end # module
|
928
|
+
|
929
|
+
# rubocop: enable Style/AccessorGrouping
|
929
930
|
# End of file
|
@@ -0,0 +1 @@
|
|
1
|
+
# frozen_string_literal: true
|
data/lib/skeem/skm_binding.rb
CHANGED
@@ -17,10 +17,13 @@ module Skeem
|
|
17
17
|
# @param anIdentifier [SkmIdentifier] The variable name
|
18
18
|
# @param aValue [SkmElement] The value to bind to the variable.
|
19
19
|
def initialize(anIdentifier, aValue)
|
20
|
+
super(nil)
|
20
21
|
@variable = anIdentifier
|
21
22
|
@value = aValue
|
22
23
|
end
|
23
24
|
|
25
|
+
# rubocop: disable Style/NegatedIfElseCondition
|
26
|
+
|
24
27
|
def evaluate(aRuntime)
|
25
28
|
name = variable.evaluate(aRuntime)
|
26
29
|
|
@@ -42,6 +45,7 @@ module Skeem
|
|
42
45
|
binding_action(aRuntime, name, result)
|
43
46
|
result
|
44
47
|
end
|
48
|
+
# rubocop: enable Style/NegatedIfElseCondition
|
45
49
|
|
46
50
|
protected
|
47
51
|
|
@@ -59,7 +63,6 @@ module Skeem
|
|
59
63
|
end
|
60
64
|
end # class
|
61
65
|
|
62
|
-
|
63
66
|
class SkmUpdateBinding < SkmBinding
|
64
67
|
protected
|
65
68
|
|
@@ -71,10 +74,6 @@ module Skeem
|
|
71
74
|
class SkmDelayedUpdateBinding < SkmBinding
|
72
75
|
attr_reader :new_val
|
73
76
|
|
74
|
-
def initialize(anIdentifier, aValue)
|
75
|
-
super(anIdentifier, aValue)
|
76
|
-
end
|
77
|
-
|
78
77
|
def do_it!(aRuntime)
|
79
78
|
aRuntime.update_binding(variable, new_val)
|
80
79
|
end
|
@@ -22,13 +22,12 @@ module Skeem
|
|
22
22
|
def ==(other)
|
23
23
|
return true if equal?(other)
|
24
24
|
|
25
|
-
|
25
|
+
case other
|
26
26
|
when SkmCompoundDatum
|
27
27
|
self.class == other.class && members == other.members
|
28
28
|
when Array
|
29
29
|
members == other
|
30
30
|
end
|
31
|
-
result
|
32
31
|
end
|
33
32
|
|
34
33
|
alias eqv? equal?
|
@@ -70,7 +69,7 @@ module Skeem
|
|
70
69
|
|
71
70
|
def inspect_specific
|
72
71
|
result = +''
|
73
|
-
members.each { |elem| result << elem.inspect
|
72
|
+
members.each { |elem| result << "#{elem.inspect}, " }
|
74
73
|
result.sub!(/, $/, '')
|
75
74
|
result
|
76
75
|
end
|
data/lib/skeem/skm_element.rb
CHANGED
data/lib/skeem/skm_pair.rb
CHANGED
@@ -4,7 +4,10 @@ require_relative 'skm_empty_list'
|
|
4
4
|
|
5
5
|
module Skeem
|
6
6
|
class SkmPair < SkmElement
|
7
|
+
# @return [SkmElement]
|
7
8
|
attr_accessor :car
|
9
|
+
|
10
|
+
# @return [SkmElement]
|
8
11
|
attr_accessor :cdr
|
9
12
|
|
10
13
|
alias first car
|
@@ -168,8 +171,8 @@ module Skeem
|
|
168
171
|
begin
|
169
172
|
result = clone_evaluate(aRuntime)
|
170
173
|
rescue NoMethodError => e
|
171
|
-
$stderr.puts
|
172
|
-
$stderr.puts
|
174
|
+
$stderr.puts "SkmPair#evaluate: #{inspect}"
|
175
|
+
$stderr.puts "SkmPair as Array: #{to_a.inspect}"
|
173
176
|
raise e
|
174
177
|
end
|
175
178
|
end
|
@@ -6,7 +6,10 @@ module Skeem
|
|
6
6
|
# Abstract class. Root of class hierarchy needed for Interpreter
|
7
7
|
# design pattern
|
8
8
|
class SkmSimpleDatum < SkmElement
|
9
|
+
# @return [Rley::Syntax::Token] token object corresponding to Skeem element
|
9
10
|
attr_reader :token
|
11
|
+
|
12
|
+
# @return [Object]
|
10
13
|
attr_reader :value
|
11
14
|
|
12
15
|
def initialize(aToken, aPosition)
|
@@ -37,13 +40,11 @@ module Skeem
|
|
37
40
|
def ==(other)
|
38
41
|
return true if equal?(other)
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
result
|
43
|
+
if other.kind_of?(SkmSimpleDatum)
|
44
|
+
value == other.value
|
45
|
+
else
|
46
|
+
value == other
|
47
|
+
end
|
47
48
|
end
|
48
49
|
|
49
50
|
alias eqv? ==
|
@@ -104,10 +105,12 @@ module Skeem
|
|
104
105
|
false
|
105
106
|
end
|
106
107
|
|
108
|
+
# rubocop: disable Style/NegatedIfElseCondition
|
109
|
+
|
107
110
|
def eqv?(other)
|
108
111
|
return true if equal?(other)
|
109
112
|
|
110
|
-
|
113
|
+
if other.kind_of?(SkmNumber)
|
111
114
|
if exact? != other.exact?
|
112
115
|
false
|
113
116
|
else
|
@@ -116,9 +119,8 @@ module Skeem
|
|
116
119
|
else
|
117
120
|
value == other
|
118
121
|
end
|
119
|
-
|
120
|
-
result
|
121
122
|
end
|
123
|
+
# rubocop: enable Style/NegatedIfElseCondition
|
122
124
|
end # class
|
123
125
|
|
124
126
|
class SkmReal < SkmNumber
|
@@ -76,8 +76,7 @@ module Skeem
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def quasiquote(aRuntime)
|
79
|
-
|
80
|
-
result
|
79
|
+
evaluate(aRuntime)
|
81
80
|
end
|
82
81
|
|
83
82
|
protected
|
@@ -115,7 +114,10 @@ module Skeem
|
|
115
114
|
class SkmBindingBlock < SkmUnaryExpression
|
116
115
|
alias body child
|
117
116
|
|
117
|
+
# @return [Symbol] One of: :let, :let_star
|
118
118
|
attr_reader :kind
|
119
|
+
|
120
|
+
# @return [Array<SkmBinding>]
|
119
121
|
attr_reader :bindings
|
120
122
|
|
121
123
|
def initialize(theKind, theBindings, aBody)
|
@@ -126,14 +128,15 @@ module Skeem
|
|
126
128
|
|
127
129
|
def evaluate(aRuntime)
|
128
130
|
aRuntime.push(SkmFrame.new(aRuntime.environment))
|
129
|
-
|
131
|
+
case kind
|
132
|
+
when :let
|
130
133
|
locals = bindings.map do |bnd|
|
131
134
|
SkmBinding.new(bnd.variable, bnd.value.evaluate(aRuntime))
|
132
135
|
end
|
133
136
|
locals.each do |bnd|
|
134
137
|
aRuntime.add_binding(bnd.variable.evaluate(aRuntime), bnd.value)
|
135
138
|
end
|
136
|
-
|
139
|
+
when :let_star
|
137
140
|
bindings.each do |bnd|
|
138
141
|
val = bnd.value.evaluate(aRuntime)
|
139
142
|
aRuntime.add_binding(bnd.variable.evaluate(aRuntime), val)
|
@@ -186,18 +189,16 @@ module Skeem
|
|
186
189
|
def eval_pair(aRuntime)
|
187
190
|
result = nil
|
188
191
|
sequence.to_a.each do |cmd|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
result = cmd.evaluate(aRuntime)
|
194
|
-
end
|
195
|
-
rescue NoMethodError => e
|
196
|
-
$stderr.puts inspect
|
197
|
-
$stderr.puts sequence.inspect
|
198
|
-
$stderr.puts cmd.inspect
|
199
|
-
raise e
|
192
|
+
if cmd.kind_of?(SkmLambda)
|
193
|
+
result = cmd.dup_cond(aRuntime)
|
194
|
+
else
|
195
|
+
result = cmd.evaluate(aRuntime)
|
200
196
|
end
|
197
|
+
rescue NoMethodError => e
|
198
|
+
$stderr.puts inspect
|
199
|
+
$stderr.puts sequence.inspect
|
200
|
+
$stderr.puts cmd.inspect
|
201
|
+
raise e
|
201
202
|
end
|
202
203
|
|
203
204
|
result
|
@@ -215,18 +216,16 @@ module Skeem
|
|
215
216
|
|
216
217
|
if sequence[:sequence].kind_of?(SkmPair)
|
217
218
|
sequence[:sequence].to_a.each do |cmd|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
result = cmd.evaluate(aRuntime)
|
223
|
-
end
|
224
|
-
rescue NoMethodError => e
|
225
|
-
$stderr.puts inspect
|
226
|
-
$stderr.puts sequence[:sequence].inspect
|
227
|
-
$stderr.puts cmd.inspect
|
228
|
-
raise e
|
219
|
+
if cmd.kind_of?(SkmLambda)
|
220
|
+
result = cmd.dup_cond(aRuntime)
|
221
|
+
else
|
222
|
+
result = cmd.evaluate(aRuntime)
|
229
223
|
end
|
224
|
+
rescue NoMethodError => e
|
225
|
+
$stderr.puts inspect
|
226
|
+
$stderr.puts sequence[:sequence].inspect
|
227
|
+
$stderr.puts cmd.inspect
|
228
|
+
raise e
|
230
229
|
end
|
231
230
|
else
|
232
231
|
result = sequence.evaluate(aRuntime)
|