unparser 0.4.9 → 0.5.0

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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/bin/unparser +1 -1
  3. data/lib/unparser.rb +98 -61
  4. data/lib/unparser/ast.rb +0 -1
  5. data/lib/unparser/ast/local_variable_scope.rb +6 -76
  6. data/lib/unparser/buffer.rb +19 -16
  7. data/lib/unparser/cli.rb +26 -39
  8. data/lib/unparser/color.rb +0 -3
  9. data/lib/unparser/comments.rb +0 -26
  10. data/lib/unparser/constants.rb +4 -53
  11. data/lib/unparser/diff.rb +0 -17
  12. data/lib/unparser/dsl.rb +0 -32
  13. data/lib/unparser/emitter.rb +23 -425
  14. data/lib/unparser/emitter/alias.rb +2 -8
  15. data/lib/unparser/emitter/args.rb +45 -0
  16. data/lib/unparser/emitter/argument.rb +8 -166
  17. data/lib/unparser/emitter/array.rb +27 -0
  18. data/lib/unparser/emitter/array_pattern.rb +29 -0
  19. data/lib/unparser/emitter/assignment.rb +36 -127
  20. data/lib/unparser/emitter/begin.rb +9 -84
  21. data/lib/unparser/emitter/binary.rb +7 -20
  22. data/lib/unparser/emitter/block.rb +57 -41
  23. data/lib/unparser/emitter/case.rb +6 -48
  24. data/lib/unparser/emitter/case_guard.rb +27 -0
  25. data/lib/unparser/emitter/case_match.rb +40 -0
  26. data/lib/unparser/emitter/cbase.rb +1 -3
  27. data/lib/unparser/emitter/class.rb +6 -26
  28. data/lib/unparser/emitter/const_pattern.rb +24 -0
  29. data/lib/unparser/emitter/def.rb +7 -51
  30. data/lib/unparser/emitter/defined.rb +2 -12
  31. data/lib/unparser/emitter/dstr.rb +22 -0
  32. data/lib/unparser/emitter/dsym.rb +41 -0
  33. data/lib/unparser/emitter/flipflop.rb +11 -10
  34. data/lib/unparser/emitter/float.rb +29 -0
  35. data/lib/unparser/emitter/flow_modifier.rb +8 -55
  36. data/lib/unparser/emitter/for.rb +5 -19
  37. data/lib/unparser/emitter/hash.rb +74 -0
  38. data/lib/unparser/emitter/hash_pattern.rb +67 -0
  39. data/lib/unparser/emitter/hookexe.rb +5 -11
  40. data/lib/unparser/emitter/if.rb +9 -73
  41. data/lib/unparser/emitter/in_match.rb +21 -0
  42. data/lib/unparser/emitter/in_pattern.rb +34 -0
  43. data/lib/unparser/emitter/index.rb +21 -88
  44. data/lib/unparser/emitter/kwbegin.rb +31 -0
  45. data/lib/unparser/emitter/lambda.rb +0 -8
  46. data/lib/unparser/emitter/masgn.rb +20 -0
  47. data/lib/unparser/emitter/match.rb +3 -17
  48. data/lib/unparser/emitter/match_alt.rb +23 -0
  49. data/lib/unparser/emitter/match_as.rb +21 -0
  50. data/lib/unparser/emitter/match_rest.rb +26 -0
  51. data/lib/unparser/emitter/match_var.rb +19 -0
  52. data/lib/unparser/emitter/mlhs.rb +40 -0
  53. data/lib/unparser/emitter/module.rb +3 -9
  54. data/lib/unparser/emitter/op_assign.rb +12 -27
  55. data/lib/unparser/emitter/pin.rb +19 -0
  56. data/lib/unparser/emitter/primitive.rb +93 -0
  57. data/lib/unparser/emitter/range.rb +35 -0
  58. data/lib/unparser/emitter/regexp.rb +35 -0
  59. data/lib/unparser/emitter/repetition.rb +17 -57
  60. data/lib/unparser/emitter/rescue.rb +1 -97
  61. data/lib/unparser/emitter/root.rb +17 -1
  62. data/lib/unparser/emitter/send.rb +10 -219
  63. data/lib/unparser/emitter/simple.rb +33 -0
  64. data/lib/unparser/emitter/splat.rb +2 -18
  65. data/lib/unparser/emitter/super.rb +1 -29
  66. data/lib/unparser/emitter/undef.rb +1 -9
  67. data/lib/unparser/emitter/variable.rb +1 -31
  68. data/lib/unparser/emitter/xstr.rb +72 -0
  69. data/lib/unparser/emitter/yield.rb +1 -9
  70. data/lib/unparser/generation.rb +250 -0
  71. data/lib/unparser/node_details.rb +21 -0
  72. data/lib/unparser/node_details/send.rb +62 -0
  73. data/lib/unparser/node_helpers.rb +45 -6
  74. data/lib/unparser/validation.rb +37 -35
  75. data/lib/unparser/writer.rb +15 -0
  76. data/lib/unparser/writer/binary.rb +99 -0
  77. data/lib/unparser/writer/dynamic_string.rb +229 -0
  78. data/lib/unparser/writer/resbody.rb +40 -0
  79. data/lib/unparser/writer/rescue.rb +39 -0
  80. data/lib/unparser/writer/send.rb +124 -0
  81. data/lib/unparser/{emitter → writer}/send/attribute_assignment.rb +11 -26
  82. data/lib/unparser/writer/send/binary.rb +27 -0
  83. data/lib/unparser/writer/send/conditional.rb +25 -0
  84. data/lib/unparser/writer/send/regular.rb +33 -0
  85. data/lib/unparser/{emitter → writer}/send/unary.rb +10 -17
  86. metadata +63 -31
  87. data/lib/unparser/emitter/empty.rb +0 -23
  88. data/lib/unparser/emitter/ensure.rb +0 -37
  89. data/lib/unparser/emitter/literal.rb +0 -10
  90. data/lib/unparser/emitter/literal/array.rb +0 -29
  91. data/lib/unparser/emitter/literal/dynamic.rb +0 -53
  92. data/lib/unparser/emitter/literal/dynamic_body.rb +0 -132
  93. data/lib/unparser/emitter/literal/execute_string.rb +0 -38
  94. data/lib/unparser/emitter/literal/hash.rb +0 -156
  95. data/lib/unparser/emitter/literal/primitive.rb +0 -145
  96. data/lib/unparser/emitter/literal/range.rb +0 -36
  97. data/lib/unparser/emitter/literal/regexp.rb +0 -114
  98. data/lib/unparser/emitter/literal/singleton.rb +0 -26
  99. data/lib/unparser/emitter/meta.rb +0 -16
  100. data/lib/unparser/emitter/redo.rb +0 -25
  101. data/lib/unparser/emitter/resbody.rb +0 -76
  102. data/lib/unparser/emitter/retry.rb +0 -25
  103. data/lib/unparser/emitter/send/binary.rb +0 -57
  104. data/lib/unparser/emitter/send/conditional.rb +0 -40
  105. data/lib/unparser/emitter/send/regular.rb +0 -40
  106. data/lib/unparser/preprocessor.rb +0 -159
@@ -11,16 +11,10 @@ module Unparser
11
11
 
12
12
  private
13
13
 
14
- # Perform dispatch
15
- #
16
- # @return [undefined]
17
- #
18
- # @api private
19
- #
20
14
  def dispatch
21
- write(K_ALIAS, WS)
15
+ write('alias ')
22
16
  visit(target)
23
- write(WS)
17
+ ws
24
18
  visit(source)
25
19
  end
26
20
 
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Arguments emitter
6
+ class Args < self
7
+ def emit_block_arguments
8
+ delimited(normal_arguments)
9
+
10
+ write(',') if normal_arguments.one? && n_arg?(normal_arguments.first)
11
+
12
+ emit_shadowargs
13
+ end
14
+
15
+ def emit_def_arguments
16
+ delimited(normal_arguments)
17
+ end
18
+
19
+ def emit_lambda_arguments
20
+ delimited(normal_arguments)
21
+ emit_shadowargs
22
+ end
23
+
24
+ private
25
+
26
+ def emit_shadowargs
27
+ return if shadowargs.empty?
28
+
29
+ write('; ')
30
+ delimited(shadowargs)
31
+ end
32
+
33
+ def normal_arguments
34
+ children.reject(&method(:n_shadowarg?))
35
+ end
36
+ memoize :normal_arguments
37
+
38
+ def shadowargs
39
+ children.select(&method(:n_shadowarg?))
40
+ end
41
+ memoize :shadowargs
42
+
43
+ end # Arguments
44
+ end # Emitter
45
+ end # Unparser
@@ -2,121 +2,19 @@
2
2
 
3
3
  module Unparser
4
4
  class Emitter
5
-
6
- # Arg expr (pattern args) emitter
7
- class ArgExpr < self
8
-
9
- handle :arg_expr
10
-
11
- children :body
12
-
13
- private
14
-
15
- # Perform dispatch
16
- #
17
- # @return [undefined]
18
- #
19
- # @api private
20
- #
21
- def dispatch
22
- visit_parentheses(body)
23
- end
24
- end # ArgExpr
25
-
26
- # Arguments emitter
27
- class Arguments < self
28
- include Terminated
29
-
30
- handle :args
31
-
32
- SHADOWARGS = ->(node) { node.type.equal?(:shadowarg) }.freeze
33
- ARG = ->(node) { node.type.equal?(:arg) }.freeze
34
-
35
- private
36
-
37
- # Perform dispatch
38
- #
39
- # @return [undefined]
40
- #
41
- # @api private
42
- #
43
- def dispatch
44
- delimited(normal_arguments)
45
-
46
- write(', ') if procarg_disambiguator?
47
-
48
- return if shadowargs.empty?
49
-
50
- write('; ')
51
- delimited(shadowargs)
52
- end
53
-
54
- # Test for procarg_disambiguator
55
- #
56
- # @return [Boolean]
57
- #
58
- # @api private
59
- #
60
- def procarg_disambiguator?
61
- regular_block? && normal_arguments.all?(&ARG) && normal_arguments.one?
62
- end
63
-
64
- # Test for regular block
65
- #
66
- # @return [Boolean]
67
- #
68
- # @api private
69
- #
70
- def regular_block?
71
- parent_type.equal?(:block) && !parent.node.children.first.type.equal?(:lambda)
72
- end
73
-
74
- # Return normal arguments
75
- #
76
- # @return [Enumerable<Parser::AST::Node>]
77
- #
78
- # @api private
79
- #
80
- def normal_arguments
81
- children.reject(&SHADOWARGS)
82
- end
83
- memoize :normal_arguments
84
-
85
- # Return shadow args
86
- #
87
- # @return [Enumerable<Parser::AST::Node>]
88
- #
89
- # @api private
90
- #
91
- def shadowargs
92
- children.select(&SHADOWARGS)
93
- end
94
- memoize :shadowargs
95
-
96
- end # Arguments
97
-
98
5
  # Emitter for block and kwrestarg arguments
99
6
  class Morearg < self
100
- include Terminated
101
-
102
7
  MAP = {
103
- blockarg: T_AMP,
104
- kwrestarg: T_DSPLAT
8
+ blockarg: '&',
9
+ kwrestarg: '**'
105
10
  }.freeze
106
11
 
107
- handle :blockarg
108
- handle :kwrestarg
12
+ handle(*MAP.keys)
109
13
 
110
14
  children :name
111
15
 
112
16
  private
113
17
 
114
- # Perform dispatch
115
- #
116
- # @return [undefined]
117
- #
118
- # @api private
119
- #
120
18
  def dispatch
121
19
  write(MAP.fetch(node_type), name.to_s)
122
20
  end
@@ -125,44 +23,28 @@ module Unparser
125
23
 
126
24
  # Optional argument emitter
127
25
  class Optarg < self
128
- include Terminated
129
-
130
26
  handle :optarg
131
27
 
132
28
  children :name, :value
133
29
 
134
30
  private
135
31
 
136
- # Perform dispatch
137
- #
138
- # @return [undefined]
139
- #
140
- # @api private
141
- #
142
32
  def dispatch
143
- write(name.to_s, WS, T_ASN, WS)
33
+ write(name.to_s, ' = ')
144
34
  visit(value)
145
35
  end
146
36
  end
147
37
 
148
38
  # Optional keyword argument emitter
149
39
  class KeywordOptional < self
150
- include Terminated
151
-
152
40
  handle :kwoptarg
153
41
 
154
42
  children :name, :value
155
43
 
156
44
  private
157
45
 
158
- # Perform dispatch
159
- #
160
- # @return [undefined]
161
- #
162
- # @api private
163
- #
164
46
  def dispatch
165
- write(name.to_s, T_COLON, WS)
47
+ write(name.to_s, ': ')
166
48
  visit(value)
167
49
  end
168
50
 
@@ -170,64 +52,40 @@ module Unparser
170
52
 
171
53
  # Keyword argument emitter
172
54
  class Kwarg < self
173
- include Terminated
174
-
175
55
  handle :kwarg
176
56
 
177
57
  children :name
178
58
 
179
59
  private
180
60
 
181
- # Perform dispatch
182
- #
183
- # @return [undefined]
184
- #
185
- # @api private
186
- #
187
61
  def dispatch
188
- write(name.to_s, T_COLON)
62
+ write(name.to_s, ':')
189
63
  end
190
64
 
191
65
  end # Restarg
192
66
 
193
67
  # Rest argument emitter
194
68
  class Restarg < self
195
- include Terminated
196
-
197
69
  handle :restarg
198
70
 
199
71
  children :name
200
72
 
201
73
  private
202
74
 
203
- # Perform dispatch
204
- #
205
- # @return [undefined]
206
- #
207
- # @api private
208
- #
209
75
  def dispatch
210
- write(T_SPLAT, name.to_s)
76
+ write('*', name.to_s)
211
77
  end
212
78
 
213
79
  end # Restarg
214
80
 
215
81
  # Argument emitter
216
82
  class Argument < self
217
- include Terminated
218
-
219
83
  handle :arg, :shadowarg
220
84
 
221
85
  children :name
222
86
 
223
87
  private
224
88
 
225
- # Perform dispatch
226
- #
227
- # @return [undefined]
228
- #
229
- # @api private
230
- #
231
89
  def dispatch
232
90
  write(name.to_s)
233
91
  end
@@ -236,20 +94,12 @@ module Unparser
236
94
 
237
95
  # Progarg emitter
238
96
  class Procarg < self
239
- include Terminated
240
-
241
97
  handle :procarg0
242
98
 
243
99
  PARENS = %i[restarg mlhs].freeze
244
100
 
245
101
  private
246
102
 
247
- # Perform dispatch
248
- #
249
- # @return [undefined]
250
- #
251
- # @api private
252
- #
253
103
  def dispatch
254
104
  if needs_parens?
255
105
  parentheses do
@@ -269,22 +119,14 @@ module Unparser
269
119
 
270
120
  # Block pass node emitter
271
121
  class BlockPass < self
272
- include Terminated
273
-
274
122
  handle :block_pass
275
123
 
276
124
  children :name
277
125
 
278
126
  private
279
127
 
280
- # Perform dispatch
281
- #
282
- # @return [undefined]
283
- #
284
- # @api private
285
- #
286
128
  def dispatch
287
- write(T_AMP)
129
+ write('&')
288
130
  visit(name)
289
131
  end
290
132
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Array literal emitter
6
+ class Array < self
7
+ handle :array
8
+
9
+ def emit_heredoc_reminders
10
+ emitters.each(&:emit_heredoc_reminders)
11
+ end
12
+
13
+ private
14
+
15
+ def dispatch
16
+ parentheses('[', ']') do
17
+ delimited(emitters, &:write_to_buffer)
18
+ end
19
+ end
20
+
21
+ def emitters
22
+ children.map(&method(:emitter))
23
+ end
24
+ memoize :emitters
25
+ end # Array
26
+ end # Emitter
27
+ end # Unparser
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Emitter for array patterns
6
+ class ArrayPattern < self
7
+
8
+ handle :array_pattern
9
+ handle :array_pattern_with_tail
10
+
11
+ private
12
+
13
+ def dispatch
14
+ write('[')
15
+ delimited(children, &method(:emit_member))
16
+ write(', ') if node_type.equal?(:array_pattern_with_tail)
17
+ write(']')
18
+ end
19
+
20
+ def emit_member(node)
21
+ if n_match_rest?(node)
22
+ writer_with(MatchRest, node).emit_array_pattern
23
+ else
24
+ visit(node)
25
+ end
26
+ end
27
+ end # Pin
28
+ end # Emitter
29
+ end # Unparser
@@ -5,163 +5,72 @@ module Unparser
5
5
 
6
6
  # Base class for assignment emitters
7
7
  class Assignment < self
8
+ BINARY_OPERATOR = %i[and or].freeze
9
+
10
+ def symbol_name
11
+ true
12
+ end
13
+
14
+ def emit_heredoc_reminders
15
+ return unless right
16
+
17
+ emitter(right).emit_heredoc_reminders
18
+ end
8
19
 
9
20
  private
10
21
 
11
- # Perform dispatch
12
- #
13
- # @return [undefined]
14
- #
15
- # @api private
16
- #
17
22
  def dispatch
18
23
  emit_left
19
24
  emit_right
20
25
  end
21
26
 
22
- # Single assignment emitter
23
- class Single < self
24
-
25
- # Test for terminated emit
26
- #
27
- # @return [Boolean]
28
- #
29
- # @api private
30
- #
31
- def terminated?
32
- right.nil?
33
- end
34
-
35
- private
27
+ def emit_right
28
+ return unless right
36
29
 
37
- # Emit right
38
- #
39
- # @return [undefined]
40
- #
41
- # @api private
42
- #
43
- def emit_right
44
- return unless right
30
+ write(' = ')
45
31
 
46
- write(WS, T_ASN, WS)
32
+ if BINARY_OPERATOR.include?(right.type)
33
+ writer_with(Writer::Binary, right).emit_operator
34
+ else
47
35
  visit(right)
48
36
  end
37
+ end
49
38
 
50
- abstract_method :emit_left
51
-
52
- # Variable assignment emitter
53
- class Variable < self
54
-
55
- handle :lvasgn, :ivasgn, :cvasgn, :gvasgn
56
-
57
- children :name, :right
58
-
59
- private
60
-
61
- # Emit left
62
- #
63
- # @return [undefined]
64
- #
65
- # @api private
66
- #
67
- def emit_left
68
- write(name.to_s)
69
- end
70
-
71
- end # Variable
72
-
73
- # Constant assignment emitter
74
- class Constant < self
75
-
76
- handle :casgn
77
-
78
- children :base, :name, :right
79
-
80
- private
81
-
82
- # Emit left
83
- #
84
- # @return [undefined]
85
- #
86
- # @api private
87
- #
88
- def emit_left
89
- if base
90
- visit(base)
91
- write(T_DCL) if base.type != :cbase
92
- end
93
- write(name.to_s)
94
- end
39
+ abstract_method :emit_left
95
40
 
96
- end # Constant
97
- end # Single
41
+ # Variable assignment emitter
42
+ class Variable < self
98
43
 
99
- # Multiple assignment
100
- class Multiple < self
101
- include Unterminated
44
+ handle :lvasgn, :ivasgn, :cvasgn, :gvasgn
102
45
 
103
- handle :masgn
46
+ children :name, :right
104
47
 
105
48
  private
106
49
 
107
- # Emit left
108
- #
109
- # @return [undefined]
110
- #
111
- # @api private
112
- #
113
50
  def emit_left
114
- visit_plain(first_child)
51
+ write(name.to_s)
115
52
  end
116
53
 
117
- # Emit right
118
- #
119
- # @return [undefined]
120
- #
121
- # @api private
122
- #
123
- def emit_right
124
- write(WS, T_ASN, WS)
125
- visit(children.last)
126
- end
54
+ end # Variable
127
55
 
128
- end # Multiple
56
+ # Constant assignment emitter
57
+ class Constant < self
129
58
 
130
- # Emitter for multiple assignment left hand side
131
- class MLHS < Emitter
132
- include Unterminated
59
+ handle :casgn
133
60
 
134
- handle :mlhs
61
+ children :base, :name, :right
135
62
 
136
63
  private
137
64
 
138
- NO_COMMA = %i[splat restarg].to_set.freeze
139
- PARENT_MLHS = %i[mlhs masgn].freeze
140
-
141
- # Perform dispatch
142
- #
143
- # @return [undefined]
144
- #
145
- # @api private
146
- #
147
- def dispatch
148
- delimited(children)
149
-
150
- write(',') if children.one? && mlhs?
151
- end
152
-
153
- # Test for mlhs context
154
- #
155
- # @return [undefined]
156
- #
157
- # @api private
158
- #
159
- def mlhs?
160
- !NO_COMMA.include?(first_child.type) && PARENT_MLHS.include?(parent_type)
65
+ def emit_left
66
+ if base
67
+ visit(base)
68
+ write('::') unless n_cbase?(base)
69
+ end
70
+ write(name.to_s)
161
71
  end
162
72
 
163
- end # MLHS
164
-
73
+ end # Constant
165
74
  end # Assignment
166
75
  end # Emitter
167
76
  end # Unparser