seeing_is_believing 1.0.1 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,20 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seeing_is_believing
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 1.0.1
4
+ prerelease: 6
5
+ version: 2.0.0.beta1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Josh Cheek
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-13 00:00:00.000000000 Z
12
+ date: 2013-08-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  version_requirements: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: 2.0.0.pre6
20
20
  none: false
@@ -23,7 +23,7 @@ dependencies:
23
23
  prerelease: false
24
24
  requirement: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - '='
26
+ - - ~>
27
27
  - !ruby/object:Gem::Version
28
28
  version: 2.0.0.pre6
29
29
  none: false
@@ -140,10 +140,10 @@ files:
140
140
  - lib/seeing_is_believing/debugger.rb
141
141
  - lib/seeing_is_believing/error.rb
142
142
  - lib/seeing_is_believing/evaluate_by_moving_files.rb
143
- - lib/seeing_is_believing/expression_list.rb
144
143
  - lib/seeing_is_believing/hard_core_ensure.rb
145
144
  - lib/seeing_is_believing/has_exception.rb
146
145
  - lib/seeing_is_believing/line.rb
146
+ - lib/seeing_is_believing/program_rewriter.rb
147
147
  - lib/seeing_is_believing/queue.rb
148
148
  - lib/seeing_is_believing/remove_inline_comments.rb
149
149
  - lib/seeing_is_believing/result.rb
@@ -157,9 +157,9 @@ files:
157
157
  - spec/binary/remove_previous_annotations_spec.rb
158
158
  - spec/debugger_spec.rb
159
159
  - spec/evaluate_by_moving_files_spec.rb
160
- - spec/expression_list_spec.rb
161
160
  - spec/hard_core_ensure_spec.rb
162
161
  - spec/line_spec.rb
162
+ - spec/program_rewriter_spec.rb
163
163
  - spec/queue_spec.rb
164
164
  - spec/seeing_is_believing_spec.rb
165
165
  - spec/syntax_analyzer_spec.rb
@@ -179,9 +179,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
179
179
  none: false
180
180
  required_rubygems_version: !ruby/object:Gem::Requirement
181
181
  requirements:
182
- - - ! '>='
182
+ - - ! '>'
183
183
  - !ruby/object:Gem::Version
184
- version: '0'
184
+ version: 1.3.1
185
185
  none: false
186
186
  requirements: []
187
187
  rubyforge_project: seeing_is_believing
@@ -200,9 +200,9 @@ test_files:
200
200
  - spec/binary/remove_previous_annotations_spec.rb
201
201
  - spec/debugger_spec.rb
202
202
  - spec/evaluate_by_moving_files_spec.rb
203
- - spec/expression_list_spec.rb
204
203
  - spec/hard_core_ensure_spec.rb
205
204
  - spec/line_spec.rb
205
+ - spec/program_rewriter_spec.rb
206
206
  - spec/queue_spec.rb
207
207
  - spec/seeing_is_believing_spec.rb
208
208
  - spec/syntax_analyzer_spec.rb
@@ -1,101 +0,0 @@
1
- require 'open3'
2
- require 'seeing_is_believing/debugger'
3
- require 'seeing_is_believing/syntax_analyzer'
4
-
5
- # can we get better debugging support so that we don't need to drop ANSI escape sequences in the middle of strings?
6
- class SeeingIsBelieving
7
- class ExpressionList
8
- PendingExpression = Struct.new :expression, :children do
9
- # coloured debug because there's so much syntax that I get lost trying to parse the output
10
- def inspect(debug=false)
11
- colour1 = colour2 = lambda { |s| s }
12
- colour1 = lambda { |s| "\e[30;46m#{s}\e[0m" } if debug
13
- colour2 = lambda { |s| "\e[37;46m#{s}\e[0m" } if debug
14
- "#{colour1['PE(']}#{colour2[expression.inspect]}#{colour1[',' ]}#{colour2[children.inspect]}#{colour1[')']}"
15
- end
16
- end
17
-
18
- def initialize(options)
19
- self.debugger = options.fetch :debugger, Debugger.new(enabled: false)
20
- self.get_next_line = options.fetch :get_next_line
21
- self.peek_next_line = options.fetch :peek_next_line
22
- self.on_complete = options.fetch :on_complete
23
- end
24
-
25
- def call
26
- offset, expressions, expression = 0, [], nil
27
- begin
28
- pending_expression = generate(expressions)
29
-
30
- debugger.context debugger_context do
31
- "GENERATED: #{pending_expression.expression.inspect}, ADDING IT TO #{inspected_expressions expressions}"
32
- end
33
-
34
- expression = reduce expressions, offset unless next_line_modifies_current?
35
-
36
- offset += 1
37
- end until expressions.empty?
38
- return expression, offset
39
- end
40
-
41
- private
42
-
43
- attr_accessor :debugger, :get_next_line, :peek_next_line, :on_complete, :expressions
44
-
45
- def debugger_context
46
- "EXPRESSION EVALUATION"
47
- end
48
-
49
- def generate(expressions)
50
- expression = get_next_line.call
51
- raise SyntaxError unless expression
52
- if expressions.last && SyntaxAnalyzer.unfinished_here_doc?(expressions.last.expression)
53
- expressions.last.expression << "\n" << expression # more stupid \n -.-
54
- else
55
- expressions << PendingExpression.new(expression, [])
56
- end
57
- expressions.last
58
- end
59
-
60
- def next_line_modifies_current?
61
- # method invocations can be put on the next line, and begin with a dot.
62
- # I think that's the only case we need to worry about.
63
- # e.g: `3\n.times { |i| p i }`
64
- peek_next_line.call && SyntaxAnalyzer.next_line_modifies_current?(peek_next_line.call)
65
- end
66
-
67
- def inspected_expressions(expressions)
68
- "[#{expressions.map { |pe| pe.inspect debugger.enabled? }.join(', ')}]"
69
- end
70
-
71
- def reduce(expressions, offset)
72
- expressions.size.times do |i|
73
- expression = expressions[i..-1].map { |e| [e.expression, *e.children] }
74
- .flatten
75
- .join("\n") # must use newline otherwise can get expressions like `a\\+b` that should be `a\\\n+b`, former is invalid
76
- return if children_will_never_be_valid? expression
77
- next unless valid_ruby? expression
78
- result = on_complete.call(expressions[i].expression,
79
- expressions[i].children,
80
- expressions[i+1..-1].map { |pe| [pe.expression, pe.children] }.flatten, # hmmm, not sure this is really correct, but it allows it to work for my use cases
81
- offset)
82
- expressions.replace expressions[0, i]
83
- expressions[i-1].children << result unless expressions.empty?
84
- debugger.context(debugger_context) { "REDUCED: #{result.inspect}, LIST: #{inspected_expressions expressions}" }
85
- return result
86
- end
87
- end
88
-
89
- def valid_ruby?(expression)
90
- valid = SyntaxAnalyzer.valid_ruby? expression
91
- debugger.context(debugger_context) { "#{valid ? "\e[32mIS VALID:" : "\e[31mIS NOT VALID:"}: #{expression.inspect}\e[0m" }
92
- valid
93
- end
94
-
95
- def children_will_never_be_valid?(expression)
96
- analyzer = SyntaxAnalyzer.new(expression)
97
- analyzer.parse
98
- analyzer.unclosed_string? || analyzer.unclosed_regexp? || SyntaxAnalyzer.unclosed_comment?(expression)
99
- end
100
- end
101
- end
@@ -1,277 +0,0 @@
1
- require 'seeing_is_believing/expression_list'
2
-
3
- describe SeeingIsBelieving::ExpressionList do
4
-
5
- def list_for(generations, options={}, &block)
6
- described_class.new({
7
- on_complete: block,
8
- get_next_line: -> { generations.shift || raise("EMPTY!") },
9
- peek_next_line: -> { generations.first },
10
- }.merge(options))
11
- end
12
-
13
- def call(generations, options={}, &block)
14
- list_for(generations, options, &block).call
15
- end
16
-
17
- example 'example: multiple children' do
18
- block_invocations = 0
19
- result, size = call %w[begin b+ c x\\ + y end] do |line, children, completions, offset|
20
- case offset
21
- when 2
22
- line.should == 'b+'
23
- children.should == []
24
- completions.should == ['c']
25
- block_invocations += 1
26
- 'b+c'
27
- when 5
28
- line.should == 'x\\'
29
- children.should == []
30
- completions.should == ['+', 'y']
31
- block_invocations += 10
32
- "x+y"
33
- when 6
34
- line.should == 'begin'
35
- children.should == ['b+c', 'x+y']
36
- completions.should == ['end']
37
- block_invocations += 100
38
- 'ALL DONE!'
39
- else
40
- raise "offset: #{offset.inspect}"
41
- end
42
- end
43
- result.should == 'ALL DONE!'
44
- size.should == 7
45
- block_invocations.should == 111
46
- end
47
-
48
-
49
- example 'example: nested children' do
50
- block_invocations = 0
51
- expressions = [ '[1].map do |n1|',
52
- ' [2].map do |n2|',
53
- ' n1 + n2',
54
- ' end',
55
- 'end',
56
- ]
57
- result, size = call expressions do |line, children, completions, offset|
58
- case offset
59
- when 2
60
- [line, children, completions].should == [' n1 + n2', [], []]
61
- block_invocations += 1
62
- when 3
63
- [line, children, completions].should == [' [2].map do |n2|', [' n1 + n2'], [' end']]
64
- block_invocations += 10
65
- when 4
66
- [line, children, completions].should == ['[1].map do |n1|',
67
- [" [2].map do |n2|\n n1 + n2\n end"],
68
- ['end']]
69
- block_invocations += 100
70
- else
71
- raise "line_number: #{line_number.inspect}"
72
- end
73
- [line, *children, *completions].join("\n")
74
- end
75
- block_invocations.should == 111
76
- result.should == "[1].map do |n1|\n"\
77
- " [2].map do |n2|\n"\
78
- " n1 + n2\n"\
79
- " end\n"\
80
- "end"
81
- size.should == 5
82
- end
83
-
84
-
85
- example 'example: completions that have children' do
86
- block_invocations = 0
87
- expressions = [ "[1].map do |n1|",
88
- "[2].map do |n2|",
89
- "n1 + n2",
90
- "end end",
91
- ]
92
- result, size = call expressions do |line, children, completions, offset|
93
- case offset
94
- when 2
95
- [line, children, completions].should == ["n1 + n2", [], []]
96
- block_invocations += 1
97
- when 3
98
- # not really sure what this *should* be like, but if this is the result,
99
- # then it will work for the use cases I need it for
100
- [line, *children, *completions].should == ["[1].map do |n1|",
101
- "[2].map do |n2|",
102
- "n1 + n2",
103
- 'end end']
104
- block_invocations += 10
105
- else
106
- raise "offset: #{offset.inspect}"
107
- end
108
- [line, *children, *completions].join("\n")
109
- end
110
- block_invocations.should == 11
111
- result.should == "[1].map do |n1|\n"\
112
- "[2].map do |n2|\n"\
113
- "n1 + n2\n"\
114
- "end end"
115
- size.should == 4
116
- end
117
-
118
- example 'example: completions who requires its children to be considered for the expression to be valid' do
119
- block_invocations = 0
120
- result, size = call ["if true &&", "true", "1", "end"] do |line, children, completions, offset|
121
- case offset
122
- when 1
123
- [line, children, completions].should == ['true', [], []]
124
- block_invocations += 1
125
- when 2
126
- [line, children, completions].should == ['1', [], []]
127
- block_invocations += 10
128
- when 3
129
- [line, children, completions].should == ['if true &&', ['true', '1'], ['end']]
130
- block_invocations += 100
131
- end
132
- [line, *children, *completions].join("\n")
133
- end
134
- block_invocations.should == 111
135
- result.should == "if true &&\ntrue\n1\nend"
136
- size.should == 4
137
- end
138
-
139
- example 'example: multiline strings with valid code in them' do
140
- block_invocations = 0
141
- call ["'", "1", "'"] do |*expressions, offset|
142
- expressions.join('').should == "'1'"
143
- offset.should == 2
144
- block_invocations += 1
145
- end
146
- block_invocations.should == 1
147
- end
148
-
149
- example 'example: multiline regexps with valid code in them' do
150
- block_invocations = 0
151
- call ['/', '1', '/'] do |*expressions, offset|
152
- expressions.join('').should == "/1/"
153
- offset.should == 2
154
- block_invocations += 1
155
- end
156
- block_invocations.should == 1
157
- end
158
-
159
- example "example: =begin/=end comments" do
160
- block_invocations = 0
161
- call ['=begin', '1', '=end'] do |*expressions, offset|
162
- expressions.join('').should == "=begin1=end"
163
- offset.should == 2
164
- block_invocations += 1
165
- end
166
- block_invocations.should == 1
167
- end
168
-
169
- example "example: heredoc" do
170
- pending 'Not sure how to do this, for now just catch it at a higher level' do
171
- result, size = call ['strings = [<<A, <<-B]', '1', 'A', '2', ' B'] do |*expressions, offset|
172
- offset.should == 1
173
- expressions.should == ['strings = [<<A, <<B]']
174
- 'zomg!'
175
- end
176
- result.should == "zomg!\n1\nA\n2\n B"
177
- size.should == 5
178
- end
179
- end
180
-
181
- example "example: method invocations on next line", not_implemented: true do
182
- pending 'I need to *actually* parse the Ruby in order to be able to identify where to split the expressions :('
183
- # example 1: consume the expression with lines after
184
- list = list_for ['a', '.b', ' .c', 'irrelevant'] do |*expressions, offset|
185
- flat_expressions = expressions.flatten.join('')
186
- case offset
187
- when 0
188
- flat_expressions.should == 'a'
189
- 'A'
190
- when 1
191
- flat_expressions.should == 'A.b'
192
- 'A.B'
193
- when 2
194
- flat_expressions.should == 'A.B .c'
195
- 'A.B.C'
196
- else
197
- raise "O.o"
198
- end
199
- end
200
- list.call.should == ['A.B.C', 3]
201
-
202
- # example 2: consume the expression with no lines after
203
- list = list_for ['a', '.b'] do |*expressions, offset|
204
- flat_expressions = expressions.flatten.join('')
205
- case offset
206
- when 0
207
- flat_expressions.should == 'a'
208
- 'A'
209
- when 1
210
- flat_expressions.should == 'A.b'
211
- 'A.B'
212
- else
213
- raise "O.o"
214
- end
215
- end
216
- list.call.should == ['A.B', 2]
217
- end
218
-
219
- example "example: method invocations on next line with the first line not being its own expression", not_implemented: true do
220
- pending 'I need to *actually* parse the Ruby in order to be able to identify where to split the expressions :('
221
- list = list_for ['x = a', '.b', ' .c', 'irrelevant'] do |*expressions, offset|
222
- flat_expressions = expressions.flatten.join('')
223
- case offset
224
- when 0
225
- flat_expressions.should == 'a'
226
- 'A'
227
- when 1
228
- flat_expressions.should == 'A.b'
229
- 'A.B'
230
- when 2
231
- flat_expressions.should == 'x = A.B .c'
232
- 'X=A.B.C'
233
- else
234
- raise "O.o"
235
- end
236
- end
237
- list.call.should == ['X=A.B.C', 3]
238
-
239
- list = list_for ['puts a', '.b', ' .c', 'irrelevant'] do |*expressions, offset|
240
- flat_expressions = expressions.flatten.join('')
241
- case offset
242
- when 0
243
- flat_expressions.should == 'a'
244
- 'A'
245
- when 1
246
- flat_expressions.should == 'A.b'
247
- 'A.B'
248
- when 2
249
- flat_expressions.should == 'puts A.B .c'
250
- 'PUTS A.B.C'
251
- else
252
- raise "O.o"
253
- end
254
- end
255
- list.call.should == ['PUTS A.B.C', 3]
256
- end
257
-
258
- example "example: smoke test debug option" do
259
- debugger = SeeingIsBelieving::Debugger.new
260
- call(%w[a+ b], debugger: debugger) { |*expressions, _| expressions.join("\n") }
261
- debugger.to_s.should include "GENERATED"
262
- debugger.to_s.should include "REDUCED"
263
- end
264
-
265
- # in reality, the problem may just lie with our lib
266
- # but it should be correct in most cases
267
- it 'Raises a syntax error if it cannot generate the expression' do
268
- generations = ["'"]
269
- expect do
270
- described_class.new(
271
- on_complete: -> { "" },
272
- get_next_line: -> { generations.shift },
273
- peek_next_line: -> { generations.first }
274
- ).call
275
- end.to raise_error SyntaxError
276
- end
277
- end