prism 0.30.0 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -1
- data/README.md +3 -1
- data/config.yml +185 -126
- data/docs/serialization.md +3 -0
- data/ext/prism/api_node.c +2843 -2085
- data/ext/prism/extconf.rb +1 -1
- data/ext/prism/extension.c +35 -25
- data/ext/prism/extension.h +2 -2
- data/include/prism/ast.h +1048 -69
- data/include/prism/defines.h +9 -0
- data/include/prism/diagnostic.h +11 -3
- data/include/prism/options.h +55 -1
- data/include/prism/parser.h +27 -3
- data/include/prism/regexp.h +2 -1
- data/include/prism/util/pm_integer.h +6 -6
- data/include/prism/util/pm_newline_list.h +11 -0
- data/include/prism/util/pm_string.h +1 -0
- data/include/prism/version.h +3 -3
- data/lib/prism/desugar_compiler.rb +111 -74
- data/lib/prism/dispatcher.rb +2 -1
- data/lib/prism/dot_visitor.rb +21 -31
- data/lib/prism/dsl.rb +656 -471
- data/lib/prism/ffi.rb +3 -0
- data/lib/prism/inspect_visitor.rb +285 -57
- data/lib/prism/mutation_compiler.rb +5 -5
- data/lib/prism/node.rb +2282 -4754
- data/lib/prism/node_ext.rb +72 -11
- data/lib/prism/parse_result/errors.rb +65 -0
- data/lib/prism/parse_result/newlines.rb +28 -28
- data/lib/prism/parse_result.rb +25 -2
- data/lib/prism/reflection.rb +7 -7
- data/lib/prism/serialize.rb +468 -610
- data/lib/prism/translation/parser/compiler.rb +18 -18
- data/lib/prism/translation/parser/lexer.rb +1 -1
- data/lib/prism/translation/parser.rb +3 -3
- data/lib/prism/translation/ripper.rb +14 -14
- data/lib/prism/translation/ruby_parser.rb +43 -7
- data/prism.gemspec +3 -1
- data/rbi/prism/dsl.rbi +521 -0
- data/rbi/prism/node.rbi +1456 -5616
- data/rbi/prism.rbi +16 -16
- data/sig/prism/dsl.rbs +189 -305
- data/sig/prism/node.rbs +702 -603
- data/sig/prism/parse_result.rbs +2 -0
- data/src/diagnostic.c +22 -6
- data/src/node.c +277 -284
- data/src/options.c +18 -0
- data/src/prettyprint.c +99 -108
- data/src/prism.c +1282 -760
- data/src/regexp.c +72 -4
- data/src/serialize.c +165 -50
- data/src/token_type.c +2 -2
- data/src/util/pm_integer.c +14 -14
- data/src/util/pm_newline_list.c +29 -0
- data/src/util/pm_string.c +9 -5
- metadata +4 -2
data/include/prism/defines.h
CHANGED
@@ -118,6 +118,15 @@
|
|
118
118
|
# endif
|
119
119
|
#endif
|
120
120
|
|
121
|
+
/**
|
122
|
+
* If PRISM_HAS_NO_FILESYSTEM is defined, then we want to exclude all filesystem
|
123
|
+
* related code from the library. All filesystem related code should be guarded
|
124
|
+
* by PRISM_HAS_FILESYSTEM.
|
125
|
+
*/
|
126
|
+
#ifndef PRISM_HAS_NO_FILESYSTEM
|
127
|
+
# define PRISM_HAS_FILESYSTEM
|
128
|
+
#endif
|
129
|
+
|
121
130
|
/**
|
122
131
|
* isinf on Windows is defined as accepting a float, but on POSIX systems it
|
123
132
|
* accepts a float, a double, or a long double. We want to mirror this behavior
|
data/include/prism/diagnostic.h
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
|
1
|
+
/*----------------------------------------------------------------------------*/
|
2
2
|
/* This file is generated by the templates/template.rb script and should not */
|
3
3
|
/* be modified manually. See */
|
4
4
|
/* templates/include/prism/diagnostic.h.erb */
|
5
5
|
/* if you are looking to modify the */
|
6
6
|
/* template */
|
7
|
-
|
7
|
+
/*----------------------------------------------------------------------------*/
|
8
8
|
|
9
9
|
/**
|
10
10
|
* @file diagnostic.h
|
@@ -110,8 +110,10 @@ typedef enum {
|
|
110
110
|
PM_ERR_ESCAPE_INVALID_META_REPEAT,
|
111
111
|
PM_ERR_ESCAPE_INVALID_UNICODE,
|
112
112
|
PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS,
|
113
|
+
PM_ERR_ESCAPE_INVALID_UNICODE_LIST,
|
113
114
|
PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL,
|
114
115
|
PM_ERR_ESCAPE_INVALID_UNICODE_LONG,
|
116
|
+
PM_ERR_ESCAPE_INVALID_UNICODE_SHORT,
|
115
117
|
PM_ERR_ESCAPE_INVALID_UNICODE_TERM,
|
116
118
|
PM_ERR_EXPECT_ARGUMENT,
|
117
119
|
PM_ERR_EXPECT_EOL_AFTER_STATEMENT,
|
@@ -237,6 +239,7 @@ typedef enum {
|
|
237
239
|
PM_ERR_PARAMETER_UNEXPECTED_FWD,
|
238
240
|
PM_ERR_PARAMETER_UNEXPECTED_NO_KW,
|
239
241
|
PM_ERR_PARAMETER_WILD_LOOSE_COMMA,
|
242
|
+
PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS,
|
240
243
|
PM_ERR_PATTERN_CAPTURE_DUPLICATE,
|
241
244
|
PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET,
|
242
245
|
PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA,
|
@@ -248,6 +251,7 @@ typedef enum {
|
|
248
251
|
PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE,
|
249
252
|
PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE,
|
250
253
|
PM_ERR_PATTERN_EXPRESSION_AFTER_REST,
|
254
|
+
PM_ERR_PATTERN_FIND_MISSING_INNER,
|
251
255
|
PM_ERR_PATTERN_HASH_IMPLICIT,
|
252
256
|
PM_ERR_PATTERN_HASH_KEY,
|
253
257
|
PM_ERR_PATTERN_HASH_KEY_DUPLICATE,
|
@@ -290,11 +294,14 @@ typedef enum {
|
|
290
294
|
PM_ERR_TERNARY_COLON,
|
291
295
|
PM_ERR_TERNARY_EXPRESSION_FALSE,
|
292
296
|
PM_ERR_TERNARY_EXPRESSION_TRUE,
|
297
|
+
PM_ERR_UNARY_DISALLOWED,
|
293
298
|
PM_ERR_UNARY_RECEIVER,
|
294
299
|
PM_ERR_UNDEF_ARGUMENT,
|
295
300
|
PM_ERR_UNEXPECTED_BLOCK_ARGUMENT,
|
296
301
|
PM_ERR_UNEXPECTED_INDEX_BLOCK,
|
297
302
|
PM_ERR_UNEXPECTED_INDEX_KEYWORDS,
|
303
|
+
PM_ERR_UNEXPECTED_MULTI_WRITE,
|
304
|
+
PM_ERR_UNEXPECTED_RANGE_OPERATOR,
|
298
305
|
PM_ERR_UNEXPECTED_SAFE_NAVIGATION,
|
299
306
|
PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT,
|
300
307
|
PM_ERR_UNEXPECTED_TOKEN_IGNORE,
|
@@ -323,10 +330,11 @@ typedef enum {
|
|
323
330
|
PM_WARN_DUPLICATED_WHEN_CLAUSE,
|
324
331
|
PM_WARN_FLOAT_OUT_OF_RANGE,
|
325
332
|
PM_WARN_IGNORED_FROZEN_STRING_LITERAL,
|
333
|
+
PM_WARN_INDENTATION_MISMATCH,
|
326
334
|
PM_WARN_INTEGER_IN_FLIP_FLOP,
|
327
335
|
PM_WARN_INVALID_CHARACTER,
|
336
|
+
PM_WARN_INVALID_MAGIC_COMMENT_VALUE,
|
328
337
|
PM_WARN_INVALID_NUMBERED_REFERENCE,
|
329
|
-
PM_WARN_INVALID_SHAREABLE_CONSTANT_VALUE,
|
330
338
|
PM_WARN_KEYWORD_EOL,
|
331
339
|
PM_WARN_LITERAL_IN_CONDITION_DEFAULT,
|
332
340
|
PM_WARN_LITERAL_IN_CONDITION_VERBOSE,
|
data/include/prism/options.h
CHANGED
@@ -40,6 +40,23 @@ typedef struct pm_options_scope {
|
|
40
40
|
pm_string_t *locals;
|
41
41
|
} pm_options_scope_t;
|
42
42
|
|
43
|
+
// Forward declaration needed by the callback typedef.
|
44
|
+
struct pm_options;
|
45
|
+
|
46
|
+
/**
|
47
|
+
* The callback called when additional switches are found in a shebang comment
|
48
|
+
* that need to be processed by the runtime.
|
49
|
+
*
|
50
|
+
* @param options The options struct that may be updated by this callback.
|
51
|
+
* Certain fields will be checked for changes, specifically encoding,
|
52
|
+
* command_line, and frozen_string_literal.
|
53
|
+
* @param source The source of the shebang comment.
|
54
|
+
* @param length The length of the source.
|
55
|
+
* @param shebang_callback_data Any additional data that should be passed along
|
56
|
+
* to the callback.
|
57
|
+
*/
|
58
|
+
typedef void (*pm_options_shebang_callback_t)(struct pm_options *options, const uint8_t *source, size_t length, void *shebang_callback_data);
|
59
|
+
|
43
60
|
/**
|
44
61
|
* The version of Ruby syntax that we should be parsing with. This is used to
|
45
62
|
* allow consumers to specify which behavior they want in case they need to
|
@@ -56,7 +73,19 @@ typedef enum {
|
|
56
73
|
/**
|
57
74
|
* The options that can be passed to the parser.
|
58
75
|
*/
|
59
|
-
typedef struct {
|
76
|
+
typedef struct pm_options {
|
77
|
+
/**
|
78
|
+
* The callback to call when additional switches are found in a shebang
|
79
|
+
* comment.
|
80
|
+
*/
|
81
|
+
pm_options_shebang_callback_t shebang_callback;
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Any additional data that should be passed along to the shebang callback
|
85
|
+
* if one was set.
|
86
|
+
*/
|
87
|
+
void *shebang_callback_data;
|
88
|
+
|
60
89
|
/** The name of the file that is currently being parsed. */
|
61
90
|
pm_string_t filepath;
|
62
91
|
|
@@ -103,6 +132,13 @@ typedef struct {
|
|
103
132
|
* - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET
|
104
133
|
*/
|
105
134
|
int8_t frozen_string_literal;
|
135
|
+
|
136
|
+
/**
|
137
|
+
* Whether or not the encoding magic comments should be respected. This is a
|
138
|
+
* niche use-case where you want to parse a file with a specific encoding
|
139
|
+
* but ignore any encoding magic comments at the top of the file.
|
140
|
+
*/
|
141
|
+
bool encoding_locked;
|
106
142
|
} pm_options_t;
|
107
143
|
|
108
144
|
/**
|
@@ -142,6 +178,16 @@ static const uint8_t PM_OPTIONS_COMMAND_LINE_P = 0x10;
|
|
142
178
|
*/
|
143
179
|
static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20;
|
144
180
|
|
181
|
+
/**
|
182
|
+
* Set the shebang callback option on the given options struct.
|
183
|
+
*
|
184
|
+
* @param options The options struct to set the shebang callback on.
|
185
|
+
* @param shebang_callback The shebang callback to set.
|
186
|
+
* @param shebang_callback_data Any additional data that should be passed along
|
187
|
+
* to the callback.
|
188
|
+
*/
|
189
|
+
PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data);
|
190
|
+
|
145
191
|
/**
|
146
192
|
* Set the filepath option on the given options struct.
|
147
193
|
*
|
@@ -166,6 +212,14 @@ PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t
|
|
166
212
|
*/
|
167
213
|
PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding);
|
168
214
|
|
215
|
+
/**
|
216
|
+
* Set the encoding_locked option on the given options struct.
|
217
|
+
*
|
218
|
+
* @param options The options struct to set the encoding_locked value on.
|
219
|
+
* @param encoding_locked The encoding_locked value to set.
|
220
|
+
*/
|
221
|
+
PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked);
|
222
|
+
|
169
223
|
/**
|
170
224
|
* Set the frozen string literal option on the given options struct.
|
171
225
|
*
|
data/include/prism/parser.h
CHANGED
@@ -364,6 +364,9 @@ typedef enum {
|
|
364
364
|
/** a rescue statement within a lambda expression */
|
365
365
|
PM_CONTEXT_LAMBDA_RESCUE,
|
366
366
|
|
367
|
+
/** the predicate clause of a loop statement */
|
368
|
+
PM_CONTEXT_LOOP_PREDICATE,
|
369
|
+
|
367
370
|
/** the top level context */
|
368
371
|
PM_CONTEXT_MAIN,
|
369
372
|
|
@@ -505,9 +508,9 @@ typedef struct {
|
|
505
508
|
/** The type of shareable constant value that can be set. */
|
506
509
|
typedef uint8_t pm_shareable_constant_value_t;
|
507
510
|
static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_NONE = 0x0;
|
508
|
-
static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL =
|
509
|
-
static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING =
|
510
|
-
static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY =
|
511
|
+
static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL;
|
512
|
+
static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING;
|
513
|
+
static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY;
|
511
514
|
|
512
515
|
/**
|
513
516
|
* This tracks an individual local variable in a certain lexical context, as
|
@@ -622,6 +625,13 @@ typedef uint32_t pm_state_stack_t;
|
|
622
625
|
* it's considering.
|
623
626
|
*/
|
624
627
|
struct pm_parser {
|
628
|
+
/**
|
629
|
+
* The next node identifier that will be assigned. This is a unique
|
630
|
+
* identifier used to track nodes such that the syntax tree can be dropped
|
631
|
+
* but the node can be found through another parse.
|
632
|
+
*/
|
633
|
+
uint32_t node_id;
|
634
|
+
|
625
635
|
/** The current state of the lexer. */
|
626
636
|
pm_lex_state_t lex_state;
|
627
637
|
|
@@ -857,6 +867,14 @@ struct pm_parser {
|
|
857
867
|
/** Whether or not we're currently recovering from a syntax error. */
|
858
868
|
bool recovering;
|
859
869
|
|
870
|
+
/**
|
871
|
+
* This is very specialized behavior for when you want to parse in a context
|
872
|
+
* that does not respect encoding comments. Its main use case is translating
|
873
|
+
* into the whitequark/parser AST which re-encodes source files in UTF-8
|
874
|
+
* before they are parsed and ignores encoding comments.
|
875
|
+
*/
|
876
|
+
bool encoding_locked;
|
877
|
+
|
860
878
|
/**
|
861
879
|
* Whether or not the encoding has been changed by a magic comment. We use
|
862
880
|
* this to provide a fast path for the lexer instead of going through the
|
@@ -884,6 +902,12 @@ struct pm_parser {
|
|
884
902
|
* characters.
|
885
903
|
*/
|
886
904
|
bool current_regular_expression_ascii_only;
|
905
|
+
|
906
|
+
/**
|
907
|
+
* By default, Ruby always warns about mismatched indentation. This can be
|
908
|
+
* toggled with a magic comment.
|
909
|
+
*/
|
910
|
+
bool warn_mismatched_indentation;
|
887
911
|
};
|
888
912
|
|
889
913
|
#endif
|
data/include/prism/regexp.h
CHANGED
@@ -32,11 +32,12 @@ typedef void (*pm_regexp_error_callback_t)(const uint8_t *start, const uint8_t *
|
|
32
32
|
* @param parser The parser that is currently being used.
|
33
33
|
* @param source The source code to parse.
|
34
34
|
* @param size The size of the source code.
|
35
|
+
* @param extended_mode Whether to parse the regular expression in extended mode.
|
35
36
|
* @param name_callback The optional callback to call when a named capture group is found.
|
36
37
|
* @param name_data The optional data to pass to the name callback.
|
37
38
|
* @param error_callback The callback to call when a parse error is found.
|
38
39
|
* @param error_data The data to pass to the error callback.
|
39
40
|
*/
|
40
|
-
PRISM_EXPORTED_FUNCTION void pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, pm_regexp_name_callback_t name_callback, void *name_data, pm_regexp_error_callback_t error_callback, void *error_data);
|
41
|
+
PRISM_EXPORTED_FUNCTION void pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, bool extended_mode, pm_regexp_name_callback_t name_callback, void *name_data, pm_regexp_error_callback_t error_callback, void *error_data);
|
41
42
|
|
42
43
|
#endif
|
@@ -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.
|
@@ -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
|
data/include/prism/version.h
CHANGED
@@ -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
|
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
|
17
|
+
#define PRISM_VERSION_MINOR 0
|
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.
|
27
|
+
#define PRISM_VERSION "1.0.0"
|
28
28
|
|
29
29
|
#endif
|
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
module Prism
|
4
4
|
class DesugarAndWriteNode # :nodoc:
|
5
|
-
|
5
|
+
include DSL
|
6
6
|
|
7
|
-
|
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
|
-
@
|
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
|
-
|
18
|
-
|
19
|
-
read_class
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
36
|
+
include DSL
|
37
|
+
|
38
|
+
attr_reader :node, :default_source, :read_class, :write_class, :arguments
|
29
39
|
|
30
|
-
def initialize(node,
|
40
|
+
def initialize(node, default_source, read_class, write_class, **arguments)
|
31
41
|
@node = node
|
32
|
-
@
|
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
|
-
|
41
|
-
|
42
|
-
node.operator_loc,
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
87
|
+
include DSL
|
65
88
|
|
66
|
-
|
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
|
-
@
|
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
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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(
|
96
|
-
|
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
|
-
|
131
|
+
include DSL
|
103
132
|
|
104
|
-
|
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
|
-
@
|
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
|
-
|
115
|
-
|
116
|
-
read_class
|
117
|
-
|
118
|
-
|
119
|
-
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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
|
|
data/lib/prism/dispatcher.rb
CHANGED
@@ -22,7 +22,8 @@ module Prism
|
|
22
22
|
# end
|
23
23
|
# end
|
24
24
|
#
|
25
|
-
#
|
25
|
+
# listener = OctalListener.new
|
26
|
+
# dispatcher = Prism::Dispatcher.new
|
26
27
|
# dispatcher.register(listener, :on_integer_node_enter)
|
27
28
|
#
|
28
29
|
# Then, you can walk any number of trees and dispatch events to the listeners:
|