skeem 0.2.17 → 0.2.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -138,7 +138,7 @@ module Skeem
138
138
  end
139
139
 
140
140
  def inspect_specific
141
- raise NotImplementedError, "Missing #{self.class.to_s + '#' + 'inspect_specific'}"
141
+ raise NotImplementedError, "Missing #{self.class}#inspect_specific"
142
142
  end
143
143
  end # struct
144
144
  end # module
@@ -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 'SkmPair#evaluate: ' + inspect
172
- $stderr.puts 'SkmPair as Array: ' + to_a.inspect
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
@@ -4,7 +4,10 @@ require_relative 'runtime'
4
4
 
5
5
  module Skeem
6
6
  class SkmProcedureExec
7
+ # @return [SkmFrame]
7
8
  attr_reader :frame
9
+
10
+ # @return [SkmLambda]
8
11
  attr_reader :definition
9
12
 
10
13
  def initialize(aLambda)
@@ -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
- result = if other.kind_of?(SkmSimpleDatum)
41
- value == other.value
42
- else
43
- value == other
44
- end
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
- result = if other.kind_of?(SkmNumber)
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
- result = evaluate(aRuntime)
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
- if kind == :let
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
- elsif kind == :let_star
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
- begin
190
- if cmd.kind_of?(SkmLambda)
191
- result = cmd.dup_cond(aRuntime)
192
- else
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
- begin
219
- if cmd.kind_of?(SkmLambda)
220
- result = cmd.dup_cond(aRuntime)
221
- else
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)
@@ -16,8 +16,13 @@ module Skeem
16
16
  # Delimiters: parentheses '(', ')'
17
17
  # Separators: comma
18
18
  class Tokenizer
19
+ # @return [StringScanner]
19
20
  attr_reader(:scanner)
21
+
22
+ # @return [Integer] Current line number
20
23
  attr_reader(:lineno)
24
+
25
+ # @return [Integer] Offset of start of current line
21
26
  attr_reader(:line_start)
22
27
 
23
28
  @@lexeme2name = {
@@ -53,7 +58,7 @@ module Skeem
53
58
  SYNTAX-RULES
54
59
  UNQUOTE
55
60
  UNQUOTE-SPLICING
56
- ].map { |x| [x, x] }.to_h
61
+ ].map { |x| [x, x.sub(/\*$/, '_STAR')] }.to_h
57
62
 
58
63
  class ScanError < StandardError; end
59
64
 
@@ -162,11 +167,10 @@ other literal data (section 2.4).
162
167
  if (lexeme = scanner.scan(/#\\/))
163
168
  if (lexeme = scanner.scan(/(?:alarm|backspace|delete|escape|newline|null|return|space|tab)/))
164
169
  token = build_token('CHAR', lexeme, :name)
165
- elsif (lexeme = scanner.scan(/[^x]/))
166
- token = build_token('CHAR', lexeme, :escaped)
167
170
  elsif (lexeme = scanner.scan(/x[0-9a-fA-F]+/))
168
171
  token = build_token('CHAR', lexeme, :hex_value)
169
- elsif (lexeme = scanner.scan(/x/))
172
+ else
173
+ lexeme = scanner.getch
170
174
  token = build_token('CHAR', lexeme, :escaped)
171
175
  end
172
176
  end
data/lib/skeem/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Skeem
4
- VERSION = '0.2.17'
4
+ VERSION = '0.2.18'
5
5
  end
data/skeem.gemspec CHANGED
@@ -24,7 +24,8 @@ module PkgExtending
24
24
  'lib/**/*.rb',
25
25
  'lib/**/*.skm',
26
26
  'spec/**/*.rb',
27
- 'spec/**/*.skm'
27
+ 'spec/**/*.skm',
28
+ 'spec/**/*.yml'
28
29
  ]
29
30
  aPackage.files = file_list
30
31
  aPackage.test_files = Dir['spec/**/*_spec.rb']
@@ -53,7 +54,7 @@ DESCR
53
54
  SUMMARY
54
55
  spec.homepage = 'https://github.com/famished-tiger/Skeem'
55
56
  spec.license = 'MIT'
56
- spec.required_ruby_version = '>= 2.3.0'
57
+ spec.required_ruby_version = '>= 2.5.0'
57
58
 
58
59
  spec.bindir = 'bin'
59
60
  spec.executables << 'skeem'
@@ -61,7 +62,7 @@ SUMMARY
61
62
  PkgExtending.pkg_files(spec)
62
63
  PkgExtending.pkg_documentation(spec)
63
64
  # Runtime dependencies
64
- spec.add_dependency 'rley', '~> 0.7'
65
+ spec.add_dependency 'rley', '~> 0.8.03'
65
66
 
66
67
  # Development dependencies
67
68
  spec.add_development_dependency 'bundler', '~> 2.0'
@@ -12,7 +12,9 @@ module Skeem
12
12
  let(:simple_datum) { integer 42 }
13
13
  let(:listener) do
14
14
  fake = double('fake-subscriber')
15
- fake.define_singleton_method(:accept_all) {}
15
+ fake.define_singleton_method(:accept_all) do
16
+ # Dummy block
17
+ end
16
18
  fake
17
19
  end
18
20
 
@@ -16,7 +16,7 @@ module Skeem
16
16
  end
17
17
 
18
18
  it 'could be initialized with a block argument' do
19
- expect { Interpreter.new { |interp| } }.not_to raise_error
19
+ expect { Interpreter.new(&:runtime) }.not_to raise_error
20
20
  end
21
21
 
22
22
  it 'should have a parser' do
@@ -67,6 +67,7 @@ module Skeem
67
67
  end
68
68
  end
69
69
 
70
+ # rubocop: disable Style/ExponentialNotation
70
71
  it 'should evaluate isolated real numbers' do
71
72
  samples = [
72
73
  ['0.0', 0.0],
@@ -80,6 +81,7 @@ module Skeem
80
81
  expect(result).to eq(predicted)
81
82
  end
82
83
  end
84
+ # rubocop: enable Style/ExponentialNotation
83
85
 
84
86
  it 'should evaluate isolated strings' do
85
87
  samples = [
@@ -31,7 +31,7 @@ SKEEM
31
31
 
32
32
  context 'Defining compound procedures:' do
33
33
  it 'should accept the definition of simple procedure with arity 1' do
34
- source = definition_set + "\n" + 'square'
34
+ source = "#{definition_set}\nsquare"
35
35
  result = subject.run(source)
36
36
 
37
37
  square = result.last
@@ -41,7 +41,7 @@ SKEEM
41
41
  end
42
42
 
43
43
  it 'should accept the definition of simple procedure with arity 2' do
44
- source = definition_set + "\n" + 'sum-of-squares'
44
+ source = "#{definition_set}\nsum-of-squares"
45
45
  result = subject.run(source)
46
46
 
47
47
  square = result.last
@@ -65,14 +65,14 @@ SKEEM
65
65
  end
66
66
 
67
67
  it 'should support the call to a simple procedure with arity 2' do
68
- source = definition_set + "\n" + '(sum-of-squares 3 4)'
68
+ source = "#{definition_set}\n(sum-of-squares 3 4)"
69
69
  result = subject.run(source)
70
70
 
71
71
  expect(result.last).to eq(25)
72
72
  end
73
73
 
74
74
  it 'should support the call to a nested lambda procedure' do
75
- source = definition_set + "\n" + '(f 5)'
75
+ source = "#{definition_set}\n(f 5)"
76
76
  result = subject.run(source)
77
77
 
78
78
  expect(result.last).to eq(136)
@@ -45,6 +45,7 @@ module Skeem
45
45
  end
46
46
  end
47
47
 
48
+ # rubocop: disable Style/ExponentialNotation
48
49
  it 'should parse isolated real numbers' do
49
50
  samples = [
50
51
  ['0.0', 0.0],
@@ -59,6 +60,7 @@ module Skeem
59
60
  expect(ptree.root.value).to eq(predicted)
60
61
  end
61
62
  end
63
+ # rubocop: enable Style/ExponentialNotation
62
64
 
63
65
  it 'should parse isolated strings' do
64
66
  samples = [
@@ -654,8 +654,8 @@ SKEEM
654
654
  ["(append '(a b) '(c d))", array2list_ids(%w[a b c d])],
655
655
  ["(append '(a b) '(c) 'd)", array2list_ids(%w[a b c d])],
656
656
  ["(append '(a (b)) '((c)))", [SkmIdentifier.create('a'),
657
- SkmPair.create_from_a(array2list_ids(['b'])),
658
- SkmPair.create_from_a(array2list_ids(['c']))]],
657
+ SkmPair.create_from_a(array2list_ids(['b'])),
658
+ SkmPair.create_from_a(array2list_ids(['c']))]],
659
659
  ["(append '() 'a)", SkmIdentifier.create('a')]
660
660
  ]
661
661
  compare_to_predicted(checks) do |result, expectation|
@@ -919,8 +919,8 @@ SKEEM
919
919
  result = subject.run(source)
920
920
  expect(result).to be_kind_of(SkmVector)
921
921
  expectation = [SkmInteger.create(0),
922
- SkmPair.new(SkmString.create('Sue'), SkmPair.new(SkmString.create('Sue'), SkmEmptyList.instance)),
923
- SkmString.create('Anna')]
922
+ SkmPair.new(SkmString.create('Sue'), SkmPair.new(SkmString.create('Sue'), SkmEmptyList.instance)),
923
+ SkmString.create('Anna')]
924
924
  expect(result).to eq(expectation)
925
925
 
926
926
  source = <<-SKEEM
@@ -1010,7 +1010,7 @@ SKEEM
1010
1010
  err = StandardError
1011
1011
  msg1 = 'Error: assertion failed on line 3, column 4'
1012
1012
  msg2 = 'with <Skeem::SkmBoolean: false>'
1013
- expect { subject.run(source) }.to raise_error(err, msg1 + ', ' + msg2)
1013
+ expect { subject.run(source) }.to raise_error(err, "#{msg1}, #{msg2}")
1014
1014
  end
1015
1015
  end # context
1016
1016
  end # describe
@@ -149,7 +149,7 @@ module Skeem
149
149
  expect(pproc.call(rtime, no_arg)).to eq(0)
150
150
 
151
151
  many = [SkmString.create('foo'), SkmString.create('bar'),
152
- SkmString.create('quux')]
152
+ SkmString.create('quux')]
153
153
  expect(pproc.call(rtime, many)).to eq(3)
154
154
  end
155
155
  end # context
@@ -50,7 +50,7 @@ module Skeem
50
50
  it 'should return its text representation' do
51
51
  txt1 = '<Skeem::SkmCompoundDatum: <Skeem::SkmInteger: 1>,'
52
52
  txt2 = '<Skeem::SkmInteger: 2>, <Skeem::SkmInteger: 3>>'
53
- expect(subject.inspect).to eq(txt1 + ' ' + txt2)
53
+ expect(subject.inspect).to eq("#{txt1} #{txt2}")
54
54
  end
55
55
  end # context
56
56
 
@@ -37,7 +37,7 @@ module Skeem
37
37
 
38
38
  context 'Provided services:' do
39
39
  let(:runtime) { Runtime.new(SkmFrame.new) }
40
- let(:list_length_2) { SkmPair.new(integer(10), subject) }
40
+ let(:list_length2) { SkmPair.new(integer(10), subject) }
41
41
  let(:quirk_element) { double('three') }
42
42
  let(:quirk_members) { [integer(10), quirk_element] }
43
43
 
@@ -71,7 +71,7 @@ module Skeem
71
71
  expect(subject.length).to eq(1)
72
72
 
73
73
  # Use a list of length 2
74
- expect(list_length_2.length).to eq(2)
74
+ expect(list_length2.length).to eq(2)
75
75
  end
76
76
 
77
77
  it 'should respond false to `eqv?` message' do
@@ -113,7 +113,7 @@ module Skeem
113
113
  expect(subject.to_a).to eq([sample_car])
114
114
 
115
115
  # Use a list of length 2
116
- expect(list_length_2.to_a).to eq([integer(10), sample_car])
116
+ expect(list_length2.to_a).to eq([integer(10), sample_car])
117
117
  end
118
118
 
119
119
  it 'should return the last pair of a proper list' do
@@ -133,7 +133,7 @@ module Skeem
133
133
 
134
134
  it 'should return the last element of a list' do
135
135
  expect(subject.last).to eq(sample_car)
136
- expect(list_length_2.last).to eq(sample_car)
136
+ expect(list_length2.last).to eq(sample_car)
137
137
  end
138
138
 
139
139
  it 'should append a new element to a list' do
@@ -227,7 +227,7 @@ module Skeem
227
227
  expect(subject.inspect).to eq(predicted)
228
228
 
229
229
  predicted = '<Skeem::SkmPair: <Skeem::SkmInteger: 10>, <Skeem::SkmInteger: 3>>'
230
- expect(list_length_2.inspect).to eq(predicted)
230
+ expect(list_length2.inspect).to eq(predicted)
231
231
  end
232
232
  end # context
233
233
  end # describe