prism 0.29.0 → 1.3.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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +115 -1
  3. data/CONTRIBUTING.md +0 -4
  4. data/Makefile +1 -1
  5. data/README.md +4 -0
  6. data/config.yml +920 -148
  7. data/docs/build_system.md +8 -11
  8. data/docs/fuzzing.md +1 -1
  9. data/docs/parsing_rules.md +4 -1
  10. data/docs/relocation.md +34 -0
  11. data/docs/ripper_translation.md +22 -0
  12. data/docs/serialization.md +3 -0
  13. data/ext/prism/api_node.c +2863 -2079
  14. data/ext/prism/extconf.rb +14 -37
  15. data/ext/prism/extension.c +241 -391
  16. data/ext/prism/extension.h +2 -2
  17. data/include/prism/ast.h +2156 -453
  18. data/include/prism/defines.h +58 -7
  19. data/include/prism/diagnostic.h +24 -6
  20. data/include/prism/node.h +0 -21
  21. data/include/prism/options.h +94 -3
  22. data/include/prism/parser.h +82 -40
  23. data/include/prism/regexp.h +18 -8
  24. data/include/prism/static_literals.h +3 -2
  25. data/include/prism/util/pm_char.h +1 -2
  26. data/include/prism/util/pm_constant_pool.h +0 -8
  27. data/include/prism/util/pm_integer.h +22 -15
  28. data/include/prism/util/pm_newline_list.h +11 -0
  29. data/include/prism/util/pm_string.h +28 -12
  30. data/include/prism/version.h +3 -3
  31. data/include/prism.h +47 -11
  32. data/lib/prism/compiler.rb +3 -0
  33. data/lib/prism/desugar_compiler.rb +111 -74
  34. data/lib/prism/dispatcher.rb +16 -1
  35. data/lib/prism/dot_visitor.rb +55 -34
  36. data/lib/prism/dsl.rb +660 -468
  37. data/lib/prism/ffi.rb +113 -8
  38. data/lib/prism/inspect_visitor.rb +296 -64
  39. data/lib/prism/lex_compat.rb +1 -1
  40. data/lib/prism/mutation_compiler.rb +11 -6
  41. data/lib/prism/node.rb +4262 -5023
  42. data/lib/prism/node_ext.rb +91 -14
  43. data/lib/prism/parse_result/comments.rb +0 -7
  44. data/lib/prism/parse_result/errors.rb +65 -0
  45. data/lib/prism/parse_result/newlines.rb +101 -11
  46. data/lib/prism/parse_result.rb +183 -6
  47. data/lib/prism/reflection.rb +12 -10
  48. data/lib/prism/relocation.rb +504 -0
  49. data/lib/prism/serialize.rb +496 -609
  50. data/lib/prism/string_query.rb +30 -0
  51. data/lib/prism/translation/parser/compiler.rb +185 -155
  52. data/lib/prism/translation/parser/lexer.rb +26 -4
  53. data/lib/prism/translation/parser.rb +9 -4
  54. data/lib/prism/translation/ripper.rb +23 -25
  55. data/lib/prism/translation/ruby_parser.rb +86 -17
  56. data/lib/prism/visitor.rb +3 -0
  57. data/lib/prism.rb +6 -8
  58. data/prism.gemspec +9 -5
  59. data/rbi/prism/dsl.rbi +521 -0
  60. data/rbi/prism/node.rbi +1115 -1120
  61. data/rbi/prism/parse_result.rbi +29 -0
  62. data/rbi/prism/string_query.rbi +12 -0
  63. data/rbi/prism/visitor.rbi +3 -0
  64. data/rbi/prism.rbi +36 -30
  65. data/sig/prism/dsl.rbs +190 -303
  66. data/sig/prism/mutation_compiler.rbs +1 -0
  67. data/sig/prism/node.rbs +678 -632
  68. data/sig/prism/parse_result.rbs +22 -0
  69. data/sig/prism/relocation.rbs +185 -0
  70. data/sig/prism/string_query.rbs +11 -0
  71. data/sig/prism/visitor.rbs +1 -0
  72. data/sig/prism.rbs +103 -64
  73. data/src/diagnostic.c +64 -28
  74. data/src/node.c +502 -1739
  75. data/src/options.c +76 -27
  76. data/src/prettyprint.c +188 -112
  77. data/src/prism.c +3376 -2293
  78. data/src/regexp.c +208 -71
  79. data/src/serialize.c +182 -50
  80. data/src/static_literals.c +64 -85
  81. data/src/token_type.c +4 -4
  82. data/src/util/pm_char.c +1 -1
  83. data/src/util/pm_constant_pool.c +0 -8
  84. data/src/util/pm_integer.c +53 -25
  85. data/src/util/pm_newline_list.c +29 -0
  86. data/src/util/pm_string.c +131 -80
  87. data/src/util/pm_strpbrk.c +32 -6
  88. metadata +11 -7
  89. data/include/prism/util/pm_string_list.h +0 -44
  90. data/lib/prism/debug.rb +0 -249
  91. data/lib/prism/translation/parser/rubocop.rb +0 -73
  92. data/src/util/pm_string_list.c +0 -28
@@ -95,9 +95,10 @@ typedef struct {
95
95
  * @param start_line The line number that the parser starts on.
96
96
  * @param literals The set of static literals to add the node to.
97
97
  * @param node The node to add to the set.
98
+ * @param replace Whether to replace the previous node if one already exists.
98
99
  * @return A pointer to the node that is being overwritten, if there is one.
99
100
  */
100
- pm_node_t * pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node);
101
+ pm_node_t * pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace);
101
102
 
102
103
  /**
103
104
  * Free the internal memory associated with the given static literals set.
@@ -115,6 +116,6 @@ void pm_static_literals_free(pm_static_literals_t *literals);
115
116
  * @param encoding_name The name of the encoding of the source being parsed.
116
117
  * @param node The node to create a string representation of.
117
118
  */
118
- PRISM_EXPORTED_FUNCTION void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, int32_t start_line, const char *encoding_name, const pm_node_t *node);
119
+ void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, int32_t start_line, const char *encoding_name, const pm_node_t *node);
119
120
 
120
121
  #endif
@@ -34,8 +34,7 @@ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length);
34
34
  * @return The number of characters at the start of the string that are
35
35
  * whitespace.
36
36
  */
37
- size_t
38
- pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_newline_list_t *newline_list);
37
+ size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_newline_list_t *newline_list);
39
38
 
40
39
  /**
41
40
  * Returns the number of characters at the start of the string that are inline
@@ -87,14 +87,6 @@ void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_co
87
87
  */
88
88
  bool pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id);
89
89
 
90
- /**
91
- * Get the memory size of a list of constant ids.
92
- *
93
- * @param list The list to get the memory size of.
94
- * @return The memory size of the list.
95
- */
96
- size_t pm_constant_id_list_memsize(pm_constant_id_list_t *list);
97
-
98
90
  /**
99
91
  * Free the memory associated with a list of constant ids.
100
92
  *
@@ -18,12 +18,6 @@
18
18
  * A structure represents an arbitrary-sized integer.
19
19
  */
20
20
  typedef struct {
21
- /**
22
- * Embedded value for small integer. This value is set to 0 if the value
23
- * does not fit into uint32_t.
24
- */
25
- uint32_t value;
26
-
27
21
  /**
28
22
  * The number of allocated values. length is set to 0 if the integer fits
29
23
  * into uint32_t.
@@ -35,6 +29,12 @@ typedef struct {
35
29
  */
36
30
  uint32_t *values;
37
31
 
32
+ /**
33
+ * Embedded value for small integer. This value is set to 0 if the value
34
+ * does not fit into uint32_t.
35
+ */
36
+ uint32_t value;
37
+
38
38
  /**
39
39
  * Whether or not the integer is negative. It is stored this way so that a
40
40
  * zeroed pm_integer_t is always positive zero.
@@ -48,6 +48,9 @@ typedef struct {
48
48
  * from the string itself.
49
49
  */
50
50
  typedef enum {
51
+ /** The default decimal base, with no prefix. Leading 0s will be ignored. */
52
+ PM_INTEGER_BASE_DEFAULT,
53
+
51
54
  /** The binary base, indicated by a 0b or 0B prefix. */
52
55
  PM_INTEGER_BASE_BINARY,
53
56
 
@@ -79,15 +82,7 @@ typedef enum {
79
82
  * @param start The start of the string.
80
83
  * @param end The end of the string.
81
84
  */
82
- PRISM_EXPORTED_FUNCTION void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end);
83
-
84
- /**
85
- * Return the memory size of the integer.
86
- *
87
- * @param integer The integer to get the memory size of.
88
- * @return The size of the memory associated with the integer.
89
- */
90
- size_t pm_integer_memsize(const pm_integer_t *integer);
85
+ void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end);
91
86
 
92
87
  /**
93
88
  * Compare two integers. This function returns -1 if the left integer is less
@@ -100,6 +95,18 @@ size_t pm_integer_memsize(const pm_integer_t *integer);
100
95
  */
101
96
  int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right);
102
97
 
98
+ /**
99
+ * Reduce a ratio of integers to its simplest form.
100
+ *
101
+ * If either the numerator or denominator do not fit into a 32-bit integer, then
102
+ * this function is a no-op. In the future, we may consider reducing even the
103
+ * larger numbers, but for now we're going to keep it simple.
104
+ *
105
+ * @param numerator The numerator of the ratio.
106
+ * @param denominator The denominator of the ratio.
107
+ */
108
+ void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator);
109
+
103
110
  /**
104
111
  * Convert an integer to a decimal string.
105
112
  *
@@ -80,6 +80,17 @@ pm_newline_list_clear(pm_newline_list_t *list);
80
80
  */
81
81
  bool pm_newline_list_append(pm_newline_list_t *list, const uint8_t *cursor);
82
82
 
83
+ /**
84
+ * Returns the line of the given offset. If the offset is not in the list, the
85
+ * line of the closest offset less than the given offset is returned.
86
+ *
87
+ * @param list The list to search.
88
+ * @param cursor A pointer to the offset to search for.
89
+ * @param start_line The line to start counting from.
90
+ * @return The line of the given offset.
91
+ */
92
+ int32_t pm_newline_list_line(const pm_newline_list_t *list, const uint8_t *cursor, int32_t start_line);
93
+
83
94
  /**
84
95
  * Returns the line and column of the given offset. If the offset is not in the
85
96
  * list, the line and column of the closest offset less than the given offset
@@ -9,6 +9,7 @@
9
9
  #include "prism/defines.h"
10
10
 
11
11
  #include <assert.h>
12
+ #include <errno.h>
12
13
  #include <stdbool.h>
13
14
  #include <stddef.h>
14
15
  #include <stdlib.h>
@@ -21,6 +22,9 @@
21
22
  #include <fcntl.h>
22
23
  #include <sys/mman.h>
23
24
  #include <sys/stat.h>
25
+ #elif defined(PRISM_HAS_FILESYSTEM)
26
+ #include <fcntl.h>
27
+ #include <sys/stat.h>
24
28
  #endif
25
29
 
26
30
  /**
@@ -92,6 +96,26 @@ void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length);
92
96
  */
93
97
  void pm_string_constant_init(pm_string_t *string, const char *source, size_t length);
94
98
 
99
+ /**
100
+ * Represents the result of calling pm_string_mapped_init or
101
+ * pm_string_file_init. We need this additional information because there is
102
+ * not a platform-agnostic way to indicate that the file that was attempted to
103
+ * be opened was a directory.
104
+ */
105
+ typedef enum {
106
+ /** Indicates that the string was successfully initialized. */
107
+ PM_STRING_INIT_SUCCESS = 0,
108
+ /**
109
+ * Indicates a generic error from a string_*_init function, where the type
110
+ * of error should be read from `errno` or `GetLastError()`.
111
+ */
112
+ PM_STRING_INIT_ERROR_GENERIC = 1,
113
+ /**
114
+ * Indicates that the file that was attempted to be opened was a directory.
115
+ */
116
+ PM_STRING_INIT_ERROR_DIRECTORY = 2
117
+ } pm_string_init_result_t;
118
+
95
119
  /**
96
120
  * Read the file indicated by the filepath parameter into source and load its
97
121
  * contents and size into the given `pm_string_t`. The given `pm_string_t`
@@ -105,9 +129,9 @@ void pm_string_constant_init(pm_string_t *string, const char *source, size_t len
105
129
  *
106
130
  * @param string The string to initialize.
107
131
  * @param filepath The filepath to read.
108
- * @return Whether or not the file was successfully mapped.
132
+ * @return The success of the read, indicated by the value of the enum.
109
133
  */
110
- PRISM_EXPORTED_FUNCTION bool pm_string_mapped_init(pm_string_t *string, const char *filepath);
134
+ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath);
111
135
 
112
136
  /**
113
137
  * Read the file indicated by the filepath parameter into source and load its
@@ -116,17 +140,9 @@ PRISM_EXPORTED_FUNCTION bool pm_string_mapped_init(pm_string_t *string, const ch
116
140
  *
117
141
  * @param string The string to initialize.
118
142
  * @param filepath The filepath to read.
119
- * @return Whether or not the file was successfully read.
120
- */
121
- PRISM_EXPORTED_FUNCTION bool pm_string_file_init(pm_string_t *string, const char *filepath);
122
-
123
- /**
124
- * Returns the memory size associated with the string.
125
- *
126
- * @param string The string to get the memory size of.
127
- * @return The size of the memory associated with the string.
143
+ * @return The success of the read, indicated by the value of the enum.
128
144
  */
129
- size_t pm_string_memsize(const pm_string_t *string);
145
+ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath);
130
146
 
131
147
  /**
132
148
  * Ensure the string is owned. If it is not, then reinitialize it as owned and
@@ -9,12 +9,12 @@
9
9
  /**
10
10
  * The major version of the Prism library as an int.
11
11
  */
12
- #define PRISM_VERSION_MAJOR 0
12
+ #define PRISM_VERSION_MAJOR 1
13
13
 
14
14
  /**
15
15
  * The minor version of the Prism library as an int.
16
16
  */
17
- #define PRISM_VERSION_MINOR 29
17
+ #define PRISM_VERSION_MINOR 3
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.29.0"
27
+ #define PRISM_VERSION "1.3.0"
28
28
 
29
29
  #endif
data/include/prism.h CHANGED
@@ -219,17 +219,6 @@ PRISM_EXPORTED_FUNCTION const char * pm_token_type_name(pm_token_type_t token_ty
219
219
  */
220
220
  const char * pm_token_type_human(pm_token_type_t token_type);
221
221
 
222
- /**
223
- * Format the errors on the parser into the given buffer.
224
- *
225
- * @param parser The parser to format the errors for.
226
- * @param error_list The list of errors to format.
227
- * @param buffer The buffer to format the errors into.
228
- * @param colorize Whether or not to colorize the errors with ANSI escape sequences.
229
- * @param inline_messages Whether or not to inline the messages with the source.
230
- */
231
- PRISM_EXPORTED_FUNCTION void pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, pm_buffer_t *buffer, bool colorize, bool inline_messages);
232
-
233
222
  // We optionally support dumping to JSON. For systems that don't want or need
234
223
  // this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define.
235
224
  #ifndef PRISM_EXCLUDE_JSON
@@ -245,6 +234,53 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t
245
234
 
246
235
  #endif
247
236
 
237
+ /**
238
+ * Represents the results of a slice query.
239
+ */
240
+ typedef enum {
241
+ /** Returned if the encoding given to a slice query was invalid. */
242
+ PM_STRING_QUERY_ERROR = -1,
243
+
244
+ /** Returned if the result of the slice query is false. */
245
+ PM_STRING_QUERY_FALSE,
246
+
247
+ /** Returned if the result of the slice query is true. */
248
+ PM_STRING_QUERY_TRUE
249
+ } pm_string_query_t;
250
+
251
+ /**
252
+ * Check that the slice is a valid local variable name.
253
+ *
254
+ * @param source The source to check.
255
+ * @param length The length of the source.
256
+ * @param encoding_name The name of the encoding of the source.
257
+ * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if
258
+ * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid.
259
+ */
260
+ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name);
261
+
262
+ /**
263
+ * Check that the slice is a valid constant name.
264
+ *
265
+ * @param source The source to check.
266
+ * @param length The length of the source.
267
+ * @param encoding_name The name of the encoding of the source.
268
+ * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if
269
+ * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid.
270
+ */
271
+ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name);
272
+
273
+ /**
274
+ * Check that the slice is a valid method name.
275
+ *
276
+ * @param source The source to check.
277
+ * @param length The length of the source.
278
+ * @param encoding_name The name of the encoding of the source.
279
+ * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if
280
+ * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid.
281
+ */
282
+ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name);
283
+
248
284
  /**
249
285
  * @mainpage
250
286
  *
@@ -301,6 +301,9 @@ module Prism
301
301
  # Compile a InterpolatedXStringNode node
302
302
  alias visit_interpolated_x_string_node visit_child_nodes
303
303
 
304
+ # Compile a ItLocalVariableReadNode node
305
+ alias visit_it_local_variable_read_node visit_child_nodes
306
+
304
307
  # Compile a ItParametersNode node
305
308
  alias visit_it_parameters_node visit_child_nodes
306
309
 
@@ -2,11 +2,13 @@
2
2
 
3
3
  module Prism
4
4
  class DesugarAndWriteNode # :nodoc:
5
- attr_reader :node, :source, :read_class, :write_class, :arguments
5
+ include DSL
6
6
 
7
- def initialize(node, source, read_class, write_class, *arguments)
7
+ attr_reader :node, :default_source, :read_class, :write_class, :arguments
8
+
9
+ def initialize(node, default_source, read_class, write_class, **arguments)
8
10
  @node = node
9
- @source = source
11
+ @default_source = default_source
10
12
  @read_class = read_class
11
13
  @write_class = write_class
12
14
  @arguments = arguments
@@ -14,22 +16,30 @@ module Prism
14
16
 
15
17
  # Desugar `x &&= y` to `x && x = y`
16
18
  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
19
+ and_node(
20
+ location: node.location,
21
+ left: public_send(read_class, location: node.name_loc, **arguments),
22
+ right: public_send(
23
+ write_class,
24
+ location: node.location,
25
+ **arguments,
26
+ name_loc: node.name_loc,
27
+ value: node.value,
28
+ operator_loc: node.operator_loc
29
+ ),
30
+ operator_loc: node.operator_loc
23
31
  )
24
32
  end
25
33
  end
26
34
 
27
35
  class DesugarOrWriteDefinedNode # :nodoc:
28
- attr_reader :node, :source, :read_class, :write_class, :arguments
36
+ include DSL
37
+
38
+ attr_reader :node, :default_source, :read_class, :write_class, :arguments
29
39
 
30
- def initialize(node, source, read_class, write_class, *arguments)
40
+ def initialize(node, default_source, read_class, write_class, **arguments)
31
41
  @node = node
32
- @source = source
42
+ @default_source = default_source
33
43
  @read_class = read_class
34
44
  @write_class = write_class
35
45
  @arguments = arguments
@@ -37,35 +47,50 @@ module Prism
37
47
 
38
48
  # Desugar `x ||= y` to `defined?(x) ? x : x = y`
39
49
  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
50
+ if_node(
51
+ location: node.location,
52
+ if_keyword_loc: node.operator_loc,
53
+ predicate: defined_node(
54
+ location: node.name_loc,
55
+ value: public_send(read_class, location: node.name_loc, **arguments),
56
+ keyword_loc: node.operator_loc
57
+ ),
58
+ then_keyword_loc: node.operator_loc,
59
+ statements: statements_node(
60
+ location: node.location,
61
+ body: [public_send(read_class, location: node.name_loc, **arguments)]
62
+ ),
63
+ subsequent: else_node(
64
+ location: node.location,
65
+ else_keyword_loc: node.operator_loc,
66
+ statements: statements_node(
67
+ location: node.location,
68
+ body: [
69
+ public_send(
70
+ write_class,
71
+ location: node.location,
72
+ **arguments,
73
+ name_loc: node.name_loc,
74
+ value: node.value,
75
+ operator_loc: node.operator_loc
76
+ )
77
+ ]
53
78
  ),
54
- node.operator_loc,
55
- node.location
79
+ end_keyword_loc: node.operator_loc
56
80
  ),
57
- node.operator_loc,
58
- node.location
81
+ end_keyword_loc: node.operator_loc
59
82
  )
60
83
  end
61
84
  end
62
85
 
63
86
  class DesugarOperatorWriteNode # :nodoc:
64
- attr_reader :node, :source, :read_class, :write_class, :arguments
87
+ include DSL
65
88
 
66
- def initialize(node, source, read_class, write_class, *arguments)
89
+ attr_reader :node, :default_source, :read_class, :write_class, :arguments
90
+
91
+ def initialize(node, default_source, read_class, write_class, **arguments)
67
92
  @node = node
68
- @source = source
93
+ @default_source = default_source
69
94
  @read_class = read_class
70
95
  @write_class = write_class
71
96
  @arguments = arguments
@@ -75,35 +100,41 @@ module Prism
75
100
  def compile
76
101
  binary_operator_loc = node.binary_operator_loc.chop
77
102
 
78
- write_class.new(
79
- source,
80
- *arguments,
81
- node.name_loc,
82
- CallNode.new(
83
- source,
84
- 0,
85
- read_class.new(source, *arguments, node.name_loc),
86
- nil,
87
- binary_operator_loc.slice.to_sym,
88
- binary_operator_loc,
89
- nil,
90
- ArgumentsNode.new(source, 0, [node.value], node.value.location),
91
- nil,
92
- nil,
93
- node.location
103
+ public_send(
104
+ write_class,
105
+ location: node.location,
106
+ **arguments,
107
+ name_loc: node.name_loc,
108
+ value: call_node(
109
+ location: node.location,
110
+ receiver: public_send(
111
+ read_class,
112
+ location: node.name_loc,
113
+ **arguments
114
+ ),
115
+ name: binary_operator_loc.slice.to_sym,
116
+ message_loc: binary_operator_loc,
117
+ arguments: arguments_node(
118
+ location: node.value.location,
119
+ arguments: [node.value]
120
+ )
94
121
  ),
95
- node.binary_operator_loc.copy(start_offset: node.binary_operator_loc.end_offset - 1, length: 1),
96
- node.location
122
+ operator_loc: node.binary_operator_loc.copy(
123
+ start_offset: node.binary_operator_loc.end_offset - 1,
124
+ length: 1
125
+ )
97
126
  )
98
127
  end
99
128
  end
100
129
 
101
130
  class DesugarOrWriteNode # :nodoc:
102
- attr_reader :node, :source, :read_class, :write_class, :arguments
131
+ include DSL
103
132
 
104
- def initialize(node, source, read_class, write_class, *arguments)
133
+ attr_reader :node, :default_source, :read_class, :write_class, :arguments
134
+
135
+ def initialize(node, default_source, read_class, write_class, **arguments)
105
136
  @node = node
106
- @source = source
137
+ @default_source = default_source
107
138
  @read_class = read_class
108
139
  @write_class = write_class
109
140
  @arguments = arguments
@@ -111,12 +142,18 @@ module Prism
111
142
 
112
143
  # Desugar `x ||= y` to `x || x = y`
113
144
  def compile
114
- OrNode.new(
115
- source,
116
- read_class.new(source, *arguments, node.name_loc),
117
- write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location),
118
- node.operator_loc,
119
- node.location
145
+ or_node(
146
+ location: node.location,
147
+ left: public_send(read_class, location: node.name_loc, **arguments),
148
+ right: public_send(
149
+ write_class,
150
+ location: node.location,
151
+ **arguments,
152
+ name_loc: node.name_loc,
153
+ value: node.value,
154
+ operator_loc: node.operator_loc
155
+ ),
156
+ operator_loc: node.operator_loc
120
157
  )
121
158
  end
122
159
  end
@@ -125,91 +162,91 @@ module Prism
125
162
 
126
163
  class ClassVariableAndWriteNode
127
164
  def desugar # :nodoc:
128
- DesugarAndWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
165
+ DesugarAndWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile
129
166
  end
130
167
  end
131
168
 
132
169
  class ClassVariableOrWriteNode
133
170
  def desugar # :nodoc:
134
- DesugarOrWriteDefinedNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
171
+ DesugarOrWriteDefinedNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile
135
172
  end
136
173
  end
137
174
 
138
175
  class ClassVariableOperatorWriteNode
139
176
  def desugar # :nodoc:
140
- DesugarOperatorWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
177
+ DesugarOperatorWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile
141
178
  end
142
179
  end
143
180
 
144
181
  class ConstantAndWriteNode
145
182
  def desugar # :nodoc:
146
- DesugarAndWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
183
+ DesugarAndWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile
147
184
  end
148
185
  end
149
186
 
150
187
  class ConstantOrWriteNode
151
188
  def desugar # :nodoc:
152
- DesugarOrWriteDefinedNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
189
+ DesugarOrWriteDefinedNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile
153
190
  end
154
191
  end
155
192
 
156
193
  class ConstantOperatorWriteNode
157
194
  def desugar # :nodoc:
158
- DesugarOperatorWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
195
+ DesugarOperatorWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile
159
196
  end
160
197
  end
161
198
 
162
199
  class GlobalVariableAndWriteNode
163
200
  def desugar # :nodoc:
164
- DesugarAndWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
201
+ DesugarAndWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile
165
202
  end
166
203
  end
167
204
 
168
205
  class GlobalVariableOrWriteNode
169
206
  def desugar # :nodoc:
170
- DesugarOrWriteDefinedNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
207
+ DesugarOrWriteDefinedNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile
171
208
  end
172
209
  end
173
210
 
174
211
  class GlobalVariableOperatorWriteNode
175
212
  def desugar # :nodoc:
176
- DesugarOperatorWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
213
+ DesugarOperatorWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile
177
214
  end
178
215
  end
179
216
 
180
217
  class InstanceVariableAndWriteNode
181
218
  def desugar # :nodoc:
182
- DesugarAndWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
219
+ DesugarAndWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile
183
220
  end
184
221
  end
185
222
 
186
223
  class InstanceVariableOrWriteNode
187
224
  def desugar # :nodoc:
188
- DesugarOrWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
225
+ DesugarOrWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile
189
226
  end
190
227
  end
191
228
 
192
229
  class InstanceVariableOperatorWriteNode
193
230
  def desugar # :nodoc:
194
- DesugarOperatorWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
231
+ DesugarOperatorWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile
195
232
  end
196
233
  end
197
234
 
198
235
  class LocalVariableAndWriteNode
199
236
  def desugar # :nodoc:
200
- DesugarAndWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
237
+ DesugarAndWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile
201
238
  end
202
239
  end
203
240
 
204
241
  class LocalVariableOrWriteNode
205
242
  def desugar # :nodoc:
206
- DesugarOrWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
243
+ DesugarOrWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile
207
244
  end
208
245
  end
209
246
 
210
247
  class LocalVariableOperatorWriteNode
211
248
  def desugar # :nodoc:
212
- DesugarOperatorWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
249
+ DesugarOperatorWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile
213
250
  end
214
251
  end
215
252