skeem 0.0.23 → 0.0.24

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.
@@ -0,0 +1,233 @@
1
+ require 'ostruct'
2
+ require_relative '../spec_helper' # Use the RSpec framework
3
+ require_relative '../../lib/skeem/skm_simple_datum' # Load the classes under test
4
+
5
+ module Skeem
6
+ describe SkmSimpleDatum do
7
+ let(:pos) { double('fake-position') }
8
+ let(:dummy_symbol) { double('fake-symbol') }
9
+ let(:sample_value) { 'sample-value' }
10
+ let(:dummy_token) do
11
+ obj = OpenStruct.new
12
+ obj.terminal = dummy_symbol
13
+ obj.lexeme = sample_value
14
+ obj
15
+ end
16
+ let(:instance) { SkmSimpleDatum.create(3) }
17
+ subject { SkmSimpleDatum.new(dummy_token, pos) }
18
+
19
+ context 'Initialization:' do
20
+ it 'should be initialized with a token and a position' do
21
+ expect { SkmSimpleDatum.new(dummy_token, pos) }.not_to raise_error
22
+ end
23
+
24
+ it 'could be created with just a value' do
25
+ expect { SkmSimpleDatum.create(3) }.not_to raise_error
26
+ expect(instance).to be_kind_of(SkmSimpleDatum)
27
+ expect(instance.value).to eq(3)
28
+ end
29
+
30
+ it 'should know its token' do
31
+ expect(subject.token).to eq(dummy_token)
32
+ end
33
+
34
+ it 'should know its value' do
35
+ expect(subject.value).to eq(sample_value)
36
+ end
37
+
38
+ it "should know the token's symbol" do
39
+ expect(subject.symbol).to eq(dummy_symbol)
40
+ end
41
+ end # context
42
+
43
+ context 'Provided services:' do
44
+ let(:runtime) { double('fake-runtime') }
45
+
46
+ it 'should assert that it is equal to itself' do
47
+ expect(subject).to eq(subject)
48
+ end
49
+
50
+ it 'should assert the equality by value' do
51
+ # Comparison with other instances
52
+ expect(instance).to eq(SkmSimpleDatum.create(3))
53
+ expect(instance).not_to eq(SkmSimpleDatum.create('foo'))
54
+
55
+ # Comparison with PORO values
56
+ expect(instance).to eq(3)
57
+ expect(instance).not_to eq('foo')
58
+ end
59
+
60
+ it 'should be self-evaluating' do
61
+ expect(subject.evaluate(runtime)).to be_equal(subject)
62
+ end
63
+
64
+ it 'should be self-quasiquoting' do
65
+ expect(subject.quasiquote(runtime)).to be_equal(subject)
66
+ end
67
+
68
+ it 'should return its text representation' do
69
+ expect(subject.inspect).to eq("<Skeem::SkmSimpleDatum: sample-value>")
70
+ end
71
+
72
+ it 'should respond to visitor' do
73
+ visitor = double('fake-visitor')
74
+ expect(visitor).to receive(:visit_simple_datum).with(subject)
75
+ expect { subject.accept(visitor) }.not_to raise_error
76
+ end
77
+ end # context
78
+ end # describe
79
+
80
+ describe SkmBoolean do
81
+ let(:pos) { double('fake-position') }
82
+ let(:dummy_symbol) { double('BOOLEAN') }
83
+ let(:sample_value) { false }
84
+ let(:dummy_token) do
85
+ obj = OpenStruct.new
86
+ obj.terminal = dummy_symbol
87
+ obj.lexeme = sample_value
88
+ obj
89
+ end
90
+ subject { SkmBoolean.new(dummy_token, pos) }
91
+
92
+ context 'Initialization:' do
93
+ it 'should be initialized with a token and a position' do
94
+ expect { SkmBoolean.new(dummy_token, pos) }.not_to raise_error
95
+ end
96
+
97
+ it 'should react positively to boolean? predicate' do
98
+ expect(subject).to be_boolean
99
+ end
100
+ end # context
101
+
102
+ context 'Provided services:' do
103
+ it 'should return its text representation' do
104
+ expect(subject.inspect).to eq('<Skeem::SkmBoolean: false>')
105
+ end
106
+ end # context
107
+ end # describe
108
+
109
+ describe SkmNumber do
110
+ let(:pos) { double('fake-position') }
111
+ let(:dummy_symbol) { double('dummy') }
112
+ let(:sample_value) { 0.5100 }
113
+ let(:dummy_token) do
114
+ obj = OpenStruct.new
115
+ obj.terminal = dummy_symbol
116
+ obj.lexeme = sample_value
117
+ obj
118
+ end
119
+ subject { SkmNumber.new(dummy_token, pos) }
120
+
121
+ context 'Initialization:' do
122
+ it 'should be initialized with a token and a position' do
123
+ expect { SkmNumber.new(dummy_token, pos) }.not_to raise_error
124
+ end
125
+ end # context
126
+
127
+ context 'Provided services:' do
128
+ it 'should react positively to number? predicate' do
129
+ expect(subject).to be_number
130
+ end
131
+
132
+ it 'should return its text representation' do
133
+ expect(subject.inspect).to eq('<Skeem::SkmNumber: 0.51>')
134
+ end
135
+ end # context
136
+ end # describe
137
+
138
+ describe SkmReal do
139
+ let(:pos) { double('fake-position') }
140
+ let(:dummy_symbol) { double('dummy') }
141
+ let(:sample_value) { 0.5100 }
142
+ let(:dummy_token) do
143
+ obj = OpenStruct.new
144
+ obj.terminal = dummy_symbol
145
+ obj.lexeme = sample_value
146
+ obj
147
+ end
148
+ subject { SkmReal.new(dummy_token, pos) }
149
+
150
+ context 'Provided services:' do
151
+ it 'should react positively to number? predicate' do
152
+ expect(subject).to be_number
153
+ end
154
+
155
+ it 'should react positively to real? predicate' do
156
+ expect(subject).to be_real
157
+ end
158
+ end # context
159
+ end # describe
160
+
161
+ describe SkmInteger do
162
+ let(:pos) { double('fake-position') }
163
+ let(:dummy_symbol) { double('dummy') }
164
+ let(:sample_value) { 3 }
165
+ let(:dummy_token) do
166
+ obj = OpenStruct.new
167
+ obj.terminal = dummy_symbol
168
+ obj.lexeme = sample_value
169
+ obj
170
+ end
171
+ subject { SkmInteger.new(dummy_token, pos) }
172
+
173
+ context 'Provided services:' do
174
+ it 'should react positively to number? predicate' do
175
+ expect(subject).to be_number
176
+ end
177
+
178
+ it 'should react positively to real? predicate' do
179
+ expect(subject).to be_real
180
+ end
181
+
182
+ it 'should react positively to integer? predicate' do
183
+ expect(subject).to be_real
184
+ end
185
+ end # context
186
+ end # describe
187
+
188
+ describe SkmString do
189
+ let(:pos) { double('fake-position') }
190
+ let(:dummy_symbol) { double('dummy') }
191
+ let(:sample_value) { 'Hello' }
192
+ let(:dummy_token) do
193
+ obj = OpenStruct.new
194
+ obj.terminal = dummy_symbol
195
+ obj.lexeme = sample_value
196
+ obj
197
+ end
198
+ subject { SkmString.new(dummy_token, pos) }
199
+
200
+ context 'Provided services:' do
201
+ it 'should react positively to string? predicate' do
202
+ expect(subject).to be_string
203
+ end
204
+
205
+ it 'should return its text representation' do
206
+ expect(subject.inspect).to eq('<Skeem::SkmString: Hello>')
207
+ end
208
+ end # context
209
+ end # describe
210
+
211
+ describe SkmIdentifier do
212
+ let(:pos) { double('fake-position') }
213
+ let(:dummy_symbol) { double('dummy') }
214
+ let(:sample_value) { 'this-is-it!' }
215
+ let(:dummy_token) do
216
+ obj = OpenStruct.new
217
+ obj.terminal = dummy_symbol
218
+ obj.lexeme = sample_value
219
+ obj
220
+ end
221
+ subject { SkmIdentifier.new(dummy_token, pos) }
222
+
223
+ context 'Provided services:' do
224
+ it 'should react positively to symbol? predicate' do
225
+ expect(subject).to be_symbol
226
+ end
227
+
228
+ it 'should return its text representation' do
229
+ expect(subject.inspect).to eq('<Skeem::SkmIdentifier: this-is-it!>')
230
+ end
231
+ end # context
232
+ end # describe
233
+ end # module
@@ -0,0 +1,201 @@
1
+ require_relative '../spec_helper' # Use the RSpec framework
2
+ require_relative '../../lib/skeem/datum_dsl'
3
+ require_relative '../../lib/skeem/environment'
4
+ require_relative '../../lib/skeem/skm_unary_expression' # Load the classes under test
5
+
6
+ module Skeem
7
+ describe SkmUnaryExpression do
8
+ let(:pos) { double('fake-position') }
9
+ let(:sample_child) { double('fake-child') }
10
+
11
+ subject { SkmUnaryExpression.new(pos, sample_child) }
12
+
13
+ context 'Initialization:' do
14
+ it 'should be initialized with a position and a child element' do
15
+ expect{ SkmUnaryExpression.new(pos, sample_child) }.not_to raise_error
16
+ end
17
+
18
+ it 'should know its child' do
19
+ expect(subject.child).to eq(sample_child)
20
+ end
21
+ end # context
22
+
23
+ context 'Provided basic services:' do
24
+ it 'should respond to visitor' do
25
+ visitor = double('fake-visitor')
26
+ expect(visitor).to receive(:visit_unary_expression).with(subject)
27
+ expect { subject.accept(visitor) }.not_to raise_error
28
+ end
29
+ end # context
30
+ end # describe
31
+
32
+ describe SkmQuotation do
33
+ include DatumDSL
34
+
35
+ let(:sample_literal) { string('foo') }
36
+
37
+ subject { SkmQuotation.new(sample_literal) }
38
+
39
+ context 'Initialization:' do
40
+ it 'should be initialized with a Skeem element' do
41
+ expect{ SkmQuotation.new(sample_literal) }.not_to raise_error
42
+ end
43
+
44
+ it 'should know its datum' do
45
+ expect(subject.datum).to be_equal(sample_literal)
46
+ expect(subject.datum).to be_equal(subject.child)
47
+ end
48
+ end # context
49
+
50
+ context 'Provided services:' do
51
+ let(:runtime) { Runtime.new(Environment.new) }
52
+
53
+ # it 'should return the child(datum) at evaluation' do
54
+ # expect(subject.evaluate(runtime)).to be_equal(subject.child)
55
+ # end
56
+
57
+ it 'should implement quasiquotation' do
58
+ # Case 1: child is idempotent with quasiquote
59
+ expect(subject.quasiquote(runtime)).to be_equal(subject)
60
+
61
+ # Case 2: quasiquoted child is different
62
+ child = double('fake-child')
63
+ expect(child).to receive(:quasiquote).with(runtime).and_return(integer(3))
64
+ instance = SkmQuasiquotation.new(child)
65
+ expect(instance.child).to eq(child)
66
+ quasi_result = instance.quasiquote(runtime)
67
+ expect(quasi_result).to eq(3)
68
+ end
69
+
70
+ it 'should return its text representation' do
71
+ txt1 = '<Skeem::SkmQuotation: <Skeem::SkmString: foo>>'
72
+ expect(subject.inspect).to eq(txt1)
73
+ end
74
+ end # context
75
+ end # describe
76
+
77
+
78
+ describe SkmQuasiquotation do
79
+ include DatumDSL
80
+
81
+ let(:sample_literal) { string('foo') }
82
+
83
+ subject { SkmQuasiquotation.new(sample_literal) }
84
+
85
+ context 'Initialization:' do
86
+ it 'should be initialized with a Skeem element' do
87
+ expect{ SkmQuasiquotation.new(sample_literal) }.not_to raise_error
88
+ end
89
+ end # context
90
+
91
+ context 'Provided services:' do
92
+ let(:runtime) { Runtime.new(Environment.new) }
93
+
94
+ it 'should return the child(template) at evaluation' do
95
+ expect(subject.evaluate(runtime)).to be_equal(subject.child)
96
+ end
97
+
98
+ it 'should accept quasiquotation' do
99
+ # Case 1: child is idempotent with quasiquote
100
+ expect(subject.quasiquote(runtime)).to be_equal(subject.child)
101
+
102
+ # Case 2: quasiquoted child is different
103
+ child = double('fake-child')
104
+ expect(child).to receive(:quasiquote).with(runtime).and_return(integer(3))
105
+ instance = SkmQuotation.new(child)
106
+ expect(instance.child).to eq(child)
107
+ quasi_result = instance.quasiquote(runtime)
108
+ expect(quasi_result.child).to eq(3)
109
+ end
110
+
111
+ it 'should return its text representation' do
112
+ txt1 = '<Skeem::SkmQuasiquotation: <Skeem::SkmString: foo>>'
113
+ expect(subject.inspect).to eq(txt1)
114
+ end
115
+ end # context
116
+ end # describe
117
+
118
+
119
+ describe SkmUnquotation do
120
+ include DatumDSL
121
+
122
+ let(:sample_literal) { string('foo') }
123
+
124
+ subject { SkmUnquotation.new(sample_literal) }
125
+
126
+ context 'Initialization:' do
127
+ it 'should be initialized with a Skeem element' do
128
+ expect{ SkmUnquotation.new(sample_literal) }.not_to raise_error
129
+ end
130
+ end # context
131
+
132
+ context 'Provided services:' do
133
+ let(:runtime) { Runtime.new(Environment.new) }
134
+
135
+ it 'should return the child(template) at evaluation' do
136
+ expect(subject.evaluate(runtime)).to be_equal(subject.child)
137
+ end
138
+
139
+ it 'should accept quasiquotation' do
140
+ # Case 1: child is idempotent with evaluate
141
+ expect(subject.quasiquote(runtime)).to be_equal(subject.child)
142
+
143
+ # Case 2: quasiquoted child is different
144
+ child = double('fake-child')
145
+ expect(child).to receive(:evaluate).with(runtime).and_return(integer(3))
146
+ instance = SkmUnquotation.new(child)
147
+ expect(instance.child).to eq(child)
148
+ quasi_result = instance.quasiquote(runtime)
149
+ expect(quasi_result).to eq(3)
150
+ end
151
+
152
+ it 'should return its text representation' do
153
+ txt1 = '<Skeem::SkmUnquotation: <Skeem::SkmString: foo>>'
154
+ expect(subject.inspect).to eq(txt1)
155
+ end
156
+ end # context
157
+ end # describe
158
+
159
+ describe SkmVariableReference do
160
+ include DatumDSL
161
+
162
+ let(:pos) { double('fake-position') }
163
+ let(:sample_var) { identifier('three') }
164
+
165
+ subject { SkmVariableReference.new(pos, sample_var) }
166
+
167
+ context 'Initialization:' do
168
+ it 'should be initialized with a position and a symbol' do
169
+ expect{ SkmVariableReference.new(pos, sample_var) }.not_to raise_error
170
+ end
171
+
172
+ it 'should know its variable' do
173
+ expect(subject.variable).to be_equal(sample_var)
174
+ expect(subject.variable).to be_equal(subject.child)
175
+ end
176
+ end # context
177
+
178
+ context 'Provided services:' do
179
+ let(:dummy_def) { double('fake-definition') }
180
+ let(:runtime) { Runtime.new(Environment.new) }
181
+
182
+ before(:each) do
183
+ runtime.define('three', dummy_def)
184
+ end
185
+
186
+ it "should return the variable's value at evaluation" do
187
+ expect(dummy_def).to receive(:expression).and_return(integer(3))
188
+ expect(subject.evaluate(runtime)).to eq(3)
189
+ end
190
+
191
+ it "should return itself at quasiquotation" do
192
+ expect(subject.quasiquote(runtime)).to be_equal(subject)
193
+ end
194
+
195
+ it 'should return its text representation' do
196
+ txt1 = '<Skeem::SkmVariableReference: <Skeem::SkmIdentifier: three>>'
197
+ expect(subject.inspect).to eq(txt1)
198
+ end
199
+ end # context
200
+ end # describe
201
+ end # module
@@ -30,11 +30,14 @@ module Skeem
30
30
 
31
31
  context 'Delimiter and separator token recognition:' do
32
32
  it 'should tokenize single char delimiters' do
33
- subject.reinitialize("( ) ' `")
33
+ subject.reinitialize("( ) ' ` . , ,@")
34
34
  tokens = subject.tokens
35
35
  tokens.each { |token| expect(token).to be_kind_of(SToken) }
36
36
  terminals = tokens.map(&:terminal)
37
- prediction = %w[LPAREN RPAREN APOSTROPHE BACKQUOTE]
37
+ prediction = %w[LPAREN RPAREN APOSTROPHE
38
+ GRAVE_ACCENT PERIOD
39
+ COMMA COMMA_AT_SIGN
40
+ ]
38
41
  expect(terminals).to eq(prediction)
39
42
  end
40
43
  end # context
@@ -195,38 +198,8 @@ module Skeem
195
198
  expect(token.lexeme).to eq('Second text')
196
199
  end
197
200
  end
198
- =begin
199
- context 'Scanning Scheme sample code' do
200
- it 'should read examples from lis.py page' do
201
- # Shallow tokenizer testing
202
- source = <<-SCHEME
203
- (if (> (val x) 0)
204
- (fn (+ (aref A i) (* 3 i))
205
- (quote (one two)))
206
- end
207
- end
208
- SCHEME
209
- subject.reinitialize(source)
210
- expect { subject.tokens }.not_to raise_error
211
-
212
- source = "(define circle-area (lambda (r) (* pi (* r r))))"
213
- subject.reinitialize(source)
214
- expect { subject.tokens }.not_to raise_error
215
-
216
- source = "(define fact (lambda (n) (if (<= n 1) 1 (* n (fact (- n 1))))))"
217
- subject.reinitialize(source)
218
- expect { subject.tokens }.not_to raise_error
219
-
220
- source = <<-SCHEME
221
- define first car)
222
- define rest cdr)
223
- define count (lambda (item L) (if L (+ (equal? item (first L)) (count item (rest L))) 0)))
224
- count 0 (list 0 1 2 3 0 0))
225
- SCHEME
226
- subject.reinitialize(source)
227
- expect { subject.tokens }.not_to raise_error
228
- end
229
201
 
202
+ context 'Scanning Scheme sample code' do
230
203
  it 'should produce a sequence of token objects' do
231
204
  # Deeper tokenizer testing
232
205
  source = "(define circle-area (lambda (r) (* pi (* r r))))"
@@ -236,7 +209,7 @@ SCHEME
236
209
  ['DEFINE', 'define'],
237
210
  ['IDENTIFIER', 'circle-area'],
238
211
  ['LPAREN', '('],
239
- ['IDENTIFIER', 'lambda'],
212
+ ['LAMBDA', 'lambda'],
240
213
  ['LPAREN', '('],
241
214
  ['IDENTIFIER', 'r'],
242
215
  ['RPAREN', ')'],
@@ -255,6 +228,5 @@ SCHEME
255
228
  match_expectations(subject, predicted)
256
229
  end
257
230
  end # context
258
- =end
259
231
  end # describe
260
232
  end # module
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skeem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.23
4
+ version: 0.0.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-24 00:00:00.000000000 Z
11
+ date: 2018-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley
@@ -85,7 +85,8 @@ files:
85
85
  - Rakefile
86
86
  - appveyor.yml
87
87
  - lib/skeem.rb
88
- - lib/skeem/convertible.rb
88
+ - lib/skeem/datum_dsl.rb
89
+ - lib/skeem/element_visitor.rb
89
90
  - lib/skeem/environment.rb
90
91
  - lib/skeem/grammar.rb
91
92
  - lib/skeem/interpreter.rb
@@ -95,11 +96,18 @@ files:
95
96
  - lib/skeem/runtime.rb
96
97
  - lib/skeem/s_expr_builder.rb
97
98
  - lib/skeem/s_expr_nodes.rb
99
+ - lib/skeem/skm_compound_datum.rb
100
+ - lib/skeem/skm_element.rb
101
+ - lib/skeem/skm_expression.rb
102
+ - lib/skeem/skm_simple_datum.rb
103
+ - lib/skeem/skm_unary_expression.rb
98
104
  - lib/skeem/standard/base.skm
99
105
  - lib/skeem/stoken.rb
100
106
  - lib/skeem/tokenizer.rb
101
107
  - lib/skeem/version.rb
102
108
  - skeem.gemspec
109
+ - spec/skeem/datum_dsl_spec.rb
110
+ - spec/skeem/element_visitor_spec.rb
103
111
  - spec/skeem/environment_spec.rb
104
112
  - spec/skeem/interpreter_spec.rb
105
113
  - spec/skeem/parser_spec.rb
@@ -107,6 +115,10 @@ files:
107
115
  - spec/skeem/primitive/primitive_procedure_spec.rb
108
116
  - spec/skeem/runtime_spec.rb
109
117
  - spec/skeem/s_expr_nodes_spec.rb
118
+ - spec/skeem/skm_compound_datum_spec.rb
119
+ - spec/skeem/skm_element_spec.rb
120
+ - spec/skeem/skm_simple_datum_spec.rb
121
+ - spec/skeem/skm_unary_expression_spec.rb
110
122
  - spec/skeem/tokenizer_spec.rb
111
123
  - spec/skeem_spec.rb
112
124
  - spec/spec_helper.rb
@@ -137,12 +149,18 @@ specification_version: 4
137
149
  summary: Skeem is an interpreter of a subset of the Scheme programming language. Scheme
138
150
  is a descendent of the Lisp language.
139
151
  test_files:
152
+ - spec/skeem/datum_dsl_spec.rb
153
+ - spec/skeem/element_visitor_spec.rb
140
154
  - spec/skeem/environment_spec.rb
141
155
  - spec/skeem/interpreter_spec.rb
142
156
  - spec/skeem/parser_spec.rb
143
157
  - spec/skeem/primitive/primitive_builder_spec.rb
144
158
  - spec/skeem/primitive/primitive_procedure_spec.rb
145
159
  - spec/skeem/runtime_spec.rb
160
+ - spec/skeem/skm_compound_datum_spec.rb
161
+ - spec/skeem/skm_element_spec.rb
162
+ - spec/skeem/skm_simple_datum_spec.rb
163
+ - spec/skeem/skm_unary_expression_spec.rb
146
164
  - spec/skeem/s_expr_nodes_spec.rb
147
165
  - spec/skeem/tokenizer_spec.rb
148
166
  - spec/skeem_spec.rb
@@ -1,23 +0,0 @@
1
- require_relative 's_expr_nodes'
2
-
3
- module Skeem
4
- module Convertible
5
- # Convert Ruby object into its Skeem counterpart
6
- def to_skm(native_obj)
7
- return native_obj if native_obj.kind_of?(SkmElement)
8
-
9
- case native_obj
10
- when TrueClass, FalseClass
11
- SkmBoolean.create(native_obj)
12
- when Float
13
- SkmReal.create(native_obj)
14
- when Integer
15
- SkmInteger.create(native_obj)
16
- when String
17
- SkmString.create(native_obj)
18
- else
19
- raise StandardError, "No conversion of #{native_obj.class}"
20
- end
21
- end
22
- end # module
23
- end # module