skeem 0.2.17 → 0.2.18

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.
data/lib/skeem/grammar.rb CHANGED
@@ -9,7 +9,7 @@ module Skeem
9
9
  # Official Small Scheme grammar is available at:
10
10
  # https://bitbucket.org/cowan/r7rs/src/draft-10/rnrs/r7rs.pdf
11
11
  # Names of grammar elements are based on the R7RS documentation
12
- builder = Rley::Syntax::GrammarBuilder.new do
12
+ builder = Rley::grammar_builder do
13
13
  # Delimiters, separators...
14
14
  add_terminals('APOSTROPHE', 'COMMA', 'COMMA_AT_SIGN')
15
15
  add_terminals('GRAVE_ACCENT', 'LPAREN', 'RPAREN')
@@ -22,7 +22,7 @@ module Skeem
22
22
 
23
23
  # Keywords...
24
24
  add_terminals('BEGIN', 'COND', 'DEFINE', 'DEFINE-SYNTAX', 'DO')
25
- add_terminals('ELSE', 'IF', 'INCLUDE', 'LAMBDA', 'LET', 'LET*')
25
+ add_terminals('ELSE', 'IF', 'INCLUDE', 'LAMBDA', 'LET', 'LET_STAR')
26
26
  add_terminals('QUOTE', 'QUASIQUOTE', 'SET!', 'SYNTAX-RULES')
27
27
  add_terminals('UNQUOTE', 'UNQUOTE-SPLICING')
28
28
 
@@ -108,7 +108,7 @@ module Skeem
108
108
  rule('derived_expression' => 'LPAREN LET LPAREN binding_spec_star RPAREN body RPAREN').as 'short_let_form'
109
109
  # TODO: implement "named let"
110
110
  rule('derived_expression' => 'LPAREN LET IDENTIFIER LPAREN binding_spec_star RPAREN body RPAREN') # .as 'named_form'
111
- rule('derived_expression' => 'LPAREN LET* LPAREN binding_spec_star RPAREN body RPAREN').as 'let_star_form'
111
+ rule('derived_expression' => 'LPAREN LET_STAR LPAREN binding_spec_star RPAREN body RPAREN').as 'let_star_form'
112
112
 
113
113
  # As the R7RS grammar is too restrictive,
114
114
  # the next rule was made more general than its standard counterpart
@@ -45,7 +45,7 @@ module Skeem
45
45
  end
46
46
 
47
47
  def add_standard(_runtime)
48
- std_pathname = File.dirname(__FILE__) + '/standard/base.skm'
48
+ std_pathname = "#{File.dirname(__FILE__)}/standard/base.skm"
49
49
  load_lib(std_pathname)
50
50
  end
51
51
 
@@ -234,20 +234,17 @@ module Skeem
234
234
  if arglist.empty?
235
235
  raw_result = reciprocal(raw_result)
236
236
  else
237
- # Ugly: Ruby version dependency: Rubies older than 2.4 have class Fixnum instead of Integer
238
- int_class = (RUBY_VERSION[0..2] < '2.4') ? Fixnum : Integer
239
-
240
237
  arglist.each do |elem|
241
238
  elem_value = elem.value
242
239
  case [raw_result.class, elem_value.class]
243
- when [int_class, int_class]
240
+ when [Integer, Integer]
244
241
  if raw_result.modulo(elem_value).zero?
245
242
  raw_result /= elem_value
246
243
  else
247
244
  raw_result = Rational(raw_result, elem_value)
248
245
  end
249
246
 
250
- when [int_class, Rational]
247
+ when [Integer, Rational]
251
248
  raw_result *= reciprocal(elem_value)
252
249
 
253
250
  when [Rational, Rational]
@@ -827,8 +824,6 @@ module Skeem
827
824
  cloned = arg.klone
828
825
  if result.kind_of?(SkmEmptyList)
829
826
  result = cloned
830
- elsif result.kind_of?(SkmEmptyList)
831
- result = SkmPair.new(arg, SkmEmptyList.instance)
832
827
  else
833
828
  result.append_list(cloned)
834
829
  end
@@ -945,7 +940,7 @@ module Skeem
945
940
  break
946
941
  end
947
942
  pair = pair.cdr
948
- break unless pair&.kind_of?(SkmPair)
943
+ break unless pair.kind_of?(SkmPair)
949
944
  end
950
945
  end
951
946
 
@@ -967,7 +962,7 @@ module Skeem
967
962
  break
968
963
  end
969
964
  pair = pair.cdr
970
- break unless pair&.kind_of?(SkmPair)
965
+ break unless pair.kind_of?(SkmPair)
971
966
  end
972
967
  end
973
968
 
@@ -1142,7 +1137,7 @@ module Skeem
1142
1137
  # Error: assertion failed: (> 1 2)
1143
1138
  msg1 = "assertion failed on line #{pos.line}, column #{pos.column}"
1144
1139
  msg2 = ", with #{arg_evaluated.inspect}"
1145
- raise StandardError, 'Error: ' + msg1 + msg2
1140
+ raise StandardError, "Error: #{msg1}#{msg2}"
1146
1141
  else
1147
1142
  boolean(true)
1148
1143
  end
@@ -1165,7 +1160,7 @@ module Skeem
1165
1160
  # Non-standard procedure reserved for internal testing/debugging purposes.
1166
1161
  def create_inspect(aRuntime)
1167
1162
  primitive = lambda do |_runtime, arg_evaluated|
1168
- $stderr.puts 'INSPECT>' + arg_evaluated.inspect
1163
+ $stderr.puts "INSPECT>#{arg_evaluated.inspect}"
1169
1164
  Skeem::SkmUndefined.instance
1170
1165
  end
1171
1166
  define_primitive_proc(aRuntime, '_inspect', unary, primitive)
@@ -1233,7 +1228,7 @@ module Skeem
1233
1228
  else
1234
1229
  msg2 = "but got #{argument.class}"
1235
1230
  end
1236
- raise StandardError, msg1 + ' ' + msg2
1231
+ raise StandardError, "#{msg1} #{msg2}"
1237
1232
  end
1238
1233
 
1239
1234
  def remaining_args(arglist, aRuntime)
@@ -42,10 +42,11 @@ module Skeem
42
42
  check_actual_count(actuals)
43
43
  # TODO: check that next line became useless
44
44
  # aProcedureCall.operands_consumed = true
45
- result = do_call(aRuntime, actuals)
45
+ # result = do_call(aRuntime, actuals)
46
46
  # $stderr.puts " Result: #{result.inspect}"
47
47
  # $stderr.puts "--- End of procedure #{identifier}"
48
- result
48
+ # result
49
+ do_call(aRuntime, actuals)
49
50
  end
50
51
 
51
52
  def skm_equal?(other)
@@ -146,20 +147,20 @@ module Skeem
146
147
 
147
148
  def error_lambda(message_suffix)
148
149
  msg1 = "Primitive procedure '#{identifier.value}'"
149
- raise StandardError, msg1 + ' ' + message_suffix
150
+ raise StandardError, "#{msg1} #{message_suffix}"
150
151
  end
151
152
 
152
153
  def discrepancy_arity_argument_count(arity_required, count_param, delta)
153
154
  msg1 = "Discrepancy in primitive procedure '#{identifier.value}'"
154
155
  msg2 = "between arity (#{arity_required}) + #{delta}"
155
156
  msg3 = "and parameter count of lambda #{count_param}."
156
- raise StandardError, msg1 + ' ' + msg2 + ' ' + msg3
157
+ raise StandardError, "#{msg1} #{msg2} #{msg3}"
157
158
  end
158
159
 
159
160
  def wrong_number_arguments(required, actual)
160
161
  msg1 = "Wrong number of arguments for #<Procedure #{identifier.value}>"
161
162
  msg2 = "(required at least #{required}, got #{actual})"
162
- raise StandardError, msg1 + ' ' + msg2
163
+ raise StandardError, "#{msg1} #{msg2}"
163
164
  end
164
165
  end # class
165
166
  end # module
data/lib/skeem/runtime.rb CHANGED
@@ -124,16 +124,14 @@ module Skeem
124
124
  private
125
125
 
126
126
  def normalize_key(aKey)
127
- result = case aKey
128
- when String
129
- aKey
130
- when SkmVariableReference
131
- aKey.child.value
132
- else
133
- aKey.evaluate(self).value
134
- end
135
-
136
- result
127
+ case aKey
128
+ when String
129
+ aKey
130
+ when SkmVariableReference
131
+ aKey.child.value
132
+ else
133
+ aKey.evaluate(self).value
134
+ end
137
135
  end
138
136
  end # class
139
137
  end # module
@@ -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
@@ -191,9 +180,10 @@ module Skeem
191
180
 
192
181
  # rule('lambda_expression' => 'LPAREN LAMBDA formals body RPAREN').as 'lambda_expression'
193
182
  def reduce_lambda_expression(_production, aRange, _tokens, theChildren)
194
- lmbd = SkmLambdaRep.new(aRange, theChildren[2], theChildren[3])
183
+ # lmbd = SkmLambdaRep.new(aRange, theChildren[2], theChildren[3])
195
184
  # $stderr.puts lmbd.inspect
196
- lmbd
185
+ # lmbd
186
+ SkmLambdaRep.new(aRange, theChildren[2], theChildren[3])
197
187
  end
198
188
 
199
189
  # rule('formals' => 'LPAREN identifier_star RPAREN').as 'fixed_arity_formals'
@@ -103,8 +103,8 @@ module Skeem
103
103
  end
104
104
 
105
105
  def inspect
106
- result = inspect_prefix + operator.inspect + ', '
107
- result << '@operands ' + operands.inspect + inspect_suffix
106
+ result = +"#{inspect_prefix}#{operator.inspect}, "
107
+ result << "@operands #{operands.inspect}#{inspect_suffix}"
108
108
  result
109
109
  end
110
110
 
@@ -127,12 +127,10 @@ module Skeem
127
127
 
128
128
  callee = result
129
129
  # callee = fetch_callee(aRuntime, result)
130
- when Primitive::PrimitiveProcedure
130
+ when Primitive::PrimitiveProcedure, SkmLambda
131
131
  callee = operator
132
132
  when SkmLambdaRep
133
133
  callee = operator.evaluate(aRuntime)
134
- when SkmLambda
135
- callee = operator
136
134
  else
137
135
  result = operator.evaluate(aRuntime)
138
136
  if result.kind_of?(Primitive::PrimitiveProcedure)
@@ -225,9 +223,9 @@ module Skeem
225
223
  end
226
224
 
227
225
  def inspect
228
- result = inspect_prefix + '@test ' + test.inspect + ', '
229
- result << '@consequent ' + consequent.inspect + ', '
230
- result << '@alternate ' + alternate.inspect + inspect_suffix
226
+ result = +"#{inspect_prefix}@test #{test.inspect}, "
227
+ result << "@consequent #{consequent.inspect}, "
228
+ result << "@alternate #{alternate.inspect}#{inspect_suffix}"
231
229
  result
232
230
  end
233
231
 
@@ -236,7 +234,6 @@ module Skeem
236
234
  end
237
235
  end # class
238
236
 
239
-
240
237
  class SkmConditional < SkmMultiExpression
241
238
  # An array of couples [test, sequence]
242
239
  attr_reader :clauses
@@ -280,20 +277,23 @@ module Skeem
280
277
  end
281
278
 
282
279
  def inspect
283
- result = inspect_prefix + '@test ' + test.inspect + ', '
280
+ result = "#{inspect_prefix}@test #{test.inspect} , "
284
281
  result << "@clauses \n"
285
282
  clauses.each do |(test, consequent)|
286
283
  result << ' ' << test.inspect << ' ' << consequent.inspect << "\n"
287
284
  end
288
- result << '@alternate ' + alternate.inspect + inspect_suffix
285
+ result << "@alternate #{alternate.inspect}#{inspect_suffix}"
289
286
  result
290
287
  end
291
288
  end # class
292
289
 
293
290
  SkmArity = Struct.new(:low, :high) do
291
+ # rubocop: disable Style/NumericPredicate
292
+
294
293
  def nullary?
295
294
  low.zero? && high == 0
296
295
  end
296
+ # rubocop: enable Style/NumericPredicate
297
297
 
298
298
  def variadic?
299
299
  high == '*'
@@ -446,6 +446,7 @@ module Skeem
446
446
  attr_reader :update_steps
447
447
 
448
448
  def initialize(aTest, doResult, theCommands, theUpdates)
449
+ super(nil)
449
450
  @test = aTest
450
451
  @do_result = doResult
451
452
  @commands = theCommands
@@ -546,7 +547,6 @@ module Skeem
546
547
  end
547
548
  end # class
548
549
 
549
-
550
550
  # Parse tree representation of a Lambda
551
551
  # - Not bound to a frame (aka environment)
552
552
  # - Knows the parse representation of its embedded definitions
@@ -629,9 +629,7 @@ module Skeem
629
629
  variadic_part_raw = actuals.drop(required_arity)
630
630
  variadic_part = variadic_part_raw.map do |actual|
631
631
  case actual
632
- when ProcedureCall
633
- actual.evaluate(aRuntime)
634
- when SkmQuotation
632
+ when ProcedureCall, SkmQuotation
635
633
  actual.evaluate(aRuntime)
636
634
  else
637
635
  to_datum(actual)
@@ -697,9 +695,9 @@ module Skeem
697
695
 
698
696
  def inspect_specific
699
697
  result = +''
700
- result << '@formals ' + formals.inspect + ', '
701
- result << '@definitions ' + definitions.inspect + ', '
702
- result << '@sequence ' + sequence.inspect + inspect_suffix
698
+ result << "@formals #{formals.inspect}, "
699
+ result << "@definitions #{definitions.inspect}, "
700
+ result << "@sequence #{sequence.inspect}#{inspect_suffix}"
703
701
 
704
702
  result
705
703
  end
@@ -715,6 +713,7 @@ module Skeem
715
713
  def_delegators(:@representation, :formals, :definitions, :sequence)
716
714
 
717
715
  def initialize(aRepresentation, aRuntime)
716
+ super(nil)
718
717
  @representation = aRepresentation
719
718
  @environment = aRuntime.environment
720
719
  end
@@ -790,9 +789,7 @@ module Skeem
790
789
  variadic_part_raw = actuals.drop(required_arity)
791
790
  variadic_part = variadic_part_raw.map do |actual|
792
791
  case actual
793
- when ProcedureCall
794
- actual.evaluate(aRuntime)
795
- when SkmQuotation
792
+ when ProcedureCall, SkmQuotation
796
793
  actual.evaluate(aRuntime)
797
794
  else
798
795
  to_datum(actual)
@@ -814,20 +811,17 @@ module Skeem
814
811
 
815
812
  def evaluate_sequence(aRuntime)
816
813
  result = nil
817
- if sequence&.each do |cmd|
818
- begin
819
- if cmd.kind_of?(SkmLambda)
820
- result = cmd.dup_cond(aRuntime)
821
- else
822
- result = cmd.evaluate(aRuntime)
823
- end
824
- rescue NoMethodError => e
825
- $stderr.puts inspect
826
- $stderr.puts sequence.inspect
827
- $stderr.puts cmd.inspect
828
- raise e
829
- end
814
+ sequence&.each do |cmd|
815
+ if cmd.kind_of?(SkmLambda)
816
+ result = cmd.dup_cond(aRuntime)
817
+ else
818
+ result = cmd.evaluate(aRuntime)
830
819
  end
820
+ rescue NoMethodError => e
821
+ $stderr.puts inspect
822
+ $stderr.puts sequence.inspect
823
+ $stderr.puts cmd.inspect
824
+ raise e
831
825
  end
832
826
 
833
827
  result
@@ -835,22 +829,18 @@ module Skeem
835
829
 
836
830
  def dup_cond(aRuntime)
837
831
  if environment
838
- result = self
832
+ self
839
833
  else
840
834
  twin = dup
841
835
  twin.set_cond_environment(aRuntime.environment)
842
- result = twin
836
+ twin
843
837
  end
844
-
845
- result
846
838
  end
847
839
 
848
840
  def doppelganger(aRuntime)
849
841
  twin = dup
850
842
  twin.set_cond_environment(aRuntime.environment.dup)
851
- result = twin
852
-
853
- result
843
+ twin
854
844
  end
855
845
 
856
846
  def set_cond_environment(theFrame)
@@ -917,9 +907,9 @@ module Skeem
917
907
  result << "Parent environment #{environment.parent.object_id.to_s(16)}, "
918
908
  result << environment.inspect
919
909
  end
920
- result << '@formals ' + formals.inspect + ', '
921
- result << '@definitions ' + definitions.inspect + ', '
922
- result << '@sequence ' + sequence.inspect + inspect_suffix
910
+ result << "@formals #{formals.inspect}, "
911
+ result << "@definitions #{definitions.inspect}, "
912
+ result << "@sequence #{sequence.inspect}#{inspect_suffix}"
923
913
 
924
914
  result
925
915
  end
@@ -0,0 +1 @@
1
+ # frozen_string_literal: true
@@ -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
- result = case other
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