prism 1.3.0 → 1.4.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 +24 -1
- data/config.yml +9 -0
- data/docs/releasing.md +1 -1
- data/docs/ruby_api.md +1 -1
- data/ext/prism/api_node.c +1814 -1303
- data/ext/prism/extension.c +230 -109
- data/ext/prism/extension.h +4 -4
- data/include/prism/ast.h +16 -0
- data/include/prism/defines.h +4 -1
- data/include/prism/options.h +47 -1
- data/include/prism/util/pm_buffer.h +10 -0
- data/include/prism/version.h +2 -2
- data/include/prism.h +4 -4
- data/lib/prism/dot_visitor.rb +16 -0
- data/lib/prism/dsl.rb +10 -2
- data/lib/prism/ffi.rb +45 -27
- data/lib/prism/inspect_visitor.rb +2 -1
- data/lib/prism/node.rb +48 -10
- data/lib/prism/parse_result/newlines.rb +1 -1
- data/lib/prism/parse_result.rb +52 -0
- data/lib/prism/polyfill/append_as_bytes.rb +15 -0
- data/lib/prism/reflection.rb +2 -2
- data/lib/prism/serialize.rb +1252 -765
- data/lib/prism/translation/parser/builder.rb +61 -0
- data/lib/prism/translation/parser/compiler.rb +192 -136
- data/lib/prism/translation/parser/lexer.rb +435 -61
- data/lib/prism/translation/parser.rb +51 -3
- data/lib/prism/translation/parser35.rb +12 -0
- data/lib/prism/translation/ripper.rb +13 -3
- data/lib/prism/translation/ruby_parser.rb +5 -4
- data/lib/prism/translation.rb +1 -0
- data/lib/prism.rb +3 -3
- data/prism.gemspec +5 -1
- data/rbi/prism/dsl.rbi +6 -3
- data/rbi/prism/node.rbi +22 -7
- data/rbi/prism/parse_result.rbi +17 -0
- data/rbi/prism/translation/parser35.rbi +6 -0
- data/rbi/prism.rbi +39 -36
- data/sig/prism/dsl.rbs +4 -2
- data/sig/prism/node.rbs +17 -7
- data/sig/prism/parse_result.rbs +10 -0
- data/sig/prism/serialize.rbs +4 -2
- data/sig/prism.rbs +22 -1
- data/src/diagnostic.c +2 -2
- data/src/node.c +21 -0
- data/src/options.c +31 -0
- data/src/prettyprint.c +30 -0
- data/src/prism.c +374 -118
- data/src/serialize.c +6 -0
- data/src/util/pm_buffer.c +40 -0
- data/src/util/pm_constant_pool.c +6 -2
- data/src/util/pm_strncasecmp.c +13 -1
- metadata +7 -7
data/include/prism/options.h
CHANGED
@@ -39,8 +39,26 @@ typedef struct pm_options_scope {
|
|
39
39
|
|
40
40
|
/** The names of the locals in the scope. */
|
41
41
|
pm_string_t *locals;
|
42
|
+
|
43
|
+
/** Flags for the set of forwarding parameters in this scope. */
|
44
|
+
uint8_t forwarding;
|
42
45
|
} pm_options_scope_t;
|
43
46
|
|
47
|
+
/** The default value for parameters. */
|
48
|
+
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_NONE = 0x0;
|
49
|
+
|
50
|
+
/** When the scope is fowarding with the * parameter. */
|
51
|
+
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS = 0x1;
|
52
|
+
|
53
|
+
/** When the scope is fowarding with the ** parameter. */
|
54
|
+
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS = 0x2;
|
55
|
+
|
56
|
+
/** When the scope is fowarding with the & parameter. */
|
57
|
+
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_BLOCK = 0x4;
|
58
|
+
|
59
|
+
/** When the scope is fowarding with the ... parameter. */
|
60
|
+
static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_ALL = 0x8;
|
61
|
+
|
44
62
|
// Forward declaration needed by the callback typedef.
|
45
63
|
struct pm_options;
|
46
64
|
|
@@ -68,7 +86,10 @@ typedef enum {
|
|
68
86
|
PM_OPTIONS_VERSION_LATEST = 0,
|
69
87
|
|
70
88
|
/** The vendored version of prism in CRuby 3.3.x. */
|
71
|
-
PM_OPTIONS_VERSION_CRUBY_3_3 = 1
|
89
|
+
PM_OPTIONS_VERSION_CRUBY_3_3 = 1,
|
90
|
+
|
91
|
+
/** The vendored version of prism in CRuby 3.4.x. */
|
92
|
+
PM_OPTIONS_VERSION_CRUBY_3_4 = 2
|
72
93
|
} pm_options_version_t;
|
73
94
|
|
74
95
|
/**
|
@@ -157,6 +178,13 @@ typedef struct pm_options {
|
|
157
178
|
* inside another script.
|
158
179
|
*/
|
159
180
|
bool partial_script;
|
181
|
+
|
182
|
+
/**
|
183
|
+
* Whether or not the parser should freeze the nodes that it creates. This
|
184
|
+
* makes it possible to have a deeply frozen AST that is safe to share
|
185
|
+
* between concurrency primitives.
|
186
|
+
*/
|
187
|
+
bool freeze;
|
160
188
|
} pm_options_t;
|
161
189
|
|
162
190
|
/**
|
@@ -282,6 +310,14 @@ PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, b
|
|
282
310
|
*/
|
283
311
|
PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options, bool partial_script);
|
284
312
|
|
313
|
+
/**
|
314
|
+
* Set the freeze option on the given options struct.
|
315
|
+
*
|
316
|
+
* @param options The options struct to set the freeze value on.
|
317
|
+
* @param freeze The freeze value to set.
|
318
|
+
*/
|
319
|
+
PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool freeze);
|
320
|
+
|
285
321
|
/**
|
286
322
|
* Allocate and zero out the scopes array on the given options struct.
|
287
323
|
*
|
@@ -319,6 +355,14 @@ PRISM_EXPORTED_FUNCTION bool pm_options_scope_init(pm_options_scope_t *scope, si
|
|
319
355
|
*/
|
320
356
|
PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index);
|
321
357
|
|
358
|
+
/**
|
359
|
+
* Set the forwarding option on the given scope struct.
|
360
|
+
*
|
361
|
+
* @param scope The scope struct to set the forwarding on.
|
362
|
+
* @param forwarding The forwarding value to set.
|
363
|
+
*/
|
364
|
+
PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding);
|
365
|
+
|
322
366
|
/**
|
323
367
|
* Free the internal memory associated with the options.
|
324
368
|
*
|
@@ -352,6 +396,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
|
|
352
396
|
* | `1` | encoding locked |
|
353
397
|
* | `1` | main script |
|
354
398
|
* | `1` | partial script |
|
399
|
+
* | `1` | freeze |
|
355
400
|
* | `4` | the number of scopes |
|
356
401
|
* | ... | the scopes |
|
357
402
|
*
|
@@ -367,6 +412,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
|
|
367
412
|
* | # bytes | field |
|
368
413
|
* | ------- | -------------------------- |
|
369
414
|
* | `4` | the number of locals |
|
415
|
+
* | `1` | the forwarding flags |
|
370
416
|
* | ... | the locals |
|
371
417
|
*
|
372
418
|
* Each local is laid out as follows:
|
@@ -137,6 +137,16 @@ void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value);
|
|
137
137
|
*/
|
138
138
|
void pm_buffer_append_double(pm_buffer_t *buffer, double value);
|
139
139
|
|
140
|
+
/**
|
141
|
+
* Append a unicode codepoint to the buffer.
|
142
|
+
*
|
143
|
+
* @param buffer The buffer to append to.
|
144
|
+
* @param value The character to append.
|
145
|
+
* @returns True if the codepoint was valid and appended successfully, false
|
146
|
+
* otherwise.
|
147
|
+
*/
|
148
|
+
bool pm_buffer_append_unicode_codepoint(pm_buffer_t *buffer, uint32_t value);
|
149
|
+
|
140
150
|
/**
|
141
151
|
* The different types of escaping that can be performed by the buffer when
|
142
152
|
* appending a slice of Ruby source code.
|
data/include/prism/version.h
CHANGED
@@ -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
|
17
|
+
#define PRISM_VERSION_MINOR 4
|
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 "1.
|
27
|
+
#define PRISM_VERSION "1.4.0"
|
28
28
|
|
29
29
|
#endif
|
data/include/prism.h
CHANGED
@@ -93,11 +93,11 @@ typedef char * (pm_parse_stream_fgets_t)(char *string, int size, void *stream);
|
|
93
93
|
* @param parser The parser to use.
|
94
94
|
* @param buffer The buffer to use.
|
95
95
|
* @param stream The stream to parse.
|
96
|
-
* @param
|
96
|
+
* @param stream_fgets The function to use to read from the stream.
|
97
97
|
* @param options The optional options to use when parsing.
|
98
98
|
* @return The AST representing the source.
|
99
99
|
*/
|
100
|
-
PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *
|
100
|
+
PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, const pm_options_t *options);
|
101
101
|
|
102
102
|
// We optionally support serializing to a binary string. For systems that don't
|
103
103
|
// want or need this functionality, it can be turned off with the
|
@@ -110,10 +110,10 @@ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buff
|
|
110
110
|
*
|
111
111
|
* @param buffer The buffer to serialize to.
|
112
112
|
* @param stream The stream to parse.
|
113
|
-
* @param
|
113
|
+
* @param stream_fgets The function to use to read from the stream.
|
114
114
|
* @param data The optional data to pass to the parser.
|
115
115
|
*/
|
116
|
-
PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *
|
116
|
+
PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, const char *data);
|
117
117
|
|
118
118
|
/**
|
119
119
|
* Serialize the given list of comments to the given buffer.
|
data/lib/prism/dot_visitor.rb
CHANGED
@@ -3608,6 +3608,9 @@ module Prism
|
|
3608
3608
|
table = Table.new("ParenthesesNode")
|
3609
3609
|
id = node_id(node)
|
3610
3610
|
|
3611
|
+
# flags
|
3612
|
+
table.field("flags", parentheses_node_flags_inspect(node))
|
3613
|
+
|
3611
3614
|
# body
|
3612
3615
|
unless (body = node.body).nil?
|
3613
3616
|
table.field("body", port: true)
|
@@ -3954,6 +3957,11 @@ module Prism
|
|
3954
3957
|
digraph.edge("#{id}:reference -> #{node_id(reference)};")
|
3955
3958
|
end
|
3956
3959
|
|
3960
|
+
# then_keyword_loc
|
3961
|
+
unless (then_keyword_loc = node.then_keyword_loc).nil?
|
3962
|
+
table.field("then_keyword_loc", location_inspect(then_keyword_loc))
|
3963
|
+
end
|
3964
|
+
|
3957
3965
|
# statements
|
3958
3966
|
unless (statements = node.statements).nil?
|
3959
3967
|
table.field("statements", port: true)
|
@@ -4682,6 +4690,14 @@ module Prism
|
|
4682
4690
|
flags.join(", ")
|
4683
4691
|
end
|
4684
4692
|
|
4693
|
+
# Inspect a node that has parentheses_node_flags flags to display the flags as a
|
4694
|
+
# comma-separated list.
|
4695
|
+
def parentheses_node_flags_inspect(node)
|
4696
|
+
flags = [] #: Array[String]
|
4697
|
+
flags << "multiple_statements" if node.multiple_statements?
|
4698
|
+
flags.join(", ")
|
4699
|
+
end
|
4700
|
+
|
4685
4701
|
# Inspect a node that has range_flags flags to display the flags as a
|
4686
4702
|
# comma-separated list.
|
4687
4703
|
def range_flags_inspect(node)
|
data/lib/prism/dsl.rb
CHANGED
@@ -714,8 +714,8 @@ module Prism
|
|
714
714
|
end
|
715
715
|
|
716
716
|
# Create a new RescueNode node.
|
717
|
-
def rescue_node(source: default_source, node_id: 0, location: default_location, flags: 0, keyword_loc: location, exceptions: [], operator_loc: nil, reference: nil, statements: nil, subsequent: nil)
|
718
|
-
RescueNode.new(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, statements, subsequent)
|
717
|
+
def rescue_node(source: default_source, node_id: 0, location: default_location, flags: 0, keyword_loc: location, exceptions: [], operator_loc: nil, reference: nil, then_keyword_loc: nil, statements: nil, subsequent: nil)
|
718
|
+
RescueNode.new(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, then_keyword_loc, statements, subsequent)
|
719
719
|
end
|
720
720
|
|
721
721
|
# Create a new RestParameterNode node.
|
@@ -912,6 +912,14 @@ module Prism
|
|
912
912
|
end
|
913
913
|
end
|
914
914
|
|
915
|
+
# Retrieve the value of one of the ParenthesesNodeFlags flags.
|
916
|
+
def parentheses_node_flag(name)
|
917
|
+
case name
|
918
|
+
when :multiple_statements then ParenthesesNodeFlags::MULTIPLE_STATEMENTS
|
919
|
+
else Kernel.raise ArgumentError, "invalid ParenthesesNodeFlags flag: #{name.inspect}"
|
920
|
+
end
|
921
|
+
end
|
922
|
+
|
915
923
|
# Retrieve the value of one of the RangeFlags flags.
|
916
924
|
def range_flag(name)
|
917
925
|
case name
|
data/lib/prism/ffi.rb
CHANGED
@@ -15,7 +15,8 @@ module Prism
|
|
15
15
|
# must align with the build shared library from make/rake.
|
16
16
|
libprism_in_build = File.expand_path("../../build/libprism.#{RbConfig::CONFIG["SOEXT"]}", __dir__)
|
17
17
|
libprism_in_libdir = "#{RbConfig::CONFIG["libdir"]}/prism/libprism.#{RbConfig::CONFIG["SOEXT"]}"
|
18
|
-
|
18
|
+
|
19
|
+
if File.exist?(libprism_in_build)
|
19
20
|
INCLUDE_DIR = File.expand_path("../../include", __dir__)
|
20
21
|
ffi_lib libprism_in_build
|
21
22
|
else
|
@@ -279,7 +280,7 @@ module Prism
|
|
279
280
|
# access to the IO object already through the closure of the lambda, we
|
280
281
|
# can pass a null pointer here and not worry.
|
281
282
|
LibRubyParser.pm_serialize_parse_stream(buffer.pointer, nil, callback, dump_options(options))
|
282
|
-
Prism.load(source, buffer.read)
|
283
|
+
Prism.load(source, buffer.read, options.fetch(:freeze, false))
|
283
284
|
end
|
284
285
|
end
|
285
286
|
|
@@ -354,50 +355,37 @@ module Prism
|
|
354
355
|
def dump_common(string, options) # :nodoc:
|
355
356
|
LibRubyParser::PrismBuffer.with do |buffer|
|
356
357
|
LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
|
357
|
-
|
358
|
+
|
359
|
+
dumped = buffer.read
|
360
|
+
dumped.freeze if options.fetch(:freeze, false)
|
361
|
+
|
362
|
+
dumped
|
358
363
|
end
|
359
364
|
end
|
360
365
|
|
361
366
|
def lex_common(string, code, options) # :nodoc:
|
362
|
-
|
367
|
+
LibRubyParser::PrismBuffer.with do |buffer|
|
363
368
|
LibRubyParser.pm_serialize_lex(buffer.pointer, string.pointer, string.length, dump_options(options))
|
364
|
-
buffer.read
|
369
|
+
Serialize.load_lex(code, buffer.read, options.fetch(:freeze, false))
|
365
370
|
end
|
366
|
-
|
367
|
-
Serialize.load_tokens(Source.for(code), serialized)
|
368
371
|
end
|
369
372
|
|
370
373
|
def parse_common(string, code, options) # :nodoc:
|
371
374
|
serialized = dump_common(string, options)
|
372
|
-
|
375
|
+
Serialize.load_parse(code, serialized, options.fetch(:freeze, false))
|
373
376
|
end
|
374
377
|
|
375
378
|
def parse_comments_common(string, code, options) # :nodoc:
|
376
379
|
LibRubyParser::PrismBuffer.with do |buffer|
|
377
380
|
LibRubyParser.pm_serialize_parse_comments(buffer.pointer, string.pointer, string.length, dump_options(options))
|
378
|
-
|
379
|
-
source = Source.for(code)
|
380
|
-
loader = Serialize::Loader.new(source, buffer.read)
|
381
|
-
|
382
|
-
loader.load_header
|
383
|
-
loader.load_encoding
|
384
|
-
loader.load_start_line
|
385
|
-
loader.load_comments
|
381
|
+
Serialize.load_parse_comments(code, buffer.read, options.fetch(:freeze, false))
|
386
382
|
end
|
387
383
|
end
|
388
384
|
|
389
385
|
def parse_lex_common(string, code, options) # :nodoc:
|
390
386
|
LibRubyParser::PrismBuffer.with do |buffer|
|
391
387
|
LibRubyParser.pm_serialize_parse_lex(buffer.pointer, string.pointer, string.length, dump_options(options))
|
392
|
-
|
393
|
-
source = Source.for(code)
|
394
|
-
loader = Serialize::Loader.new(source, buffer.read)
|
395
|
-
|
396
|
-
tokens = loader.load_tokens
|
397
|
-
node, comments, magic_comments, data_loc, errors, warnings = loader.load_nodes
|
398
|
-
tokens.each { |token,| token.value.force_encoding(loader.encoding) }
|
399
|
-
|
400
|
-
ParseLexResult.new([node, tokens], comments, magic_comments, data_loc, errors, warnings, source)
|
388
|
+
Serialize.load_parse_lex(code, buffer.read, options.fetch(:freeze, false))
|
401
389
|
end
|
402
390
|
end
|
403
391
|
|
@@ -431,6 +419,8 @@ module Prism
|
|
431
419
|
when /\A3\.3(\.\d+)?\z/
|
432
420
|
1
|
433
421
|
when /\A3\.4(\.\d+)?\z/
|
422
|
+
2
|
423
|
+
when /\A3\.5(\.\d+)?\z/
|
434
424
|
0
|
435
425
|
else
|
436
426
|
raise ArgumentError, "invalid version: #{version}"
|
@@ -480,15 +470,43 @@ module Prism
|
|
480
470
|
template << "C"
|
481
471
|
values << (options.fetch(:partial_script, false) ? 1 : 0)
|
482
472
|
|
473
|
+
template << "C"
|
474
|
+
values << (options.fetch(:freeze, false) ? 1 : 0)
|
475
|
+
|
483
476
|
template << "L"
|
484
477
|
if (scopes = options[:scopes])
|
485
478
|
values << scopes.length
|
486
479
|
|
487
480
|
scopes.each do |scope|
|
481
|
+
locals = nil
|
482
|
+
forwarding = 0
|
483
|
+
|
484
|
+
case scope
|
485
|
+
when Array
|
486
|
+
locals = scope
|
487
|
+
when Scope
|
488
|
+
locals = scope.locals
|
489
|
+
|
490
|
+
scope.forwarding.each do |forward|
|
491
|
+
case forward
|
492
|
+
when :* then forwarding |= 0x1
|
493
|
+
when :** then forwarding |= 0x2
|
494
|
+
when :& then forwarding |= 0x4
|
495
|
+
when :"..." then forwarding |= 0x8
|
496
|
+
else raise ArgumentError, "invalid forwarding value: #{forward}"
|
497
|
+
end
|
498
|
+
end
|
499
|
+
else
|
500
|
+
raise TypeError, "wrong argument type #{scope.class.inspect} (expected Array or Prism::Scope)"
|
501
|
+
end
|
502
|
+
|
488
503
|
template << "L"
|
489
|
-
values <<
|
504
|
+
values << locals.length
|
505
|
+
|
506
|
+
template << "C"
|
507
|
+
values << forwarding
|
490
508
|
|
491
|
-
|
509
|
+
locals.each do |local|
|
492
510
|
name = local.name
|
493
511
|
template << "L"
|
494
512
|
values << name.bytesize
|
@@ -1879,7 +1879,7 @@ module Prism
|
|
1879
1879
|
# Inspect a ParenthesesNode node.
|
1880
1880
|
def visit_parentheses_node(node)
|
1881
1881
|
commands << [inspect_node("ParenthesesNode", node), indent]
|
1882
|
-
flags = [("newline" if node.newline?), ("static_literal" if node.static_literal?), ].compact
|
1882
|
+
flags = [("newline" if node.newline?), ("static_literal" if node.static_literal?), ("multiple_statements" if node.multiple_statements?)].compact
|
1883
1883
|
commands << ["├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n", indent]
|
1884
1884
|
if (body = node.body).nil?
|
1885
1885
|
commands << ["├── body: ∅\n", indent]
|
@@ -2053,6 +2053,7 @@ module Prism
|
|
2053
2053
|
commands << ["├── reference:\n", indent]
|
2054
2054
|
commands << [reference, "#{indent}│ "]
|
2055
2055
|
end
|
2056
|
+
commands << ["├── then_keyword_loc: #{inspect_location(node.then_keyword_loc)}\n", indent]
|
2056
2057
|
if (statements = node.statements).nil?
|
2057
2058
|
commands << ["├── statements: ∅\n", indent]
|
2058
2059
|
else
|
data/lib/prism/node.rb
CHANGED
@@ -10849,7 +10849,7 @@ module Prism
|
|
10849
10849
|
[*opening_loc, *parts, *closing_loc] #: Array[Prism::node | Location]
|
10850
10850
|
end
|
10851
10851
|
|
10852
|
-
# def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode], ?closing_loc: Location?) -> InterpolatedStringNode
|
10852
|
+
# def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode], ?closing_loc: Location?) -> InterpolatedStringNode
|
10853
10853
|
def copy(node_id: self.node_id, location: self.location, flags: self.flags, opening_loc: self.opening_loc, parts: self.parts, closing_loc: self.closing_loc)
|
10854
10854
|
InterpolatedStringNode.new(source, node_id, location, flags, opening_loc, parts, closing_loc)
|
10855
10855
|
end
|
@@ -10857,7 +10857,7 @@ module Prism
|
|
10857
10857
|
# def deconstruct: () -> Array[nil | Node]
|
10858
10858
|
alias deconstruct child_nodes
|
10859
10859
|
|
10860
|
-
# def deconstruct_keys: (Array[Symbol] keys) -> { node_id: Integer, location: Location, opening_loc: Location?, parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode], closing_loc: Location? }
|
10860
|
+
# def deconstruct_keys: (Array[Symbol] keys) -> { node_id: Integer, location: Location, opening_loc: Location?, parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode], closing_loc: Location? }
|
10861
10861
|
def deconstruct_keys(keys)
|
10862
10862
|
{ node_id: node_id, location: location, opening_loc: opening_loc, parts: parts, closing_loc: closing_loc }
|
10863
10863
|
end
|
@@ -10891,7 +10891,7 @@ module Prism
|
|
10891
10891
|
repository.enter(node_id, :opening_loc) unless @opening_loc.nil?
|
10892
10892
|
end
|
10893
10893
|
|
10894
|
-
# attr_reader parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode]
|
10894
|
+
# attr_reader parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode]
|
10895
10895
|
attr_reader :parts
|
10896
10896
|
|
10897
10897
|
# attr_reader closing_loc: Location?
|
@@ -14306,6 +14306,11 @@ module Prism
|
|
14306
14306
|
{ node_id: node_id, location: location, body: body, opening_loc: opening_loc, closing_loc: closing_loc }
|
14307
14307
|
end
|
14308
14308
|
|
14309
|
+
# def multiple_statements?: () -> bool
|
14310
|
+
def multiple_statements?
|
14311
|
+
flags.anybits?(ParenthesesNodeFlags::MULTIPLE_STATEMENTS)
|
14312
|
+
end
|
14313
|
+
|
14309
14314
|
# attr_reader body: Prism::node?
|
14310
14315
|
attr_reader :body
|
14311
14316
|
|
@@ -14364,6 +14369,7 @@ module Prism
|
|
14364
14369
|
# comparing the value of locations. Locations are checked only for presence.
|
14365
14370
|
def ===(other)
|
14366
14371
|
other.is_a?(ParenthesesNode) &&
|
14372
|
+
(flags === other.flags) &&
|
14367
14373
|
(body === other.body) &&
|
14368
14374
|
(opening_loc.nil? == other.opening_loc.nil?) &&
|
14369
14375
|
(closing_loc.nil? == other.closing_loc.nil?)
|
@@ -15709,7 +15715,7 @@ module Prism
|
|
15709
15715
|
# `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field.
|
15710
15716
|
class RescueNode < Node
|
15711
15717
|
# Initialize a new RescueNode node.
|
15712
|
-
def initialize(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, statements, subsequent)
|
15718
|
+
def initialize(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, then_keyword_loc, statements, subsequent)
|
15713
15719
|
@source = source
|
15714
15720
|
@node_id = node_id
|
15715
15721
|
@location = location
|
@@ -15718,6 +15724,7 @@ module Prism
|
|
15718
15724
|
@exceptions = exceptions
|
15719
15725
|
@operator_loc = operator_loc
|
15720
15726
|
@reference = reference
|
15727
|
+
@then_keyword_loc = then_keyword_loc
|
15721
15728
|
@statements = statements
|
15722
15729
|
@subsequent = subsequent
|
15723
15730
|
end
|
@@ -15744,20 +15751,20 @@ module Prism
|
|
15744
15751
|
|
15745
15752
|
# def comment_targets: () -> Array[Node | Location]
|
15746
15753
|
def comment_targets
|
15747
|
-
[keyword_loc, *exceptions, *operator_loc, *reference, *statements, *subsequent] #: Array[Prism::node | Location]
|
15754
|
+
[keyword_loc, *exceptions, *operator_loc, *reference, *then_keyword_loc, *statements, *subsequent] #: Array[Prism::node | Location]
|
15748
15755
|
end
|
15749
15756
|
|
15750
|
-
# def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode | nil, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode
|
15751
|
-
def copy(node_id: self.node_id, location: self.location, flags: self.flags, keyword_loc: self.keyword_loc, exceptions: self.exceptions, operator_loc: self.operator_loc, reference: self.reference, statements: self.statements, subsequent: self.subsequent)
|
15752
|
-
RescueNode.new(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, statements, subsequent)
|
15757
|
+
# def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode | nil, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode
|
15758
|
+
def copy(node_id: self.node_id, location: self.location, flags: self.flags, keyword_loc: self.keyword_loc, exceptions: self.exceptions, operator_loc: self.operator_loc, reference: self.reference, then_keyword_loc: self.then_keyword_loc, statements: self.statements, subsequent: self.subsequent)
|
15759
|
+
RescueNode.new(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, then_keyword_loc, statements, subsequent)
|
15753
15760
|
end
|
15754
15761
|
|
15755
15762
|
# def deconstruct: () -> Array[nil | Node]
|
15756
15763
|
alias deconstruct child_nodes
|
15757
15764
|
|
15758
|
-
# def deconstruct_keys: (Array[Symbol] keys) -> { node_id: Integer, location: Location, keyword_loc: Location, exceptions: Array[Prism::node], operator_loc: Location?, reference: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode | nil, statements: StatementsNode?, subsequent: RescueNode? }
|
15765
|
+
# def deconstruct_keys: (Array[Symbol] keys) -> { node_id: Integer, location: Location, keyword_loc: Location, exceptions: Array[Prism::node], operator_loc: Location?, reference: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode | nil, then_keyword_loc: Location?, statements: StatementsNode?, subsequent: RescueNode? }
|
15759
15766
|
def deconstruct_keys(keys)
|
15760
|
-
{ node_id: node_id, location: location, keyword_loc: keyword_loc, exceptions: exceptions, operator_loc: operator_loc, reference: reference, statements: statements, subsequent: subsequent }
|
15767
|
+
{ node_id: node_id, location: location, keyword_loc: keyword_loc, exceptions: exceptions, operator_loc: operator_loc, reference: reference, then_keyword_loc: then_keyword_loc, statements: statements, subsequent: subsequent }
|
15761
15768
|
end
|
15762
15769
|
|
15763
15770
|
# attr_reader keyword_loc: Location
|
@@ -15798,6 +15805,25 @@ module Prism
|
|
15798
15805
|
# attr_reader reference: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode | nil
|
15799
15806
|
attr_reader :reference
|
15800
15807
|
|
15808
|
+
# attr_reader then_keyword_loc: Location?
|
15809
|
+
def then_keyword_loc
|
15810
|
+
location = @then_keyword_loc
|
15811
|
+
case location
|
15812
|
+
when nil
|
15813
|
+
nil
|
15814
|
+
when Location
|
15815
|
+
location
|
15816
|
+
else
|
15817
|
+
@then_keyword_loc = Location.new(source, location >> 32, location & 0xFFFFFFFF)
|
15818
|
+
end
|
15819
|
+
end
|
15820
|
+
|
15821
|
+
# Save the then_keyword_loc location using the given saved source so that
|
15822
|
+
# it can be retrieved later.
|
15823
|
+
def save_then_keyword_loc(repository)
|
15824
|
+
repository.enter(node_id, :then_keyword_loc) unless @then_keyword_loc.nil?
|
15825
|
+
end
|
15826
|
+
|
15801
15827
|
# attr_reader statements: StatementsNode?
|
15802
15828
|
attr_reader :statements
|
15803
15829
|
|
@@ -15814,6 +15840,11 @@ module Prism
|
|
15814
15840
|
operator_loc&.slice
|
15815
15841
|
end
|
15816
15842
|
|
15843
|
+
# def then_keyword: () -> String?
|
15844
|
+
def then_keyword
|
15845
|
+
then_keyword_loc&.slice
|
15846
|
+
end
|
15847
|
+
|
15817
15848
|
# def inspect -> String
|
15818
15849
|
def inspect
|
15819
15850
|
InspectVisitor.compose(self)
|
@@ -15838,6 +15869,7 @@ module Prism
|
|
15838
15869
|
exceptions.zip(other.exceptions).all? { |left, right| left === right } &&
|
15839
15870
|
(operator_loc.nil? == other.operator_loc.nil?) &&
|
15840
15871
|
(reference === other.reference) &&
|
15872
|
+
(then_keyword_loc.nil? == other.then_keyword_loc.nil?) &&
|
15841
15873
|
(statements === other.statements) &&
|
15842
15874
|
(subsequent === other.subsequent)
|
15843
15875
|
end
|
@@ -18513,6 +18545,12 @@ module Prism
|
|
18513
18545
|
REPEATED_PARAMETER = 1 << 2
|
18514
18546
|
end
|
18515
18547
|
|
18548
|
+
# Flags for parentheses nodes.
|
18549
|
+
module ParenthesesNodeFlags
|
18550
|
+
# parentheses that contain multiple potentially void statements
|
18551
|
+
MULTIPLE_STATEMENTS = 1 << 2
|
18552
|
+
end
|
18553
|
+
|
18516
18554
|
# Flags for range and flip-flop nodes.
|
18517
18555
|
module RangeFlags
|
18518
18556
|
# ... operator
|
data/lib/prism/parse_result.rb
CHANGED
@@ -48,6 +48,16 @@ module Prism
|
|
48
48
|
@offsets = offsets # set after parsing is done
|
49
49
|
end
|
50
50
|
|
51
|
+
# Replace the value of start_line with the given value.
|
52
|
+
def replace_start_line(start_line)
|
53
|
+
@start_line = start_line
|
54
|
+
end
|
55
|
+
|
56
|
+
# Replace the value of offsets with the given value.
|
57
|
+
def replace_offsets(offsets)
|
58
|
+
@offsets.replace(offsets)
|
59
|
+
end
|
60
|
+
|
51
61
|
# Returns the encoding of the source code, which is set by parameters to the
|
52
62
|
# parser or by the encoding magic comment.
|
53
63
|
def encoding
|
@@ -132,6 +142,13 @@ module Prism
|
|
132
142
|
code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding)
|
133
143
|
end
|
134
144
|
|
145
|
+
# Freeze this object and the objects it contains.
|
146
|
+
def deep_freeze
|
147
|
+
source.freeze
|
148
|
+
offsets.freeze
|
149
|
+
freeze
|
150
|
+
end
|
151
|
+
|
135
152
|
private
|
136
153
|
|
137
154
|
# Binary search through the offsets to find the line number for the given
|
@@ -854,5 +871,40 @@ module Prism
|
|
854
871
|
location
|
855
872
|
super
|
856
873
|
end
|
874
|
+
|
875
|
+
# Freeze this object and the objects it contains.
|
876
|
+
def deep_freeze
|
877
|
+
value.freeze
|
878
|
+
location.freeze
|
879
|
+
freeze
|
880
|
+
end
|
881
|
+
end
|
882
|
+
|
883
|
+
# This object is passed to the various Prism.* methods that accept the
|
884
|
+
# `scopes` option as an element of the list. It defines both the local
|
885
|
+
# variables visible at that scope as well as the forwarding parameters
|
886
|
+
# available at that scope.
|
887
|
+
class Scope
|
888
|
+
# The list of local variables that are defined in this scope. This should be
|
889
|
+
# defined as an array of symbols.
|
890
|
+
attr_reader :locals
|
891
|
+
|
892
|
+
# The list of local variables that are forwarded to the next scope. This
|
893
|
+
# should by defined as an array of symbols containing the specific values of
|
894
|
+
# :*, :**, :&, or :"...".
|
895
|
+
attr_reader :forwarding
|
896
|
+
|
897
|
+
# Create a new scope object with the given locals and forwarding.
|
898
|
+
def initialize(locals, forwarding)
|
899
|
+
@locals = locals
|
900
|
+
@forwarding = forwarding
|
901
|
+
end
|
902
|
+
end
|
903
|
+
|
904
|
+
# Create a new scope with the given locals and forwarding options that is
|
905
|
+
# suitable for passing into one of the Prism.* methods that accepts the
|
906
|
+
# `scopes` option.
|
907
|
+
def self.scope(locals: [], forwarding: [])
|
908
|
+
Scope.new(locals, forwarding)
|
857
909
|
end
|
858
910
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Polyfill for String#append_as_bytes, which didn't exist until Ruby 3.4.
|
4
|
+
if !("".respond_to?(:append_as_bytes))
|
5
|
+
String.include(
|
6
|
+
Module.new {
|
7
|
+
def append_as_bytes(*args)
|
8
|
+
args.each do |arg|
|
9
|
+
arg = Integer === arg ? [arg].pack("C") : arg.b
|
10
|
+
self.<<(arg) # steep:ignore
|
11
|
+
end
|
12
|
+
end
|
13
|
+
}
|
14
|
+
)
|
15
|
+
end
|
data/lib/prism/reflection.rb
CHANGED
@@ -334,7 +334,7 @@ module Prism
|
|
334
334
|
when :parameters_node
|
335
335
|
[NodeListField.new(:requireds), NodeListField.new(:optionals), OptionalNodeField.new(:rest), NodeListField.new(:posts), NodeListField.new(:keywords), OptionalNodeField.new(:keyword_rest), OptionalNodeField.new(:block)]
|
336
336
|
when :parentheses_node
|
337
|
-
[OptionalNodeField.new(:body), LocationField.new(:opening_loc), LocationField.new(:closing_loc)]
|
337
|
+
[FlagsField.new(:flags, [:multiple_statements?]), OptionalNodeField.new(:body), LocationField.new(:opening_loc), LocationField.new(:closing_loc)]
|
338
338
|
when :pinned_expression_node
|
339
339
|
[NodeField.new(:expression), LocationField.new(:operator_loc), LocationField.new(:lparen_loc), LocationField.new(:rparen_loc)]
|
340
340
|
when :pinned_variable_node
|
@@ -360,7 +360,7 @@ module Prism
|
|
360
360
|
when :rescue_modifier_node
|
361
361
|
[NodeField.new(:expression), LocationField.new(:keyword_loc), NodeField.new(:rescue_expression)]
|
362
362
|
when :rescue_node
|
363
|
-
[LocationField.new(:keyword_loc), NodeListField.new(:exceptions), OptionalLocationField.new(:operator_loc), OptionalNodeField.new(:reference), OptionalNodeField.new(:statements), OptionalNodeField.new(:subsequent)]
|
363
|
+
[LocationField.new(:keyword_loc), NodeListField.new(:exceptions), OptionalLocationField.new(:operator_loc), OptionalNodeField.new(:reference), OptionalLocationField.new(:then_keyword_loc), OptionalNodeField.new(:statements), OptionalNodeField.new(:subsequent)]
|
364
364
|
when :rest_parameter_node
|
365
365
|
[FlagsField.new(:flags, [:repeated_parameter?]), OptionalConstantField.new(:name), OptionalLocationField.new(:name_loc), LocationField.new(:operator_loc)]
|
366
366
|
when :retry_node
|