to_source 0.1.3 → 0.2.16

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.
Files changed (89) hide show
  1. data/.gitignore +6 -6
  2. data/.rspec +1 -0
  3. data/.travis.yml +12 -1
  4. data/Changelog.md +115 -0
  5. data/Gemfile +5 -3
  6. data/Gemfile.devtools +67 -0
  7. data/Guardfile +18 -0
  8. data/LICENSE +21 -0
  9. data/README.md +52 -0
  10. data/Rakefile +3 -8
  11. data/TODO +9 -0
  12. data/bin/to_source +17 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +2 -0
  15. data/config/roodi.yml +26 -0
  16. data/config/site.reek +97 -0
  17. data/config/yardstick.yml +2 -0
  18. data/lib/to_source/command.rb +106 -0
  19. data/lib/to_source/emitter/access.rb +28 -0
  20. data/lib/to_source/emitter/actual_arguments.rb +89 -0
  21. data/lib/to_source/emitter/alias.rb +27 -0
  22. data/lib/to_source/emitter/assignment.rb +119 -0
  23. data/lib/to_source/emitter/attribute_assignment.rb +28 -0
  24. data/lib/to_source/emitter/begin.rb +71 -0
  25. data/lib/to_source/emitter/binary_operator.rb +63 -0
  26. data/lib/to_source/emitter/binary_operator_method.rb +58 -0
  27. data/lib/to_source/emitter/block.rb +29 -0
  28. data/lib/to_source/emitter/block_argument.rb +23 -0
  29. data/lib/to_source/emitter/block_pass.rb +23 -0
  30. data/lib/to_source/emitter/case.rb +85 -0
  31. data/lib/to_source/emitter/class.rb +44 -0
  32. data/lib/to_source/emitter/concat_arguments.rb +28 -0
  33. data/lib/to_source/emitter/default_arguments.rb +22 -0
  34. data/lib/to_source/emitter/define.rb +99 -0
  35. data/lib/to_source/emitter/defined.rb +24 -0
  36. data/lib/to_source/emitter/element_assignment.rb +29 -0
  37. data/lib/to_source/emitter/element_reference.rb +25 -0
  38. data/lib/to_source/emitter/empty_body.rb +21 -0
  39. data/lib/to_source/emitter/ensure.rb +50 -0
  40. data/lib/to_source/emitter/ensure_body.rb +27 -0
  41. data/lib/to_source/emitter/execute_string.rb +22 -0
  42. data/lib/to_source/emitter/formal_arguments.rb +212 -0
  43. data/lib/to_source/emitter/if.rb +96 -0
  44. data/lib/to_source/emitter/iter.rb +27 -0
  45. data/lib/to_source/emitter/keyword_value.rb +67 -0
  46. data/lib/to_source/emitter/literal/dynamic.rb +178 -0
  47. data/lib/to_source/emitter/literal.rb +232 -0
  48. data/lib/to_source/emitter/loop.rb +40 -0
  49. data/lib/to_source/emitter/match3.rb +25 -0
  50. data/lib/to_source/emitter/module.rb +28 -0
  51. data/lib/to_source/emitter/multiple_assignment.rb +49 -0
  52. data/lib/to_source/emitter/nth_ref.rb +22 -0
  53. data/lib/to_source/emitter/op_assign1.rb +27 -0
  54. data/lib/to_source/emitter/op_assign2.rb +27 -0
  55. data/lib/to_source/emitter/pattern_arguments.rb +24 -0
  56. data/lib/to_source/emitter/rescue.rb +28 -0
  57. data/lib/to_source/emitter/rescue_condition.rb +93 -0
  58. data/lib/to_source/emitter/scope.rb +24 -0
  59. data/lib/to_source/emitter/scope_name.rb +23 -0
  60. data/lib/to_source/emitter/scoped_name.rb +28 -0
  61. data/lib/to_source/emitter/send.rb +133 -0
  62. data/lib/to_source/emitter/send_with_arguments.rb +103 -0
  63. data/lib/to_source/emitter/singleton_class.rb +38 -0
  64. data/lib/to_source/emitter/splat.rb +24 -0
  65. data/lib/to_source/emitter/splat_when.rb +23 -0
  66. data/lib/to_source/emitter/static.rb +52 -0
  67. data/lib/to_source/emitter/super.rb +92 -0
  68. data/lib/to_source/emitter/to_array.rb +22 -0
  69. data/lib/to_source/emitter/to_string.rb +24 -0
  70. data/lib/to_source/emitter/toplevel.rb +24 -0
  71. data/lib/to_source/emitter/unary_operator_method.rb +27 -0
  72. data/lib/to_source/emitter/unless.rb +45 -0
  73. data/lib/to_source/emitter/util.rb +28 -0
  74. data/lib/to_source/emitter/when.rb +63 -0
  75. data/lib/to_source/emitter/yield.rb +28 -0
  76. data/lib/to_source/emitter/z_super.rb +24 -0
  77. data/lib/to_source/emitter.rb +278 -0
  78. data/lib/to_source/state.rb +144 -0
  79. data/lib/to_source.rb +78 -11
  80. data/spec/spec_helper.rb +11 -0
  81. data/spec/unit/to_source/class_methods/run_spec.rb +1254 -0
  82. data/to_source.gemspec +16 -14
  83. metadata +160 -20
  84. data/.rvmrc +0 -1
  85. data/Readme.md +0 -38
  86. data/lib/to_source/core_ext/node.rb +0 -22
  87. data/lib/to_source/version.rb +0 -3
  88. data/lib/to_source/visitor.rb +0 -377
  89. data/test/to_source/visitor_test.rb +0 -202
@@ -0,0 +1,27 @@
1
+ module ToSource
2
+ class Emitter
3
+ # Emitter for unary operator method
4
+ class UnaryOperatorMethod < Send
5
+
6
+ UNARY_MAPPING = {
7
+ :-@ => :-,
8
+ :+@ => :+,
9
+ }.freeze
10
+
11
+ private
12
+
13
+ # Perform dispatch
14
+ #
15
+ # @return [undefined]
16
+ #
17
+ # @api private
18
+ #
19
+ def dispatch
20
+ name = node.name
21
+ emit(UNARY_MAPPING.fetch(name, name))
22
+ visit(receiver)
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ module ToSource
2
+ class Emitter
3
+ # Emitter for unless
4
+ class Unless < self
5
+
6
+ private
7
+
8
+ # Perform dispatch
9
+ #
10
+ # @return [undefined]
11
+ #
12
+ # @api private
13
+ #
14
+ def dispatch
15
+ emit('unless ')
16
+ visit(condition)
17
+ indented do
18
+ visit(else_body)
19
+ end
20
+ emit_end
21
+ end
22
+
23
+ # Emit condition
24
+ #
25
+ # @return [undefined]
26
+ #
27
+ # @api private
28
+ #
29
+ def condition
30
+ node.condition
31
+ end
32
+
33
+ # Emit else
34
+ #
35
+ # @return [undefined]
36
+ #
37
+ # @api private
38
+ #
39
+ def else_body
40
+ node.else
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ module ToSource
2
+ class Emitter
3
+ # base class for utility emitters
4
+ class Util < self
5
+ # Emitter for delimited bodies
6
+ class DelimitedBody < self
7
+
8
+ private
9
+
10
+ # Perform dispatch
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def dispatch
17
+ body = node
18
+ max = body.length - 1
19
+ body.each_with_index do |member, index|
20
+ visit(member)
21
+ emit(', ') if index < max
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,63 @@
1
+ module ToSource
2
+ class Emitter
3
+ # Emitter for when nodes
4
+ class When < self
5
+
6
+ handle(Rubinius::AST::When)
7
+
8
+ private
9
+
10
+ # Perform dispatch
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def dispatch
17
+ emit('when ')
18
+ emit_single
19
+ emit_conditions
20
+ emit_splat
21
+ indented do
22
+ visit(node.body)
23
+ end
24
+ end
25
+
26
+ # Emit single
27
+ #
28
+ # @return [undefined]
29
+ #
30
+ # @api private
31
+ #
32
+ def emit_single
33
+ single = node.single
34
+ visit(single) if single
35
+ end
36
+
37
+ # Emit splat
38
+ #
39
+ # @return [undefined]
40
+ #
41
+ # @api private
42
+ #
43
+ def emit_splat
44
+ splat = node.splat
45
+ return unless splat
46
+ visit(splat)
47
+ end
48
+
49
+ # Emit conditions
50
+ #
51
+ # @return [undefined]
52
+ #
53
+ # @api private
54
+ #
55
+ def emit_conditions
56
+ conditions = node.conditions
57
+ return unless conditions
58
+ run(Util::DelimitedBody, conditions.body)
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,28 @@
1
+ module ToSource
2
+ class Emitter
3
+ # Emitter for yield nodes
4
+ class Yield < self
5
+
6
+ handle(Rubinius::AST::Yield)
7
+
8
+ private
9
+
10
+ # Perform dispatch
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def dispatch
17
+ emit('yield')
18
+ arguments = node.arguments
19
+ unless arguments.array.empty?
20
+ emit('(')
21
+ visit(arguments)
22
+ emit(')')
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ module ToSource
2
+ class Emitter
3
+ # Emitter for zsuper nodes
4
+ class ZSuper < self
5
+
6
+ handle(Rubinius::AST::ZSuper)
7
+
8
+ private
9
+
10
+ # Perform dispatch
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def dispatch
17
+ emit('super')
18
+ block = node.block
19
+ visit(block) if block
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,278 @@
1
+ module ToSource
2
+ # Abstract base class for emitter
3
+ class Emitter
4
+ include Adamantium::Flat, Equalizer.new(:node)
5
+
6
+ # The emitter registry
7
+ REGISTRY = {}
8
+
9
+ # Build emitter for node
10
+ #
11
+ # @param [Rubinius::AST::Node] node
12
+ # @param [Array] buffer
13
+ #
14
+ # @return [Emitter]
15
+ #
16
+ # @api private
17
+ #
18
+ def self.build(node, buffer = [])
19
+ REGISTRY.fetch(node.class).new(node, buffer)
20
+ end
21
+
22
+ # Run emitter for node
23
+ #
24
+ # @param [Rubinius::AST::Node] node
25
+ #
26
+ # @return [String]
27
+ #
28
+ # @api private
29
+ #
30
+ def self.run(node)
31
+ build(node).source
32
+ end
33
+
34
+ # Declare predicates
35
+ #
36
+ # @return [undefined]
37
+ #
38
+ # @api private
39
+ #
40
+ def self.predicate(*names)
41
+ names.each do |name|
42
+ define_predicate(name)
43
+ end
44
+ end
45
+
46
+ private_class_method :predicate
47
+
48
+ # Declare node delegators
49
+ #
50
+ # @return [undefined]
51
+ #
52
+ # @api private
53
+ #
54
+ def self.delegate(*names)
55
+ names.each do |name|
56
+ define_delegator(name)
57
+ end
58
+ end
59
+
60
+ private_class_method :delegate
61
+
62
+ # Register emitter for node class
63
+ #
64
+ # @param [Class:Rubinius::AST::Node] node_class
65
+ #
66
+ # @return [undefined]
67
+ #
68
+ # @api private
69
+ #
70
+ def self.handle(node_class)
71
+ REGISTRY[node_class]=self
72
+ end
73
+
74
+ private_class_method :handle
75
+
76
+ # Define node delegator
77
+ #
78
+ # @param [Symbol] name
79
+ #
80
+ # @return [undefined]
81
+ #
82
+ # @api private
83
+ #
84
+ def self.define_delegator(name)
85
+ define_method(name) do
86
+ node.public_send(name)
87
+ end
88
+ private(name)
89
+ end
90
+
91
+ private_class_method :define_delegator
92
+
93
+ # Define predicate
94
+ #
95
+ # @param [Symbol] name
96
+ #
97
+ # @return [undefined]
98
+ #
99
+ # @api private
100
+ #
101
+ def self.define_predicate(name)
102
+ predicate = :"#{name}?"
103
+ define_method(predicate) do
104
+ !!send(name)
105
+ end
106
+ private(predicate)
107
+ end
108
+
109
+ private_class_method :define_delegator
110
+
111
+ # Return buffer
112
+ #
113
+ # @return [Array<Command>]
114
+ #
115
+ # @api private
116
+ #
117
+ attr_reader :buffer
118
+
119
+ # Return node
120
+ #
121
+ # @return [Rubinius::AST::Node]
122
+ #
123
+ # @api private
124
+ #
125
+ attr_reader :node
126
+
127
+ # Initialize object
128
+ #
129
+ # @param [Rubinius::AST::Node] node
130
+ # @param [Array<Command>] buffer
131
+ #
132
+ # @return [undefined]
133
+ #
134
+ # @api private
135
+ #
136
+ def initialize(node, buffer)
137
+ @node, @buffer = node, buffer
138
+ dispatch
139
+ end
140
+
141
+ # Return source
142
+ #
143
+ # @return [String]
144
+ #
145
+ # @api private
146
+ #
147
+ def source
148
+ buffer.each_with_object(State.new) do |command, state|
149
+ state.execute(command)
150
+ end.source
151
+ end
152
+
153
+ private
154
+
155
+ # Push command
156
+ #
157
+ # @param [Command] command
158
+ #
159
+ # @return [undefined]
160
+ #
161
+ # @api private
162
+ #
163
+ def push(command)
164
+ buffer.push(command)
165
+ end
166
+
167
+ # Emit new line
168
+ #
169
+ # @return [undefined]
170
+ #
171
+ # @api private
172
+ #
173
+ def new_line
174
+ emit("\n")
175
+ end
176
+
177
+ # Emit single whitespace
178
+ #
179
+ # @return [undefined]
180
+ #
181
+ # @api private
182
+ #
183
+ def space
184
+ emit(' ')
185
+ end
186
+
187
+ # Emit end keyword
188
+ #
189
+ # @return [undefined]
190
+ #
191
+ # @api private
192
+ #
193
+ def emit_end
194
+ emit(:end)
195
+ end
196
+
197
+ # Push indent command
198
+ #
199
+ # @return [undefined]
200
+ #
201
+ # @api private
202
+ #
203
+ def indent
204
+ push(Command::Shift::INDENT)
205
+ end
206
+
207
+ # Push unindent command
208
+ #
209
+ # @return [undefined]
210
+ #
211
+ # @api private
212
+ #
213
+ def unindent
214
+ push(Command::Shift::UNINDENT)
215
+ end
216
+
217
+ # Push token with content
218
+ #
219
+ # @param [String] content
220
+ #
221
+ # @return [undefined]
222
+ #
223
+ # @api private
224
+ #
225
+ def emit(content)
226
+ push(Command::Token.new(content))
227
+ end
228
+
229
+ # Run block indented
230
+ #
231
+ # @return [undefined]
232
+ #
233
+ # @api private
234
+ #
235
+ def indented
236
+ indent
237
+ yield
238
+ unindent
239
+ end
240
+
241
+ # Run block in parantheses
242
+ #
243
+ # @return [undefined]
244
+ #
245
+ # @api private
246
+ #
247
+ def parantheses
248
+ emit('(')
249
+ yield
250
+ emit(')')
251
+ end
252
+
253
+ # Visit descendant node
254
+ #
255
+ # @param [Rubinius::AST::Node] node
256
+ #
257
+ # @return [undefined]
258
+ #
259
+ # @api private
260
+ #
261
+ def visit(node)
262
+ self.class.build(node, buffer)
263
+ end
264
+
265
+ # Run emitter on buffer
266
+ #
267
+ # @param [Class:Emitter] emitter
268
+ # @param [Rubinius::AST::Node] node
269
+ #
270
+ # @return [undefined]
271
+ #
272
+ # @api private
273
+ #
274
+ def run(emitter, node = self.node)
275
+ emitter.new(node, buffer)
276
+ end
277
+ end
278
+ end
@@ -0,0 +1,144 @@
1
+ module ToSource
2
+ # Emitter state
3
+ class State
4
+
5
+ # Return last command
6
+ #
7
+ # @return [Command]
8
+ #
9
+ # @api private
10
+ #
11
+ attr_reader :last
12
+
13
+ # Return current indentation level
14
+ #
15
+ # @return [Fixnum]
16
+ #
17
+ # @api private
18
+ #
19
+ attr_reader :identation
20
+
21
+ # Return buffer
22
+ #
23
+ # @return [Array]
24
+ #
25
+ # @api private
26
+ #
27
+ attr_reader :buffer
28
+
29
+ # Initialize object
30
+ #
31
+ # @return [undefined]
32
+ #
33
+ # @api private
34
+ #
35
+ def initialize
36
+ @last = Command::NULL
37
+ @indentation = 0
38
+ @buffer = []
39
+ end
40
+
41
+ # Execute command
42
+ #
43
+ # @param [Command] command
44
+ #
45
+ # @return [self]
46
+ #
47
+ # @api private
48
+ #
49
+ def execute(command)
50
+ command.run(self)
51
+ @last = command
52
+ self
53
+ end
54
+
55
+ # Write string to buffer
56
+ #
57
+ # @param [String] string
58
+ #
59
+ # @return [self]
60
+ #
61
+ # @api private
62
+ #
63
+ def write(string)
64
+ @buffer << string
65
+ self
66
+ end
67
+
68
+ # Return source
69
+ #
70
+ # @return [String]
71
+ #
72
+ # @api private
73
+ #
74
+ def source
75
+ buffer.join('')
76
+ end
77
+
78
+ # Push command
79
+ #
80
+ # @param [Command] command
81
+ #
82
+ # @return [self]
83
+ #
84
+ # @api private
85
+ #
86
+ def push(command)
87
+ indent
88
+ write(command.content)
89
+ self
90
+ end
91
+
92
+ # Indent line if needed
93
+ #
94
+ # @return [self]
95
+ #
96
+ # @api private
97
+ #
98
+ def indent
99
+ return unless blank?
100
+ write(' ' * @indentation)
101
+ self
102
+ end
103
+
104
+ # Test for blank line
105
+ #
106
+ # @return [true]
107
+ # if line is blank
108
+ #
109
+ # @return [false]
110
+ # otherwise
111
+ #
112
+ # @api private
113
+ #
114
+ def blank?
115
+ buffer.last == "\n"
116
+ end
117
+
118
+ # Write newline
119
+ #
120
+ # @return [self]
121
+ #
122
+ # @api private
123
+ #
124
+ def new_line
125
+ write("\n")
126
+ self
127
+ end
128
+
129
+ # Perform shift by width
130
+ #
131
+ # @param [Fixnum] width
132
+ #
133
+ # @return [self]
134
+ #
135
+ # @api private
136
+ #
137
+ def shift(width)
138
+ @indentation += width
139
+ @indentation = 0 if @indentation < 0
140
+ new_line
141
+ end
142
+
143
+ end
144
+ end