seeing_is_believing 1.0.1 → 2.0.0.beta1

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.
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