skeem 0.0.23 → 0.0.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -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