prism 0.19.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -1
  3. data/Makefile +5 -0
  4. data/README.md +8 -6
  5. data/config.yml +236 -38
  6. data/docs/build_system.md +19 -2
  7. data/docs/cruby_compilation.md +27 -0
  8. data/docs/parser_translation.md +34 -0
  9. data/docs/parsing_rules.md +19 -0
  10. data/docs/releasing.md +3 -3
  11. data/docs/ruby_api.md +1 -1
  12. data/docs/serialization.md +17 -5
  13. data/ext/prism/api_node.c +101 -81
  14. data/ext/prism/extension.c +74 -11
  15. data/ext/prism/extension.h +1 -1
  16. data/include/prism/ast.h +1699 -504
  17. data/include/prism/defines.h +8 -0
  18. data/include/prism/diagnostic.h +39 -2
  19. data/include/prism/encoding.h +10 -0
  20. data/include/prism/options.h +40 -14
  21. data/include/prism/parser.h +33 -17
  22. data/include/prism/util/pm_buffer.h +9 -0
  23. data/include/prism/util/pm_constant_pool.h +7 -0
  24. data/include/prism/util/pm_newline_list.h +0 -11
  25. data/include/prism/version.h +2 -2
  26. data/include/prism.h +19 -2
  27. data/lib/prism/debug.rb +11 -5
  28. data/lib/prism/dot_visitor.rb +36 -14
  29. data/lib/prism/dsl.rb +22 -22
  30. data/lib/prism/ffi.rb +2 -2
  31. data/lib/prism/node.rb +1020 -737
  32. data/lib/prism/node_ext.rb +2 -2
  33. data/lib/prism/parse_result.rb +17 -9
  34. data/lib/prism/serialize.rb +53 -29
  35. data/lib/prism/translation/parser/compiler.rb +1831 -0
  36. data/lib/prism/translation/parser/lexer.rb +335 -0
  37. data/lib/prism/translation/parser/rubocop.rb +37 -0
  38. data/lib/prism/translation/parser.rb +163 -0
  39. data/lib/prism/translation.rb +11 -0
  40. data/lib/prism.rb +1 -0
  41. data/prism.gemspec +12 -5
  42. data/rbi/prism.rbi +150 -88
  43. data/rbi/prism_static.rbi +15 -3
  44. data/sig/prism.rbs +996 -961
  45. data/sig/prism_static.rbs +123 -46
  46. data/src/diagnostic.c +259 -219
  47. data/src/encoding.c +4 -8
  48. data/src/node.c +2 -6
  49. data/src/options.c +24 -5
  50. data/src/prettyprint.c +174 -42
  51. data/src/prism.c +1136 -328
  52. data/src/serialize.c +12 -9
  53. data/src/token_type.c +353 -4
  54. data/src/util/pm_buffer.c +11 -0
  55. data/src/util/pm_constant_pool.c +12 -11
  56. data/src/util/pm_newline_list.c +2 -14
  57. metadata +10 -3
  58. data/docs/building.md +0 -29
@@ -16,6 +16,14 @@
16
16
  #include <stdio.h>
17
17
  #include <string.h>
18
18
 
19
+ /**
20
+ * We want to be able to use the PRI* macros for printing out integers, but on
21
+ * some platforms they aren't included unless this is already defined.
22
+ */
23
+ #define __STDC_FORMAT_MACROS
24
+
25
+ #include <inttypes.h>
26
+
19
27
  /**
20
28
  * By default, we compile with -fvisibility=hidden. When this is enabled, we
21
29
  * need to mark certain functions as being publically-visible. This macro does
@@ -14,6 +14,24 @@
14
14
  #include <stdlib.h>
15
15
  #include <assert.h>
16
16
 
17
+ /**
18
+ * The levels of errors generated during parsing.
19
+ */
20
+ typedef enum {
21
+ /** For errors that cannot be recovered from. */
22
+ PM_ERROR_LEVEL_FATAL = 0
23
+ } pm_error_level_t;
24
+
25
+ /**
26
+ * The levels of warnings generated during parsing.
27
+ */
28
+ typedef enum {
29
+ /** For warnings which should be emitted if $VERBOSE != nil. */
30
+ PM_WARNING_LEVEL_DEFAULT = 0,
31
+ /** For warnings which should be emitted if $VERBOSE == true. */
32
+ PM_WARNING_LEVEL_VERBOSE = 1
33
+ } pm_warning_level_t;
34
+
17
35
  /**
18
36
  * This struct represents a diagnostic generated during parsing.
19
37
  *
@@ -35,6 +53,12 @@ typedef struct {
35
53
  * diagnostic is freed.
36
54
  */
37
55
  bool owned;
56
+
57
+ /**
58
+ * The level of the diagnostic, see `pm_error_level_t` and
59
+ * `pm_warning_level_t` for possible values.
60
+ */
61
+ uint8_t level;
38
62
  } pm_diagnostic_t;
39
63
 
40
64
  /**
@@ -42,17 +66,24 @@ typedef struct {
42
66
  * of errors between the parser and the user.
43
67
  */
44
68
  typedef enum {
69
+ // This is a special error that we can potentially replace by others. For
70
+ // an example of how this is used, see parse_expression_prefix.
71
+ PM_ERR_CANNOT_PARSE_EXPRESSION,
72
+
73
+ // These are the error codes.
45
74
  PM_ERR_ALIAS_ARGUMENT,
46
75
  PM_ERR_AMPAMPEQ_MULTI_ASSIGN,
47
76
  PM_ERR_ARGUMENT_AFTER_BLOCK,
48
77
  PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES,
49
78
  PM_ERR_ARGUMENT_BARE_HASH,
79
+ PM_ERR_ARGUMENT_BLOCK_FORWARDING,
50
80
  PM_ERR_ARGUMENT_BLOCK_MULTI,
51
81
  PM_ERR_ARGUMENT_FORMAL_CLASS,
52
82
  PM_ERR_ARGUMENT_FORMAL_CONSTANT,
53
83
  PM_ERR_ARGUMENT_FORMAL_GLOBAL,
54
84
  PM_ERR_ARGUMENT_FORMAL_IVAR,
55
85
  PM_ERR_ARGUMENT_FORWARDING_UNBOUND,
86
+ PM_ERR_ARGUMENT_IN,
56
87
  PM_ERR_ARGUMENT_NO_FORWARDING_AMP,
57
88
  PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
58
89
  PM_ERR_ARGUMENT_NO_FORWARDING_STAR,
@@ -74,7 +105,6 @@ typedef enum {
74
105
  PM_ERR_BLOCK_PARAM_PIPE_TERM,
75
106
  PM_ERR_BLOCK_TERM_BRACE,
76
107
  PM_ERR_BLOCK_TERM_END,
77
- PM_ERR_CANNOT_PARSE_EXPRESSION,
78
108
  PM_ERR_CANNOT_PARSE_STRING_PART,
79
109
  PM_ERR_CASE_EXPRESSION_AFTER_CASE,
80
110
  PM_ERR_CASE_EXPRESSION_AFTER_WHEN,
@@ -165,6 +195,7 @@ typedef enum {
165
195
  PM_ERR_INVALID_PERCENT,
166
196
  PM_ERR_INVALID_TOKEN,
167
197
  PM_ERR_INVALID_VARIABLE_GLOBAL,
198
+ PM_ERR_IT_NOT_ALLOWED,
168
199
  PM_ERR_LAMBDA_OPEN,
169
200
  PM_ERR_LAMBDA_TERM_BRACE,
170
201
  PM_ERR_LAMBDA_TERM_END,
@@ -183,6 +214,7 @@ typedef enum {
183
214
  PM_ERR_MODULE_TERM,
184
215
  PM_ERR_MULTI_ASSIGN_MULTI_SPLATS,
185
216
  PM_ERR_NOT_EXPRESSION,
217
+ PM_ERR_NO_LOCAL_VARIABLE,
186
218
  PM_ERR_NUMBER_LITERAL_UNDERSCORE,
187
219
  PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED,
188
220
  PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE,
@@ -227,6 +259,7 @@ typedef enum {
227
259
  PM_ERR_RESCUE_TERM,
228
260
  PM_ERR_RESCUE_VARIABLE,
229
261
  PM_ERR_RETURN_INVALID,
262
+ PM_ERR_SINGLETON_FOR_LITERALS,
230
263
  PM_ERR_STATEMENT_ALIAS,
231
264
  PM_ERR_STATEMENT_POSTEXE_END,
232
265
  PM_ERR_STATEMENT_PREEXE_BEGIN,
@@ -244,6 +277,8 @@ typedef enum {
244
277
  PM_ERR_UNARY_RECEIVER_MINUS,
245
278
  PM_ERR_UNARY_RECEIVER_PLUS,
246
279
  PM_ERR_UNARY_RECEIVER_TILDE,
280
+ PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT,
281
+ PM_ERR_UNEXPECTED_TOKEN_IGNORE,
247
282
  PM_ERR_UNDEF_ARGUMENT,
248
283
  PM_ERR_UNTIL_TERM,
249
284
  PM_ERR_VOID_EXPRESSION,
@@ -252,13 +287,15 @@ typedef enum {
252
287
  PM_ERR_WRITE_TARGET_READONLY,
253
288
  PM_ERR_WRITE_TARGET_UNEXPECTED,
254
289
  PM_ERR_XSTRING_TERM,
290
+
291
+ // These are the warning codes.
255
292
  PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS,
256
293
  PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS,
257
294
  PM_WARN_AMBIGUOUS_PREFIX_STAR,
258
295
  PM_WARN_AMBIGUOUS_SLASH,
259
296
  PM_WARN_END_IN_METHOD,
260
297
 
261
- /* This must be the last member. */
298
+ // This is the number of diagnostic codes.
262
299
  PM_DIAGNOSTIC_ID_LEN,
263
300
  } pm_diagnostic_id_t;
264
301
 
@@ -79,6 +79,16 @@ typedef struct {
79
79
  */
80
80
  #define PRISM_ENCODING_UPPERCASE_BIT 1 << 2
81
81
 
82
+ /**
83
+ * Return the size of the next character in the UTF-8 encoding.
84
+ *
85
+ * @param b The bytes to read.
86
+ * @param n The number of bytes that can be read.
87
+ * @returns The number of bytes that the next character takes if it is valid in
88
+ * the encoding, or 0 if it is not.
89
+ */
90
+ size_t pm_encoding_utf_8_char_width(const uint8_t *b, ptrdiff_t n);
91
+
82
92
  /**
83
93
  * Return the size of the next character in the UTF-8 encoding if it is an
84
94
  * alphabetical character.
@@ -24,6 +24,19 @@ typedef struct pm_options_scope {
24
24
  pm_string_t *locals;
25
25
  } pm_options_scope_t;
26
26
 
27
+ /**
28
+ * The version of Ruby syntax that we should be parsing with. This is used to
29
+ * allow consumers to specify which behavior they want in case they need to
30
+ * parse in the same way as a specific version of CRuby would have.
31
+ */
32
+ typedef enum {
33
+ /** The current version of prism. */
34
+ PM_OPTIONS_VERSION_LATEST = 0,
35
+
36
+ /** The vendored version of prism in CRuby 3.3.0. */
37
+ PM_OPTIONS_VERSION_CRUBY_3_3_0 = 1
38
+ } pm_options_version_t;
39
+
27
40
  /**
28
41
  * The options that can be passed to the parser.
29
42
  */
@@ -33,7 +46,7 @@ typedef struct {
33
46
 
34
47
  /**
35
48
  * The line within the file that the parse starts on. This value is
36
- * 0-indexed.
49
+ * 1-indexed.
37
50
  */
38
51
  int32_t line;
39
52
 
@@ -51,19 +64,20 @@ typedef struct {
51
64
  /**
52
65
  * The scopes surrounding the code that is being parsed. For most parses
53
66
  * this will be NULL, but for evals it will be the locals that are in scope
54
- * surrounding the eval.
67
+ * surrounding the eval. Scopes are ordered from the outermost scope to the
68
+ * innermost one.
55
69
  */
56
70
  pm_options_scope_t *scopes;
57
71
 
58
- /** Whether or not the frozen string literal option has been set. */
59
- bool frozen_string_literal;
60
-
61
72
  /**
62
- * Whether or not we should suppress warnings. This is purposefully negated
63
- * so that the default is to not suppress warnings, which allows us to still
64
- * create an options struct with zeroed memory.
73
+ * The version of prism that we should be parsing with. This is used to
74
+ * allow consumers to specify which behavior they want in case they need to
75
+ * parse exactly as a specific version of CRuby.
65
76
  */
66
- bool suppress_warnings;
77
+ pm_options_version_t version;
78
+
79
+ /** Whether or not the frozen string literal option has been set. */
80
+ bool frozen_string_literal;
67
81
  } pm_options_t;
68
82
 
69
83
  /**
@@ -99,12 +113,16 @@ PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, cons
99
113
  PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal);
100
114
 
101
115
  /**
102
- * Set the suppress warnings option on the given options struct.
103
- *
104
- * @param options The options struct to set the suppress warnings value on.
105
- * @param suppress_warnings The suppress warnings value to set.
116
+ * Set the version option on the given options struct by parsing the given
117
+ * string. If the string contains an invalid option, this returns false.
118
+ * Otherwise, it returns true.
119
+ *
120
+ * @param options The options struct to set the version on.
121
+ * @param version The version to set.
122
+ * @param length The length of the version string.
123
+ * @return Whether or not the version was parsed successfully.
106
124
  */
107
- PRISM_EXPORTED_FUNCTION void pm_options_suppress_warnings_set(pm_options_t *options, bool suppress_warnings);
125
+ PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length);
108
126
 
109
127
  /**
110
128
  * Allocate and zero out the scopes array on the given options struct.
@@ -167,9 +185,17 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
167
185
  * | ... | the encoding bytes |
168
186
  * | `1` | frozen string literal |
169
187
  * | `1` | suppress warnings |
188
+ * | `1` | the version |
170
189
  * | `4` | the number of scopes |
171
190
  * | ... | the scopes |
172
191
  *
192
+ * The version field is an enum, so it should be one of the following values:
193
+ *
194
+ * | value | version |
195
+ * | ----- | ------------------------- |
196
+ * | `0` | use the latest version of prism |
197
+ * | `1` | use the version of prism that is vendored in CRuby 3.3.0 |
198
+ *
173
199
  * Each scope is layed out as follows:
174
200
  *
175
201
  * | # bytes | field |
@@ -9,6 +9,7 @@
9
9
  #include "prism/ast.h"
10
10
  #include "prism/defines.h"
11
11
  #include "prism/encoding.h"
12
+ #include "prism/options.h"
12
13
  #include "prism/util/pm_constant_pool.h"
13
14
  #include "prism/util/pm_list.h"
14
15
  #include "prism/util/pm_newline_list.h"
@@ -17,12 +18,6 @@
17
18
 
18
19
  #include <stdbool.h>
19
20
 
20
- // TODO: remove this by renaming the original flag
21
- /**
22
- * Temporary alias for the PM_NODE_FLAG_STATIC_KEYS flag.
23
- */
24
- #define PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS PM_KEYWORD_HASH_NODE_FLAGS_STATIC_KEYS
25
-
26
21
  /**
27
22
  * This enum provides various bits that represent different kinds of states that
28
23
  * the lexer can track. This is used to determine which kind of token to return
@@ -264,6 +259,9 @@ typedef struct pm_parser pm_parser_t;
264
259
  * token that is understood by a parent context but not by the current context.
265
260
  */
266
261
  typedef enum {
262
+ /** a null context, used for returning a value from a function */
263
+ PM_CONTEXT_NONE = 0,
264
+
267
265
  /** a begin statement */
268
266
  PM_CONTEXT_BEGIN,
269
267
 
@@ -471,6 +469,19 @@ typedef struct pm_scope {
471
469
  */
472
470
  bool explicit_params;
473
471
 
472
+ /**
473
+ * Booleans indicating whether the parameters for this scope have declared
474
+ * forwarding parameters.
475
+ *
476
+ * For example, some combinations of:
477
+ * def foo(*); end
478
+ * def foo(**); end
479
+ * def foo(&); end
480
+ * def foo(...); end
481
+ */
482
+
483
+ uint8_t forwarding_params;
484
+
474
485
  /**
475
486
  * An integer indicating the number of numbered parameters on this scope.
476
487
  * This is necessary to determine if child blocks are allowed to use
@@ -480,6 +491,11 @@ typedef struct pm_scope {
480
491
  uint8_t numbered_parameters;
481
492
  } pm_scope_t;
482
493
 
494
+ static const uint8_t PM_FORWARDING_POSITIONALS = 0x1;
495
+ static const uint8_t PM_FORWARDING_KEYWORDS = 0x2;
496
+ static const uint8_t PM_FORWARDING_BLOCK = 0x4;
497
+ static const uint8_t PM_FORWARDING_ALL = 0x8;
498
+
483
499
  /**
484
500
  * This struct represents the overall parser. It contains a reference to the
485
501
  * source file, as well as pointers that indicate where in the source it's
@@ -562,7 +578,11 @@ struct pm_parser {
562
578
  /** The list of magic comments that have been found while parsing. */
563
579
  pm_list_t magic_comment_list;
564
580
 
565
- /** The optional location of the __END__ keyword and its contents. */
581
+ /**
582
+ * An optional location that represents the location of the __END__ marker
583
+ * and the rest of the content of the file. This content is loaded into the
584
+ * DATA constant when the file being parsed is the main file being executed.
585
+ */
566
586
  pm_location_t data_loc;
567
587
 
568
588
  /** The list of warnings that have been found while parsing. */
@@ -668,6 +688,12 @@ struct pm_parser {
668
688
  */
669
689
  const pm_encoding_t *explicit_encoding;
670
690
 
691
+ /** The current parameter name id on parsing its default value. */
692
+ pm_constant_id_t current_param_name;
693
+
694
+ /** The version of prism that we should use to parse. */
695
+ pm_options_version_t version;
696
+
671
697
  /** Whether or not we're at the beginning of a command. */
672
698
  bool command_start;
673
699
 
@@ -690,9 +716,6 @@ struct pm_parser {
690
716
  /** This flag indicates that we are currently parsing a keyword argument. */
691
717
  bool in_keyword_arg;
692
718
 
693
- /** The current parameter name id on parsing its default value. */
694
- pm_constant_id_t current_param_name;
695
-
696
719
  /**
697
720
  * Whether or not the parser has seen a token that has semantic meaning
698
721
  * (i.e., a token that is not a comment or whitespace).
@@ -704,13 +727,6 @@ struct pm_parser {
704
727
  * a true value.
705
728
  */
706
729
  bool frozen_string_literal;
707
-
708
- /**
709
- * Whether or not we should emit warnings. This will be set to false if the
710
- * consumer of the library specified it, usually because they are parsing
711
- * when $VERBOSE is nil.
712
- */
713
- bool suppress_warnings;
714
730
  };
715
731
 
716
732
  #endif
@@ -128,6 +128,15 @@ void pm_buffer_append_varuint(pm_buffer_t *buffer, uint32_t value);
128
128
  */
129
129
  void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value);
130
130
 
131
+ /**
132
+ * Prepend the given string to the buffer.
133
+ *
134
+ * @param buffer The buffer to prepend to.
135
+ * @param value The string to prepend.
136
+ * @param length The length of the string to prepend.
137
+ */
138
+ void pm_buffer_prepend_string(pm_buffer_t *buffer, const char *value, size_t length);
139
+
131
140
  /**
132
141
  * Concatenate one buffer onto another.
133
142
  *
@@ -18,6 +18,13 @@
18
18
  #include <stdlib.h>
19
19
  #include <string.h>
20
20
 
21
+ /**
22
+ * When we allocate constants into the pool, we reserve 0 to mean that the slot
23
+ * is not yet filled. This constant is reused in other places to indicate the
24
+ * lack of a constant id.
25
+ */
26
+ #define PM_CONSTANT_ID_UNSET 0
27
+
21
28
  /**
22
29
  * A constant id is a unique identifier for a constant in the constant pool.
23
30
  */
@@ -72,17 +72,6 @@ bool pm_newline_list_init(pm_newline_list_t *list, const uint8_t *start, size_t
72
72
  */
73
73
  bool pm_newline_list_append(pm_newline_list_t *list, const uint8_t *cursor);
74
74
 
75
- /**
76
- * Conditionally append a new offset to the newline list, if the value passed in
77
- * is a newline.
78
- *
79
- * @param list The list to append to.
80
- * @param cursor A pointer to the offset to append.
81
- * @return True if the reallocation of the offsets succeeds (if one was
82
- * necessary), otherwise false.
83
- */
84
- bool pm_newline_list_check_append(pm_newline_list_t *list, const uint8_t *cursor);
85
-
86
75
  /**
87
76
  * Returns the line and column of the given offset. If the offset is not in the
88
77
  * list, the line and column of the closest offset less than the given offset
@@ -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 19
17
+ #define PRISM_VERSION_MINOR 20
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.19.0"
27
+ #define PRISM_VERSION "0.20.0"
28
28
 
29
29
  #endif
data/include/prism.h CHANGED
@@ -168,7 +168,24 @@ PRISM_EXPORTED_FUNCTION bool pm_parse_success_p(const uint8_t *source, size_t si
168
168
  * @param token_type The token type to convert to a string.
169
169
  * @return A string representation of the given token type.
170
170
  */
171
- PRISM_EXPORTED_FUNCTION const char * pm_token_type_to_str(pm_token_type_t token_type);
171
+ PRISM_EXPORTED_FUNCTION const char * pm_token_type_name(pm_token_type_t token_type);
172
+
173
+ /**
174
+ * Returns the human name of the given token type.
175
+ *
176
+ * @param token_type The token type to convert to a human name.
177
+ * @return The human name of the given token type.
178
+ */
179
+ const char * pm_token_type_human(pm_token_type_t token_type);
180
+
181
+ /**
182
+ * Format the errors on the parser into the given buffer.
183
+ *
184
+ * @param parser The parser to format the errors for.
185
+ * @param buffer The buffer to format the errors into.
186
+ * @param colorize Whether or not to colorize the errors with ANSI escape sequences.
187
+ */
188
+ PRISM_EXPORTED_FUNCTION void pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool colorize);
172
189
 
173
190
  /**
174
191
  * @mainpage
@@ -260,7 +277,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_token_type_to_str(pm_token_type_t token_
260
277
  * pm_buffer_t buffer = { 0 };
261
278
  *
262
279
  * pm_prettyprint(&buffer, &parser, root);
263
- * printf("*.s%\n", (int) buffer.length, buffer.value);
280
+ * printf("%*.s\n", (int) buffer.length, buffer.value);
264
281
  *
265
282
  * pm_buffer_free(&buffer);
266
283
  * pm_node_destroy(&parser, root);
data/lib/prism/debug.rb CHANGED
@@ -138,12 +138,14 @@ module Prism
138
138
  *params.keywords.grep(OptionalKeywordParameterNode).map(&:name),
139
139
  ]
140
140
 
141
+ sorted << AnonymousLocal if params.keywords.any?
142
+
141
143
  if params.keyword_rest.is_a?(ForwardingParameterNode)
142
- sorted.push(:*, :&, :"...")
144
+ sorted.push(:*, :**, :&, :"...")
145
+ elsif params.keyword_rest.is_a?(KeywordRestParameterNode)
146
+ sorted << (params.keyword_rest.name || :**)
143
147
  end
144
148
 
145
- sorted << AnonymousLocal if params.keywords.any?
146
-
147
149
  # Recurse down the parameter tree to find any destructured
148
150
  # parameters and add them after the other parameters.
149
151
  param_stack = params.requireds.concat(params.posts).grep(MultiTargetNode).reverse
@@ -151,15 +153,19 @@ module Prism
151
153
  case param
152
154
  when MultiTargetNode
153
155
  param_stack.concat(param.rights.reverse)
154
- param_stack << param.rest
156
+ param_stack << param.rest if param.rest&.expression && !sorted.include?(param.rest.expression.name)
155
157
  param_stack.concat(param.lefts.reverse)
156
158
  when RequiredParameterNode
157
159
  sorted << param.name
158
160
  when SplatNode
159
- sorted << param.expression.name if param.expression
161
+ sorted << param.expression.name
160
162
  end
161
163
  end
162
164
 
165
+ if params.block
166
+ sorted << (params.block.name || :&)
167
+ end
168
+
163
169
  names = sorted.concat(names - sorted)
164
170
  end
165
171
 
@@ -353,10 +353,8 @@ module Prism
353
353
  digraph.edge("#{id}:key -> #{node_id(node.key)};")
354
354
 
355
355
  # value
356
- unless (value = node.value).nil?
357
- table.field("value", port: true)
358
- digraph.edge("#{id}:value -> #{node_id(value)};")
359
- end
356
+ table.field("value", port: true)
357
+ digraph.edge("#{id}:value -> #{node_id(node.value)};")
360
358
 
361
359
  # operator_loc
362
360
  unless (operator_loc = node.operator_loc).nil?
@@ -488,6 +486,9 @@ module Prism
488
486
  table = Table.new("BlockLocalVariableNode")
489
487
  id = node_id(node)
490
488
 
489
+ # flags
490
+ table.field("flags", parameter_flags_inspect(node))
491
+
491
492
  # name
492
493
  table.field("name", node.name.inspect)
493
494
 
@@ -508,9 +509,6 @@ module Prism
508
509
  # locals
509
510
  table.field("locals", node.locals.inspect)
510
511
 
511
- # locals_body_index
512
- table.field("locals_body_index", node.locals_body_index.inspect)
513
-
514
512
  # parameters
515
513
  unless (parameters = node.parameters).nil?
516
514
  table.field("parameters", port: true)
@@ -543,6 +541,9 @@ module Prism
543
541
  table = Table.new("BlockParameterNode")
544
542
  id = node_id(node)
545
543
 
544
+ # flags
545
+ table.field("flags", parameter_flags_inspect(node))
546
+
546
547
  # name
547
548
  table.field("name", node.name.inspect)
548
549
 
@@ -1501,9 +1502,6 @@ module Prism
1501
1502
  # locals
1502
1503
  table.field("locals", node.locals.inspect)
1503
1504
 
1504
- # locals_body_index
1505
- table.field("locals_body_index", node.locals_body_index.inspect)
1506
-
1507
1505
  # def_keyword_loc
1508
1506
  table.field("def_keyword_loc", location_inspect(node.def_keyword_loc))
1509
1507
 
@@ -2805,6 +2803,9 @@ module Prism
2805
2803
  table = Table.new("KeywordRestParameterNode")
2806
2804
  id = node_id(node)
2807
2805
 
2806
+ # flags
2807
+ table.field("flags", parameter_flags_inspect(node))
2808
+
2808
2809
  # name
2809
2810
  table.field("name", node.name.inspect)
2810
2811
 
@@ -2833,9 +2834,6 @@ module Prism
2833
2834
  # locals
2834
2835
  table.field("locals", node.locals.inspect)
2835
2836
 
2836
- # locals_body_index
2837
- table.field("locals_body_index", node.locals_body_index.inspect)
2838
-
2839
2837
  # operator_loc
2840
2838
  table.field("operator_loc", location_inspect(node.operator_loc))
2841
2839
 
@@ -3404,6 +3402,9 @@ module Prism
3404
3402
  table = Table.new("OptionalKeywordParameterNode")
3405
3403
  id = node_id(node)
3406
3404
 
3405
+ # flags
3406
+ table.field("flags", parameter_flags_inspect(node))
3407
+
3407
3408
  # name
3408
3409
  table.field("name", node.name.inspect)
3409
3410
 
@@ -3428,6 +3429,9 @@ module Prism
3428
3429
  table = Table.new("OptionalParameterNode")
3429
3430
  id = node_id(node)
3430
3431
 
3432
+ # flags
3433
+ table.field("flags", parameter_flags_inspect(node))
3434
+
3431
3435
  # name
3432
3436
  table.field("name", node.name.inspect)
3433
3437
 
@@ -3810,6 +3814,9 @@ module Prism
3810
3814
  table = Table.new("RequiredKeywordParameterNode")
3811
3815
  id = node_id(node)
3812
3816
 
3817
+ # flags
3818
+ table.field("flags", parameter_flags_inspect(node))
3819
+
3813
3820
  # name
3814
3821
  table.field("name", node.name.inspect)
3815
3822
 
@@ -3830,6 +3837,9 @@ module Prism
3830
3837
  table = Table.new("RequiredParameterNode")
3831
3838
  id = node_id(node)
3832
3839
 
3840
+ # flags
3841
+ table.field("flags", parameter_flags_inspect(node))
3842
+
3833
3843
  # name
3834
3844
  table.field("name", node.name.inspect)
3835
3845
 
@@ -3925,6 +3935,9 @@ module Prism
3925
3935
  table = Table.new("RestParameterNode")
3926
3936
  id = node_id(node)
3927
3937
 
3938
+ # flags
3939
+ table.field("flags", parameter_flags_inspect(node))
3940
+
3928
3941
  # name
3929
3942
  table.field("name", node.name.inspect)
3930
3943
 
@@ -4524,6 +4537,7 @@ module Prism
4524
4537
  flags << "safe_navigation" if node.safe_navigation?
4525
4538
  flags << "variable_call" if node.variable_call?
4526
4539
  flags << "attribute_write" if node.attribute_write?
4540
+ flags << "ignore_visibility" if node.ignore_visibility?
4527
4541
  flags.join(", ")
4528
4542
  end
4529
4543
 
@@ -4551,7 +4565,7 @@ module Prism
4551
4565
  # comma-separated list.
4552
4566
  def keyword_hash_node_flags_inspect(node)
4553
4567
  flags = []
4554
- flags << "static_keys" if node.static_keys?
4568
+ flags << "symbol_keys" if node.symbol_keys?
4555
4569
  flags.join(", ")
4556
4570
  end
4557
4571
 
@@ -4563,6 +4577,14 @@ module Prism
4563
4577
  flags.join(", ")
4564
4578
  end
4565
4579
 
4580
+ # Inspect a node that has parameter_flags flags to display the flags as a
4581
+ # comma-separated list.
4582
+ def parameter_flags_inspect(node)
4583
+ flags = []
4584
+ flags << "repeated_parameter" if node.repeated_parameter?
4585
+ flags.join(", ")
4586
+ end
4587
+
4566
4588
  # Inspect a node that has range_flags flags to display the flags as a
4567
4589
  # comma-separated list.
4568
4590
  def range_flags_inspect(node)