prism 0.22.0 → 0.24.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -1
  3. data/README.md +2 -1
  4. data/docs/releasing.md +67 -17
  5. data/docs/ruby_parser_translation.md +19 -0
  6. data/docs/serialization.md +2 -0
  7. data/ext/prism/api_node.c +1982 -1538
  8. data/ext/prism/extension.c +12 -7
  9. data/ext/prism/extension.h +2 -2
  10. data/include/prism/diagnostic.h +3 -4
  11. data/include/prism/encoding.h +7 -0
  12. data/include/prism/util/pm_constant_pool.h +1 -1
  13. data/include/prism/util/pm_newline_list.h +4 -3
  14. data/include/prism/util/pm_strpbrk.h +4 -1
  15. data/include/prism/version.h +2 -2
  16. data/lib/prism/desugar_compiler.rb +225 -80
  17. data/lib/prism/dsl.rb +302 -299
  18. data/lib/prism/ffi.rb +103 -77
  19. data/lib/prism/lex_compat.rb +1 -0
  20. data/lib/prism/node.rb +3624 -2114
  21. data/lib/prism/node_ext.rb +25 -2
  22. data/lib/prism/parse_result.rb +56 -19
  23. data/lib/prism/serialize.rb +605 -303
  24. data/lib/prism/translation/parser/compiler.rb +1 -1
  25. data/lib/prism/translation/parser/rubocop.rb +11 -3
  26. data/lib/prism/translation/parser.rb +25 -12
  27. data/lib/prism/translation/parser33.rb +12 -0
  28. data/lib/prism/translation/parser34.rb +12 -0
  29. data/lib/prism/translation/ripper.rb +696 -0
  30. data/lib/prism/translation/ruby_parser.rb +1521 -0
  31. data/lib/prism/translation.rb +3 -3
  32. data/lib/prism.rb +0 -1
  33. data/prism.gemspec +6 -2
  34. data/src/diagnostic.c +10 -11
  35. data/src/encoding.c +16 -17
  36. data/src/options.c +7 -2
  37. data/src/prettyprint.c +3 -3
  38. data/src/prism.c +172 -97
  39. data/src/serialize.c +24 -13
  40. data/src/token_type.c +3 -3
  41. data/src/util/pm_constant_pool.c +1 -1
  42. data/src/util/pm_newline_list.c +6 -3
  43. data/src/util/pm_strpbrk.c +122 -14
  44. metadata +8 -4
  45. data/lib/prism/ripper_compat.rb +0 -285
@@ -542,8 +542,9 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
542
542
  pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
543
543
  pm_parser_register_encoding_changed_callback(&parser, parse_lex_encoding_changed_callback);
544
544
 
545
+ VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input));
545
546
  VALUE offsets = rb_ary_new();
546
- VALUE source_argv[] = { rb_str_new((const char *) pm_string_source(input), pm_string_length(input)), ULONG2NUM(parser.start_line), offsets };
547
+ VALUE source_argv[] = { source_string, LONG2NUM(parser.start_line), offsets };
547
548
  VALUE source = rb_class_new_instance(3, source_argv, rb_cPrismSource);
548
549
 
549
550
  parse_lex_data_t parse_lex_data = {
@@ -561,17 +562,21 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
561
562
  parser.lex_callback = &lex_callback;
562
563
  pm_node_t *node = pm_parse(&parser);
563
564
 
564
- // Here we need to update the source range to have the correct newline
565
- // offsets. We do it here because we've already created the object and given
566
- // it over to all of the tokens.
565
+ // Here we need to update the Source object to have the correct
566
+ // encoding for the source string and the correct newline offsets.
567
+ // We do it here because we've already created the Source object and given
568
+ // it over to all of the tokens, and both of these are only set after pm_parse().
569
+ rb_encoding *encoding = rb_enc_find(parser.encoding->name);
570
+ rb_enc_associate(source_string, encoding);
571
+
567
572
  for (size_t index = 0; index < parser.newline_list.size; index++) {
568
- rb_ary_push(offsets, INT2FIX(parser.newline_list.offsets[index]));
573
+ rb_ary_push(offsets, ULONG2NUM(parser.newline_list.offsets[index]));
569
574
  }
570
575
 
571
576
  VALUE value;
572
577
  if (return_nodes) {
573
578
  value = rb_ary_new_capa(2);
574
- rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding));
579
+ rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source));
575
580
  rb_ary_push(value, parse_lex_data.tokens);
576
581
  } else {
577
582
  value = parse_lex_data.tokens;
@@ -650,7 +655,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
650
655
 
651
656
  VALUE source = pm_source_new(&parser, encoding);
652
657
  VALUE result_argv[] = {
653
- pm_ast_new(&parser, node, encoding),
658
+ pm_ast_new(&parser, node, encoding, source),
654
659
  parser_comments(&parser, source),
655
660
  parser_magic_comments(&parser, source),
656
661
  parser_data_loc(&parser, source),
@@ -1,7 +1,7 @@
1
1
  #ifndef PRISM_EXT_NODE_H
2
2
  #define PRISM_EXT_NODE_H
3
3
 
4
- #define EXPECTED_PRISM_VERSION "0.22.0"
4
+ #define EXPECTED_PRISM_VERSION "0.24.0"
5
5
 
6
6
  #include <ruby.h>
7
7
  #include <ruby/encoding.h>
@@ -9,7 +9,7 @@
9
9
 
10
10
  VALUE pm_source_new(pm_parser_t *parser, rb_encoding *encoding);
11
11
  VALUE pm_token_new(pm_parser_t *parser, pm_token_t *token, rb_encoding *encoding, VALUE source);
12
- VALUE pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding);
12
+ VALUE pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding, VALUE source);
13
13
 
14
14
  void Init_prism_api_node(void);
15
15
  void Init_prism_pack(void);
@@ -219,6 +219,7 @@ typedef enum {
219
219
  PM_ERR_MODULE_NAME,
220
220
  PM_ERR_MODULE_TERM,
221
221
  PM_ERR_MULTI_ASSIGN_MULTI_SPLATS,
222
+ PM_ERR_MULTI_ASSIGN_UNEXPECTED_REST,
222
223
  PM_ERR_NOT_EXPRESSION,
223
224
  PM_ERR_NO_LOCAL_VARIABLE,
224
225
  PM_ERR_NUMBER_LITERAL_UNDERSCORE,
@@ -272,6 +273,7 @@ typedef enum {
272
273
  PM_ERR_STATEMENT_UNDEF,
273
274
  PM_ERR_STRING_CONCATENATION,
274
275
  PM_ERR_STRING_INTERPOLATED_TERM,
276
+ PM_ERR_STRING_LITERAL_EOF,
275
277
  PM_ERR_STRING_LITERAL_TERM,
276
278
  PM_ERR_SYMBOL_INVALID,
277
279
  PM_ERR_SYMBOL_TERM_DYNAMIC,
@@ -279,10 +281,7 @@ typedef enum {
279
281
  PM_ERR_TERNARY_COLON,
280
282
  PM_ERR_TERNARY_EXPRESSION_FALSE,
281
283
  PM_ERR_TERNARY_EXPRESSION_TRUE,
282
- PM_ERR_UNARY_RECEIVER_BANG,
283
- PM_ERR_UNARY_RECEIVER_MINUS,
284
- PM_ERR_UNARY_RECEIVER_PLUS,
285
- PM_ERR_UNARY_RECEIVER_TILDE,
284
+ PM_ERR_UNARY_RECEIVER,
286
285
  PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT,
287
286
  PM_ERR_UNEXPECTED_TOKEN_IGNORE,
288
287
  PM_ERR_UNDEF_ARGUMENT,
@@ -245,6 +245,13 @@ extern const pm_encoding_t pm_encodings[PM_ENCODING_MAXIMUM];
245
245
  */
246
246
  #define PM_ENCODING_US_ASCII_ENTRY (&pm_encodings[PM_ENCODING_US_ASCII])
247
247
 
248
+ /**
249
+ * This is the ASCII-8BIT encoding. We need a reference to it so that pm_strpbrk
250
+ * can compare against it because invalid multibyte characters are not a thing
251
+ * in this encoding.
252
+ */
253
+ #define PM_ENCODING_ASCII_8BIT_ENTRY (&pm_encodings[PM_ENCODING_ASCII_8BIT])
254
+
248
255
  /**
249
256
  * Parse the given name of an encoding and return a pointer to the corresponding
250
257
  * encoding struct if one can be found, otherwise return NULL.
@@ -163,7 +163,7 @@ pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool,
163
163
  * @param length The length of the constant.
164
164
  * @return The id of the constant.
165
165
  */
166
- pm_constant_id_t pm_constant_pool_find(pm_constant_pool_t *pool, const uint8_t *start, size_t length);
166
+ pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length);
167
167
 
168
168
  /**
169
169
  * Insert a constant into a constant pool that is a slice of a source string.
@@ -44,10 +44,10 @@ typedef struct {
44
44
  */
45
45
  typedef struct {
46
46
  /** The line number. */
47
- size_t line;
47
+ int32_t line;
48
48
 
49
49
  /** The column number. */
50
- size_t column;
50
+ uint32_t column;
51
51
  } pm_line_column_t;
52
52
 
53
53
  /**
@@ -79,9 +79,10 @@ bool pm_newline_list_append(pm_newline_list_t *list, const uint8_t *cursor);
79
79
  *
80
80
  * @param list The list to search.
81
81
  * @param cursor A pointer to the offset to search for.
82
+ * @param start_line The line to start counting from.
82
83
  * @return The line and column of the given offset.
83
84
  */
84
- pm_line_column_t pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor);
85
+ pm_line_column_t pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor, int32_t start_line);
85
86
 
86
87
  /**
87
88
  * Free the internal memory allocated for the newline list.
@@ -7,6 +7,7 @@
7
7
  #define PRISM_STRPBRK_H
8
8
 
9
9
  #include "prism/defines.h"
10
+ #include "prism/diagnostic.h"
10
11
  #include "prism/parser.h"
11
12
 
12
13
  #include <stddef.h>
@@ -35,9 +36,11 @@
35
36
  * @param source The source to search.
36
37
  * @param charset The charset to search for.
37
38
  * @param length The maximum number of bytes to search.
39
+ * @param validate Whether to validate that the source string is valid in the
40
+ * current encoding of the parser.
38
41
  * @return A pointer to the first character in the source string that is in the
39
42
  * charset, or NULL if no such character exists.
40
43
  */
41
- const uint8_t * pm_strpbrk(const pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, ptrdiff_t length);
44
+ const uint8_t * pm_strpbrk(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, ptrdiff_t length, bool validate);
42
45
 
43
46
  #endif
@@ -14,7 +14,7 @@
14
14
  /**
15
15
  * The minor version of the Prism library as an int.
16
16
  */
17
- #define PRISM_VERSION_MINOR 22
17
+ #define PRISM_VERSION_MINOR 24
18
18
 
19
19
  /**
20
20
  * The patch version of the Prism library as an int.
@@ -24,6 +24,6 @@
24
24
  /**
25
25
  * The version of the Prism library as a constant string.
26
26
  */
27
- #define PRISM_VERSION "0.22.0"
27
+ #define PRISM_VERSION "0.24.0"
28
28
 
29
29
  #endif
@@ -1,6 +1,216 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Prism
4
+ class DesugarAndWriteNode # :nodoc:
5
+ attr_reader :node, :source, :read_class, :write_class, :arguments
6
+
7
+ def initialize(node, source, read_class, write_class, *arguments)
8
+ @node = node
9
+ @source = source
10
+ @read_class = read_class
11
+ @write_class = write_class
12
+ @arguments = arguments
13
+ end
14
+
15
+ # Desugar `x &&= y` to `x && x = y`
16
+ def compile
17
+ AndNode.new(
18
+ source,
19
+ read_class.new(source, *arguments, node.name_loc),
20
+ write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location),
21
+ node.operator_loc,
22
+ node.location
23
+ )
24
+ end
25
+ end
26
+
27
+ class DesugarOrWriteDefinedNode # :nodoc:
28
+ attr_reader :node, :source, :read_class, :write_class, :arguments
29
+
30
+ def initialize(node, source, read_class, write_class, *arguments)
31
+ @node = node
32
+ @source = source
33
+ @read_class = read_class
34
+ @write_class = write_class
35
+ @arguments = arguments
36
+ end
37
+
38
+ # Desugar `x ||= y` to `defined?(x) ? x : x = y`
39
+ def compile
40
+ IfNode.new(
41
+ source,
42
+ node.operator_loc,
43
+ DefinedNode.new(source, nil, read_class.new(source, *arguments, node.name_loc), nil, node.operator_loc, node.name_loc),
44
+ node.operator_loc,
45
+ StatementsNode.new(source, [read_class.new(source, *arguments, node.name_loc)], node.location),
46
+ ElseNode.new(
47
+ source,
48
+ node.operator_loc,
49
+ StatementsNode.new(
50
+ source,
51
+ [write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location)],
52
+ node.location
53
+ ),
54
+ node.operator_loc,
55
+ node.location
56
+ ),
57
+ node.operator_loc,
58
+ node.location
59
+ )
60
+ end
61
+ end
62
+
63
+ class DesugarOperatorWriteNode # :nodoc:
64
+ attr_reader :node, :source, :read_class, :write_class, :arguments
65
+
66
+ def initialize(node, source, read_class, write_class, *arguments)
67
+ @node = node
68
+ @source = source
69
+ @read_class = read_class
70
+ @write_class = write_class
71
+ @arguments = arguments
72
+ end
73
+
74
+ # Desugar `x += y` to `x = x + y`
75
+ def compile
76
+ write_class.new(
77
+ source,
78
+ *arguments,
79
+ node.name_loc,
80
+ CallNode.new(
81
+ source,
82
+ 0,
83
+ read_class.new(source, *arguments, node.name_loc),
84
+ nil,
85
+ node.operator_loc.slice.chomp("="),
86
+ node.operator_loc.copy(length: node.operator_loc.length - 1),
87
+ nil,
88
+ ArgumentsNode.new(source, 0, [node.value], node.value.location),
89
+ nil,
90
+ nil,
91
+ node.location
92
+ ),
93
+ node.operator_loc.copy(start_offset: node.operator_loc.end_offset - 1, length: 1),
94
+ node.location
95
+ )
96
+ end
97
+ end
98
+
99
+ class DesugarOrWriteNode # :nodoc:
100
+ attr_reader :node, :source, :read_class, :write_class, :arguments
101
+
102
+ def initialize(node, source, read_class, write_class, *arguments)
103
+ @node = node
104
+ @source = source
105
+ @read_class = read_class
106
+ @write_class = write_class
107
+ @arguments = arguments
108
+ end
109
+
110
+ # Desugar `x ||= y` to `x || x = y`
111
+ def compile
112
+ OrNode.new(
113
+ source,
114
+ read_class.new(source, *arguments, node.name_loc),
115
+ write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location),
116
+ node.operator_loc,
117
+ node.location
118
+ )
119
+ end
120
+ end
121
+
122
+ private_constant :DesugarAndWriteNode, :DesugarOrWriteNode, :DesugarOrWriteDefinedNode, :DesugarOperatorWriteNode
123
+
124
+ class ClassVariableAndWriteNode
125
+ def desugar # :nodoc:
126
+ DesugarAndWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
127
+ end
128
+ end
129
+
130
+ class ClassVariableOrWriteNode
131
+ def desugar # :nodoc:
132
+ DesugarOrWriteDefinedNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
133
+ end
134
+ end
135
+
136
+ class ClassVariableOperatorWriteNode
137
+ def desugar # :nodoc:
138
+ DesugarOperatorWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
139
+ end
140
+ end
141
+
142
+ class ConstantAndWriteNode
143
+ def desugar # :nodoc:
144
+ DesugarAndWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
145
+ end
146
+ end
147
+
148
+ class ConstantOrWriteNode
149
+ def desugar # :nodoc:
150
+ DesugarOrWriteDefinedNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
151
+ end
152
+ end
153
+
154
+ class ConstantOperatorWriteNode
155
+ def desugar # :nodoc:
156
+ DesugarOperatorWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
157
+ end
158
+ end
159
+
160
+ class GlobalVariableAndWriteNode
161
+ def desugar # :nodoc:
162
+ DesugarAndWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
163
+ end
164
+ end
165
+
166
+ class GlobalVariableOrWriteNode
167
+ def desugar # :nodoc:
168
+ DesugarOrWriteDefinedNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
169
+ end
170
+ end
171
+
172
+ class GlobalVariableOperatorWriteNode
173
+ def desugar # :nodoc:
174
+ DesugarOperatorWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
175
+ end
176
+ end
177
+
178
+ class InstanceVariableAndWriteNode
179
+ def desugar # :nodoc:
180
+ DesugarAndWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
181
+ end
182
+ end
183
+
184
+ class InstanceVariableOrWriteNode
185
+ def desugar # :nodoc:
186
+ DesugarOrWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
187
+ end
188
+ end
189
+
190
+ class InstanceVariableOperatorWriteNode
191
+ def desugar # :nodoc:
192
+ DesugarOperatorWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
193
+ end
194
+ end
195
+
196
+ class LocalVariableAndWriteNode
197
+ def desugar # :nodoc:
198
+ DesugarAndWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
199
+ end
200
+ end
201
+
202
+ class LocalVariableOrWriteNode
203
+ def desugar # :nodoc:
204
+ DesugarOrWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
205
+ end
206
+ end
207
+
208
+ class LocalVariableOperatorWriteNode
209
+ def desugar # :nodoc:
210
+ DesugarOperatorWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
211
+ end
212
+ end
213
+
4
214
  # DesugarCompiler is a compiler that desugars Ruby code into a more primitive
5
215
  # form. This is useful for consumers that want to deal with fewer node types.
6
216
  class DesugarCompiler < MutationCompiler
@@ -10,7 +220,7 @@ module Prism
10
220
  #
11
221
  # @@foo && @@foo = bar
12
222
  def visit_class_variable_and_write_node(node)
13
- desugar_and_write_node(node, ClassVariableReadNode, ClassVariableWriteNode, node.name)
223
+ node.desugar
14
224
  end
15
225
 
16
226
  # @@foo ||= bar
@@ -19,7 +229,7 @@ module Prism
19
229
  #
20
230
  # defined?(@@foo) ? @@foo : @@foo = bar
21
231
  def visit_class_variable_or_write_node(node)
22
- desugar_or_write_defined_node(node, ClassVariableReadNode, ClassVariableWriteNode, node.name)
232
+ node.desugar
23
233
  end
24
234
 
25
235
  # @@foo += bar
@@ -28,7 +238,7 @@ module Prism
28
238
  #
29
239
  # @@foo = @@foo + bar
30
240
  def visit_class_variable_operator_write_node(node)
31
- desugar_operator_write_node(node, ClassVariableReadNode, ClassVariableWriteNode, node.name)
241
+ node.desugar
32
242
  end
33
243
 
34
244
  # Foo &&= bar
@@ -37,7 +247,7 @@ module Prism
37
247
  #
38
248
  # Foo && Foo = bar
39
249
  def visit_constant_and_write_node(node)
40
- desugar_and_write_node(node, ConstantReadNode, ConstantWriteNode, node.name)
250
+ node.desugar
41
251
  end
42
252
 
43
253
  # Foo ||= bar
@@ -46,7 +256,7 @@ module Prism
46
256
  #
47
257
  # defined?(Foo) ? Foo : Foo = bar
48
258
  def visit_constant_or_write_node(node)
49
- desugar_or_write_defined_node(node, ConstantReadNode, ConstantWriteNode, node.name)
259
+ node.desugar
50
260
  end
51
261
 
52
262
  # Foo += bar
@@ -55,7 +265,7 @@ module Prism
55
265
  #
56
266
  # Foo = Foo + bar
57
267
  def visit_constant_operator_write_node(node)
58
- desugar_operator_write_node(node, ConstantReadNode, ConstantWriteNode, node.name)
268
+ node.desugar
59
269
  end
60
270
 
61
271
  # $foo &&= bar
@@ -64,7 +274,7 @@ module Prism
64
274
  #
65
275
  # $foo && $foo = bar
66
276
  def visit_global_variable_and_write_node(node)
67
- desugar_and_write_node(node, GlobalVariableReadNode, GlobalVariableWriteNode, node.name)
277
+ node.desugar
68
278
  end
69
279
 
70
280
  # $foo ||= bar
@@ -73,7 +283,7 @@ module Prism
73
283
  #
74
284
  # defined?($foo) ? $foo : $foo = bar
75
285
  def visit_global_variable_or_write_node(node)
76
- desugar_or_write_defined_node(node, GlobalVariableReadNode, GlobalVariableWriteNode, node.name)
286
+ node.desugar
77
287
  end
78
288
 
79
289
  # $foo += bar
@@ -82,7 +292,7 @@ module Prism
82
292
  #
83
293
  # $foo = $foo + bar
84
294
  def visit_global_variable_operator_write_node(node)
85
- desugar_operator_write_node(node, GlobalVariableReadNode, GlobalVariableWriteNode, node.name)
295
+ node.desugar
86
296
  end
87
297
 
88
298
  # @foo &&= bar
@@ -91,7 +301,7 @@ module Prism
91
301
  #
92
302
  # @foo && @foo = bar
93
303
  def visit_instance_variable_and_write_node(node)
94
- desugar_and_write_node(node, InstanceVariableReadNode, InstanceVariableWriteNode, node.name)
304
+ node.desugar
95
305
  end
96
306
 
97
307
  # @foo ||= bar
@@ -100,7 +310,7 @@ module Prism
100
310
  #
101
311
  # @foo || @foo = bar
102
312
  def visit_instance_variable_or_write_node(node)
103
- desugar_or_write_node(node, InstanceVariableReadNode, InstanceVariableWriteNode, node.name)
313
+ node.desugar
104
314
  end
105
315
 
106
316
  # @foo += bar
@@ -109,7 +319,7 @@ module Prism
109
319
  #
110
320
  # @foo = @foo + bar
111
321
  def visit_instance_variable_operator_write_node(node)
112
- desugar_operator_write_node(node, InstanceVariableReadNode, InstanceVariableWriteNode, node.name)
322
+ node.desugar
113
323
  end
114
324
 
115
325
  # foo &&= bar
@@ -118,7 +328,7 @@ module Prism
118
328
  #
119
329
  # foo && foo = bar
120
330
  def visit_local_variable_and_write_node(node)
121
- desugar_and_write_node(node, LocalVariableReadNode, LocalVariableWriteNode, node.name, node.depth)
331
+ node.desugar
122
332
  end
123
333
 
124
334
  # foo ||= bar
@@ -127,7 +337,7 @@ module Prism
127
337
  #
128
338
  # foo || foo = bar
129
339
  def visit_local_variable_or_write_node(node)
130
- desugar_or_write_node(node, LocalVariableReadNode, LocalVariableWriteNode, node.name, node.depth)
340
+ node.desugar
131
341
  end
132
342
 
133
343
  # foo += bar
@@ -136,72 +346,7 @@ module Prism
136
346
  #
137
347
  # foo = foo + bar
138
348
  def visit_local_variable_operator_write_node(node)
139
- desugar_operator_write_node(node, LocalVariableReadNode, LocalVariableWriteNode, node.name, node.depth)
140
- end
141
-
142
- private
143
-
144
- # Desugar `x &&= y` to `x && x = y`
145
- def desugar_and_write_node(node, read_class, write_class, *arguments)
146
- AndNode.new(
147
- read_class.new(*arguments, node.name_loc),
148
- write_class.new(*arguments, node.name_loc, node.value, node.operator_loc, node.location),
149
- node.operator_loc,
150
- node.location
151
- )
152
- end
153
-
154
- # Desugar `x += y` to `x = x + y`
155
- def desugar_operator_write_node(node, read_class, write_class, *arguments)
156
- write_class.new(
157
- *arguments,
158
- node.name_loc,
159
- CallNode.new(
160
- 0,
161
- read_class.new(*arguments, node.name_loc),
162
- nil,
163
- node.operator_loc.slice.chomp("="),
164
- node.operator_loc.copy(length: node.operator_loc.length - 1),
165
- nil,
166
- ArgumentsNode.new(0, [node.value], node.value.location),
167
- nil,
168
- nil,
169
- node.location
170
- ),
171
- node.operator_loc.copy(start_offset: node.operator_loc.end_offset - 1, length: 1),
172
- node.location
173
- )
174
- end
175
-
176
- # Desugar `x ||= y` to `x || x = y`
177
- def desugar_or_write_node(node, read_class, write_class, *arguments)
178
- OrNode.new(
179
- read_class.new(*arguments, node.name_loc),
180
- write_class.new(*arguments, node.name_loc, node.value, node.operator_loc, node.location),
181
- node.operator_loc,
182
- node.location
183
- )
184
- end
185
-
186
- # Desugar `x ||= y` to `defined?(x) ? x : x = y`
187
- def desugar_or_write_defined_node(node, read_class, write_class, *arguments)
188
- IfNode.new(
189
- node.operator_loc,
190
- DefinedNode.new(nil, read_class.new(*arguments, node.name_loc), nil, node.operator_loc, node.name_loc),
191
- node.operator_loc,
192
- StatementsNode.new([read_class.new(*arguments, node.name_loc)], node.location),
193
- ElseNode.new(
194
- node.operator_loc,
195
- StatementsNode.new(
196
- [write_class.new(*arguments, node.name_loc, node.value, node.operator_loc, node.location)],
197
- node.location
198
- ),
199
- node.operator_loc,
200
- node.location
201
- ),
202
- node.operator_loc,
203
- node.location
204
- )
349
+ node.desugar
205
350
  end
206
351
  end
207
352
  end