yarp 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -8
  3. data/CONTRIBUTING.md +2 -2
  4. data/Makefile +5 -5
  5. data/README.md +11 -12
  6. data/config.yml +6 -2
  7. data/docs/build_system.md +21 -21
  8. data/docs/building.md +4 -4
  9. data/docs/configuration.md +25 -21
  10. data/docs/design.md +2 -2
  11. data/docs/encoding.md +17 -17
  12. data/docs/fuzzing.md +4 -4
  13. data/docs/heredocs.md +3 -3
  14. data/docs/mapping.md +94 -94
  15. data/docs/ripper.md +4 -4
  16. data/docs/ruby_api.md +11 -11
  17. data/docs/serialization.md +17 -16
  18. data/docs/testing.md +6 -6
  19. data/ext/prism/api_node.c +4725 -0
  20. data/ext/{yarp → prism}/api_pack.c +82 -82
  21. data/ext/{yarp → prism}/extconf.rb +13 -13
  22. data/ext/{yarp → prism}/extension.c +175 -168
  23. data/ext/prism/extension.h +18 -0
  24. data/include/prism/ast.h +1932 -0
  25. data/include/prism/defines.h +45 -0
  26. data/include/prism/diagnostic.h +231 -0
  27. data/include/{yarp/enc/yp_encoding.h → prism/enc/pm_encoding.h} +40 -40
  28. data/include/prism/node.h +41 -0
  29. data/include/prism/pack.h +141 -0
  30. data/include/{yarp → prism}/parser.h +143 -142
  31. data/include/prism/regexp.h +19 -0
  32. data/include/prism/unescape.h +48 -0
  33. data/include/prism/util/pm_buffer.h +51 -0
  34. data/include/{yarp/util/yp_char.h → prism/util/pm_char.h} +20 -20
  35. data/include/{yarp/util/yp_constant_pool.h → prism/util/pm_constant_pool.h} +26 -22
  36. data/include/{yarp/util/yp_list.h → prism/util/pm_list.h} +21 -21
  37. data/include/prism/util/pm_memchr.h +14 -0
  38. data/include/{yarp/util/yp_newline_list.h → prism/util/pm_newline_list.h} +11 -11
  39. data/include/prism/util/pm_state_stack.h +24 -0
  40. data/include/{yarp/util/yp_string.h → prism/util/pm_string.h} +20 -20
  41. data/include/prism/util/pm_string_list.h +25 -0
  42. data/include/{yarp/util/yp_strpbrk.h → prism/util/pm_strpbrk.h} +7 -7
  43. data/include/prism/version.h +4 -0
  44. data/include/prism.h +82 -0
  45. data/lib/prism/compiler.rb +465 -0
  46. data/lib/prism/debug.rb +157 -0
  47. data/lib/{yarp/desugar_visitor.rb → prism/desugar_compiler.rb} +4 -2
  48. data/lib/prism/dispatcher.rb +2051 -0
  49. data/lib/prism/dsl.rb +750 -0
  50. data/lib/{yarp → prism}/ffi.rb +66 -67
  51. data/lib/{yarp → prism}/lex_compat.rb +40 -43
  52. data/lib/{yarp/mutation_visitor.rb → prism/mutation_compiler.rb} +3 -3
  53. data/lib/{yarp → prism}/node.rb +2012 -2593
  54. data/lib/prism/node_ext.rb +55 -0
  55. data/lib/prism/node_inspector.rb +68 -0
  56. data/lib/{yarp → prism}/pack.rb +1 -1
  57. data/lib/{yarp → prism}/parse_result/comments.rb +1 -1
  58. data/lib/{yarp → prism}/parse_result/newlines.rb +1 -1
  59. data/lib/prism/parse_result.rb +266 -0
  60. data/lib/{yarp → prism}/pattern.rb +14 -14
  61. data/lib/{yarp → prism}/ripper_compat.rb +5 -5
  62. data/lib/{yarp → prism}/serialize.rb +12 -7
  63. data/lib/prism/visitor.rb +470 -0
  64. data/lib/prism.rb +64 -0
  65. data/lib/yarp.rb +2 -614
  66. data/src/diagnostic.c +213 -208
  67. data/src/enc/pm_big5.c +52 -0
  68. data/src/enc/pm_euc_jp.c +58 -0
  69. data/src/enc/{yp_gbk.c → pm_gbk.c} +16 -16
  70. data/src/enc/pm_shift_jis.c +56 -0
  71. data/src/enc/{yp_tables.c → pm_tables.c} +69 -69
  72. data/src/enc/{yp_unicode.c → pm_unicode.c} +40 -40
  73. data/src/enc/pm_windows_31j.c +56 -0
  74. data/src/node.c +1293 -1233
  75. data/src/pack.c +247 -247
  76. data/src/prettyprint.c +1479 -1479
  77. data/src/{yarp.c → prism.c} +5205 -5083
  78. data/src/regexp.c +132 -132
  79. data/src/serialize.c +1121 -1121
  80. data/src/token_type.c +169 -167
  81. data/src/unescape.c +106 -87
  82. data/src/util/pm_buffer.c +103 -0
  83. data/src/util/{yp_char.c → pm_char.c} +72 -72
  84. data/src/util/{yp_constant_pool.c → pm_constant_pool.c} +85 -64
  85. data/src/util/{yp_list.c → pm_list.c} +10 -10
  86. data/src/util/{yp_memchr.c → pm_memchr.c} +6 -4
  87. data/src/util/{yp_newline_list.c → pm_newline_list.c} +21 -21
  88. data/src/util/{yp_state_stack.c → pm_state_stack.c} +4 -4
  89. data/src/util/{yp_string.c → pm_string.c} +38 -38
  90. data/src/util/pm_string_list.c +29 -0
  91. data/src/util/{yp_strncasecmp.c → pm_strncasecmp.c} +1 -1
  92. data/src/util/{yp_strpbrk.c → pm_strpbrk.c} +8 -8
  93. data/yarp.gemspec +68 -59
  94. metadata +70 -61
  95. data/ext/yarp/api_node.c +0 -4728
  96. data/ext/yarp/extension.h +0 -18
  97. data/include/yarp/ast.h +0 -1929
  98. data/include/yarp/defines.h +0 -45
  99. data/include/yarp/diagnostic.h +0 -226
  100. data/include/yarp/node.h +0 -42
  101. data/include/yarp/pack.h +0 -141
  102. data/include/yarp/regexp.h +0 -19
  103. data/include/yarp/unescape.h +0 -44
  104. data/include/yarp/util/yp_buffer.h +0 -51
  105. data/include/yarp/util/yp_memchr.h +0 -14
  106. data/include/yarp/util/yp_state_stack.h +0 -24
  107. data/include/yarp/util/yp_string_list.h +0 -25
  108. data/include/yarp/version.h +0 -4
  109. data/include/yarp.h +0 -82
  110. data/src/enc/yp_big5.c +0 -52
  111. data/src/enc/yp_euc_jp.c +0 -58
  112. data/src/enc/yp_shift_jis.c +0 -56
  113. data/src/enc/yp_windows_31j.c +0 -56
  114. data/src/util/yp_buffer.c +0 -101
  115. data/src/util/yp_string_list.c +0 -29
data/lib/yarp.rb CHANGED
@@ -1,616 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module YARP
4
- # This represents a source of Ruby code that has been parsed. It is used in
5
- # conjunction with locations to allow them to resolve line numbers and source
6
- # ranges.
7
- class Source
8
- attr_reader :source, :offsets
9
-
10
- def initialize(source, offsets = compute_offsets(source))
11
- @source = source
12
- @offsets = offsets
13
- end
14
-
15
- def slice(offset, length)
16
- source.byteslice(offset, length)
17
- end
18
-
19
- def line(value)
20
- offsets.bsearch_index { |offset| offset > value } || offsets.length
21
- end
22
-
23
- def line_offset(value)
24
- offsets[line(value) - 1]
25
- end
26
-
27
- def column(value)
28
- value - offsets[line(value) - 1]
29
- end
30
-
31
- private
32
-
33
- def compute_offsets(code)
34
- offsets = [0]
35
- code.b.scan("\n") { offsets << $~.end(0) }
36
- offsets
37
- end
38
- end
39
-
40
- # This represents a location in the source.
41
- class Location
42
- # A Source object that is used to determine more information from the given
43
- # offset and length.
44
- protected attr_reader :source
45
-
46
- # The byte offset from the beginning of the source where this location
47
- # starts.
48
- attr_reader :start_offset
49
-
50
- # The length of this location in bytes.
51
- attr_reader :length
52
-
53
- # The list of comments attached to this location
54
- attr_reader :comments
55
-
56
- def initialize(source, start_offset, length)
57
- @source = source
58
- @start_offset = start_offset
59
- @length = length
60
- @comments = []
61
- end
62
-
63
- # Create a new location object with the given options.
64
- def copy(**options)
65
- Location.new(
66
- options.fetch(:source) { source },
67
- options.fetch(:start_offset) { start_offset },
68
- options.fetch(:length) { length }
69
- )
70
- end
71
-
72
- # Returns a string representation of this location.
73
- def inspect
74
- "#<YARP::Location @start_offset=#{@start_offset} @length=#{@length}>"
75
- end
76
-
77
- # The source code that this location represents.
78
- def slice
79
- source.slice(start_offset, length)
80
- end
81
-
82
- # The byte offset from the beginning of the source where this location ends.
83
- def end_offset
84
- start_offset + length
85
- end
86
-
87
- # The line number where this location starts.
88
- def start_line
89
- source.line(start_offset)
90
- end
91
-
92
- # The content of the line where this location starts before this location.
93
- def start_line_slice
94
- offset = source.line_offset(start_offset)
95
- source.slice(offset, start_offset - offset)
96
- end
97
-
98
- # The line number where this location ends.
99
- def end_line
100
- source.line(end_offset - 1)
101
- end
102
-
103
- # The column number in bytes where this location starts from the start of
104
- # the line.
105
- def start_column
106
- source.column(start_offset)
107
- end
108
-
109
- # The column number in bytes where this location ends from the start of the
110
- # line.
111
- def end_column
112
- source.column(end_offset)
113
- end
114
-
115
- def deconstruct_keys(keys)
116
- { start_offset: start_offset, end_offset: end_offset }
117
- end
118
-
119
- def pretty_print(q)
120
- q.text("(#{start_offset}...#{end_offset})")
121
- end
122
-
123
- def ==(other)
124
- other.is_a?(Location) &&
125
- other.start_offset == start_offset &&
126
- other.end_offset == end_offset
127
- end
128
-
129
- # Returns a new location that stretches from this location to the given
130
- # other location. Raises an error if this location is not before the other
131
- # location or if they don't share the same source.
132
- def join(other)
133
- raise "Incompatible sources" if source != other.source
134
- raise "Incompatible locations" if start_offset > other.start_offset
135
-
136
- Location.new(source, start_offset, other.end_offset - start_offset)
137
- end
138
-
139
- def self.null
140
- new(0, 0)
141
- end
142
- end
143
-
144
- # This represents a comment that was encountered during parsing.
145
- class Comment
146
- TYPES = [:inline, :embdoc, :__END__]
147
-
148
- attr_reader :type, :location
149
-
150
- def initialize(type, location)
151
- @type = type
152
- @location = location
153
- end
154
-
155
- def deconstruct_keys(keys)
156
- { type: type, location: location }
157
- end
158
-
159
- # Returns true if the comment happens on the same line as other code and false if the comment is by itself
160
- def trailing?
161
- type == :inline && !location.start_line_slice.strip.empty?
162
- end
163
-
164
- def inspect
165
- "#<YARP::Comment @type=#{@type.inspect} @location=#{@location.inspect}>"
166
- end
167
- end
168
-
169
- # This represents an error that was encountered during parsing.
170
- class ParseError
171
- attr_reader :message, :location
172
-
173
- def initialize(message, location)
174
- @message = message
175
- @location = location
176
- end
177
-
178
- def deconstruct_keys(keys)
179
- { message: message, location: location }
180
- end
181
-
182
- def inspect
183
- "#<YARP::ParseError @message=#{@message.inspect} @location=#{@location.inspect}>"
184
- end
185
- end
186
-
187
- # This represents a warning that was encountered during parsing.
188
- class ParseWarning
189
- attr_reader :message, :location
190
-
191
- def initialize(message, location)
192
- @message = message
193
- @location = location
194
- end
195
-
196
- def deconstruct_keys(keys)
197
- { message: message, location: location }
198
- end
199
-
200
- def inspect
201
- "#<YARP::ParseWarning @message=#{@message.inspect} @location=#{@location.inspect}>"
202
- end
203
- end
204
-
205
- # A class that knows how to walk down the tree. None of the individual visit
206
- # methods are implemented on this visitor, so it forces the consumer to
207
- # implement each one that they need. For a default implementation that
208
- # continues walking the tree, see the Visitor class.
209
- class BasicVisitor
210
- def visit(node)
211
- node&.accept(self)
212
- end
213
-
214
- def visit_all(nodes)
215
- nodes.map { |node| visit(node) }
216
- end
217
-
218
- def visit_child_nodes(node)
219
- visit_all(node.child_nodes)
220
- end
221
- end
222
-
223
- class Visitor < BasicVisitor
224
- end
225
-
226
- # This represents the result of a call to ::parse or ::parse_file. It contains
227
- # the AST, any comments that were encounters, and any errors that were
228
- # encountered.
229
- class ParseResult
230
- attr_reader :value, :comments, :errors, :warnings, :source
231
-
232
- def initialize(value, comments, errors, warnings, source)
233
- @value = value
234
- @comments = comments
235
- @errors = errors
236
- @warnings = warnings
237
- @source = source
238
- end
239
-
240
- def deconstruct_keys(keys)
241
- { value: value, comments: comments, errors: errors, warnings: warnings }
242
- end
243
-
244
- def success?
245
- errors.empty?
246
- end
247
-
248
- def failure?
249
- !success?
250
- end
251
- end
252
-
253
- # This represents a token from the Ruby source.
254
- class Token
255
- attr_reader :type, :value, :location
256
-
257
- def initialize(type, value, location)
258
- @type = type
259
- @value = value
260
- @location = location
261
- end
262
-
263
- def deconstruct_keys(keys)
264
- { type: type, value: value, location: location }
265
- end
266
-
267
- def pretty_print(q)
268
- q.group do
269
- q.text(type.to_s)
270
- self.location.pretty_print(q)
271
- q.text("(")
272
- q.nest(2) do
273
- q.breakable("")
274
- q.pp(value)
275
- end
276
- q.breakable("")
277
- q.text(")")
278
- end
279
- end
280
-
281
- def ==(other)
282
- other.is_a?(Token) &&
283
- other.type == type &&
284
- other.value == value
285
- end
286
- end
287
-
288
- # This represents a node in the tree.
289
- class Node
290
- attr_reader :location
291
-
292
- def newline?
293
- @newline ? true : false
294
- end
295
-
296
- def set_newline_flag(newline_marked)
297
- line = location.start_line
298
- unless newline_marked[line]
299
- newline_marked[line] = true
300
- @newline = true
301
- end
302
- end
303
-
304
- # Slice the location of the node from the source.
305
- def slice
306
- location.slice
307
- end
308
-
309
- def pretty_print(q)
310
- q.text(inspect.chomp)
311
- end
312
- end
313
-
314
- # This object is responsible for generating the output for the inspect method
315
- # implementations of child nodes.
316
- class NodeInspector
317
- attr_reader :prefix, :output
318
-
319
- def initialize(prefix = "")
320
- @prefix = prefix
321
- @output = +""
322
- end
323
-
324
- # Appends a line to the output with the current prefix.
325
- def <<(line)
326
- output << "#{prefix}#{line}"
327
- end
328
-
329
- # This generates a string that is used as the header of the inspect output
330
- # for any given node.
331
- def header(node)
332
- output = +"@ #{node.class.name.split("::").last} ("
333
- output << "location: (#{node.location.start_offset}...#{node.location.end_offset})"
334
- output << ", newline: true" if node.newline?
335
- output << ")\n"
336
- output
337
- end
338
-
339
- # Generates a string that represents a list of nodes. It handles properly
340
- # using the box drawing characters to make the output look nice.
341
- def list(prefix, nodes)
342
- output = +"(length: #{nodes.length})\n"
343
- last_index = nodes.length - 1
344
-
345
- nodes.each_with_index do |node, index|
346
- pointer, preadd = (index == last_index) ? ["└── ", " "] : ["├── ", "│ "]
347
- node_prefix = "#{prefix}#{preadd}"
348
- output << node.inspect(NodeInspector.new(node_prefix)).sub(node_prefix, "#{prefix}#{pointer}")
349
- end
350
-
351
- output
352
- end
353
-
354
- # Generates a string that represents a location field on a node.
355
- def location(value)
356
- if value
357
- "(#{value.start_offset}...#{value.end_offset}) = #{value.slice.inspect}"
358
- else
359
- "∅"
360
- end
361
- end
362
-
363
- # Generates a string that represents a child node.
364
- def child_node(node, append)
365
- node.inspect(child_inspector(append)).delete_prefix(prefix)
366
- end
367
-
368
- # Returns a new inspector that can be used to inspect a child node.
369
- def child_inspector(append)
370
- NodeInspector.new("#{prefix}#{append}")
371
- end
372
-
373
- # Returns the output as a string.
374
- def to_str
375
- output
376
- end
377
- end
378
-
379
- # Load the serialized AST using the source as a reference into a tree.
380
- def self.load(source, serialized)
381
- Serialize.load(source, serialized)
382
- end
383
-
384
- # This module is used for testing and debugging and is not meant to be used by
385
- # consumers of this library.
386
- module Debug
387
- class ISeq
388
- attr_reader :parts
389
-
390
- def initialize(parts)
391
- @parts = parts
392
- end
393
-
394
- def type
395
- parts[0]
396
- end
397
-
398
- def local_table
399
- parts[10]
400
- end
401
-
402
- def instructions
403
- parts[13]
404
- end
405
-
406
- def each_child
407
- instructions.each do |instruction|
408
- # Only look at arrays. Other instructions are line numbers or
409
- # tracepoint events.
410
- next unless instruction.is_a?(Array)
411
-
412
- instruction.each do |opnd|
413
- # Only look at arrays. Other operands are literals.
414
- next unless opnd.is_a?(Array)
415
-
416
- # Only look at instruction sequences. Other operands are literals.
417
- next unless opnd[0] == "YARVInstructionSequence/SimpleDataFormat"
418
-
419
- yield ISeq.new(opnd)
420
- end
421
- end
422
- end
423
- end
424
-
425
- # For the given source, compiles with CRuby and returns a list of all of the
426
- # sets of local variables that were encountered.
427
- def self.cruby_locals(source)
428
- verbose = $VERBOSE
429
- $VERBOSE = nil
430
-
431
- begin
432
- locals = []
433
- stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)]
434
-
435
- while (iseq = stack.pop)
436
- if iseq.type != :once
437
- names = iseq.local_table
438
-
439
- # CRuby will push on a special local variable when there are keyword
440
- # arguments. We get rid of that here.
441
- names = names.grep_v(Integer)
442
-
443
- # For some reason, CRuby occasionally pushes this special local
444
- # variable when there are splat arguments. We get rid of that here.
445
- names = names.grep_v(:"#arg_rest")
446
-
447
- # Now push them onto the list of locals.
448
- locals << names
449
- end
450
-
451
- iseq.each_child { |child| stack << child }
452
- end
453
-
454
- locals
455
- ensure
456
- $VERBOSE = verbose
457
- end
458
- end
459
-
460
- # For the given source, parses with YARP and returns a list of all of the
461
- # sets of local variables that were encountered.
462
- def self.yarp_locals(source)
463
- locals = []
464
- stack = [YARP.parse(source).value]
465
-
466
- while (node = stack.pop)
467
- case node
468
- when BlockNode, DefNode, LambdaNode
469
- names = node.locals
470
-
471
- params = node.parameters
472
- params = params&.parameters unless node.is_a?(DefNode)
473
-
474
- # YARP places parameters in the same order that they appear in the
475
- # source. CRuby places them in the order that they need to appear
476
- # according to their own internal calling convention. We mimic that
477
- # order here so that we can compare properly.
478
- if params
479
- sorted = [
480
- *params.requireds.grep(RequiredParameterNode).map(&:name),
481
- *params.optionals.map(&:name),
482
- *((params.rest.name || :*) if params.rest && params.rest.operator != ","),
483
- *params.posts.grep(RequiredParameterNode).map(&:name),
484
- *params.keywords.reject(&:value).map(&:name),
485
- *params.keywords.select(&:value).map(&:name)
486
- ]
487
-
488
- # TODO: When we get a ... parameter, we should be pushing * and &
489
- # onto the local list. We don't do that yet, so we need to add them
490
- # in here.
491
- if params.keyword_rest.is_a?(ForwardingParameterNode)
492
- sorted.push(:*, :&, :"...")
493
- end
494
-
495
- # Recurse down the parameter tree to find any destructured
496
- # parameters and add them after the other parameters.
497
- param_stack = params.requireds.concat(params.posts).grep(RequiredDestructuredParameterNode).reverse
498
- while (param = param_stack.pop)
499
- case param
500
- when RequiredDestructuredParameterNode
501
- param_stack.concat(param.parameters.reverse)
502
- when RequiredParameterNode
503
- sorted << param.name
504
- when SplatNode
505
- sorted << param.expression.name if param.expression
506
- end
507
- end
508
-
509
- names = sorted.concat(names - sorted)
510
- end
511
-
512
- locals << names
513
- when ClassNode, ModuleNode, ProgramNode, SingletonClassNode
514
- locals << node.locals
515
- when ForNode
516
- locals << []
517
- when PostExecutionNode
518
- locals.push([], [])
519
- when InterpolatedRegularExpressionNode
520
- locals << [] if node.once?
521
- end
522
-
523
- stack.concat(node.child_nodes.compact)
524
- end
525
-
526
- locals
527
- end
528
-
529
- def self.newlines(source)
530
- YARP.parse(source).source.offsets
531
- end
532
-
533
- def self.parse_serialize_file(filepath)
534
- parse_serialize_file_metadata(filepath, [filepath.bytesize, filepath.b, 0].pack("LA*L"))
535
- end
536
- end
537
-
538
- # Marking this as private so that consumers don't see it. It makes it a little
539
- # annoying for testing since you have to const_get it to access the methods,
540
- # but at least this way it's clear it's not meant for consumers.
541
- private_constant :Debug
542
- end
543
-
544
- require_relative "yarp/lex_compat"
545
- require_relative "yarp/mutation_visitor"
546
- require_relative "yarp/desugar_visitor"
547
- require_relative "yarp/node"
548
- require_relative "yarp/ripper_compat"
549
- require_relative "yarp/serialize"
550
- require_relative "yarp/pack"
551
- require_relative "yarp/pattern"
552
-
553
- require_relative "yarp/parse_result/comments"
554
- require_relative "yarp/parse_result/newlines"
555
-
556
- if RUBY_ENGINE == "ruby" and !ENV["YARP_FFI_BACKEND"]
557
- require "yarp/yarp"
558
- else
559
- require_relative "yarp/ffi"
560
- end
561
-
562
- # Reopening the YARP module after yarp/node is required so that constant
563
- # reflection APIs will find the constants defined in the node file before these.
564
- # This block is meant to contain extra APIs we define on YARP nodes that aren't
565
- # templated and are meant as convenience methods.
566
- module YARP
567
- class FloatNode < Node
568
- # Returns the value of the node as a Ruby Float.
569
- def value
570
- Float(slice)
571
- end
572
- end
573
-
574
- class ImaginaryNode < Node
575
- # Returns the value of the node as a Ruby Complex.
576
- def value
577
- Complex(0, numeric.value)
578
- end
579
- end
580
-
581
- class IntegerNode < Node
582
- # Returns the value of the node as a Ruby Integer.
583
- def value
584
- Integer(slice)
585
- end
586
- end
587
-
588
- class InterpolatedRegularExpressionNode < Node
589
- # Returns a numeric value that represents the flags that were used to create
590
- # the regular expression.
591
- def options
592
- o = flags & 0b111
593
- o |= Regexp::FIXEDENCODING if flags.anybits?(RegularExpressionFlags::EUC_JP | RegularExpressionFlags::WINDOWS_31J | RegularExpressionFlags::UTF_8)
594
- o |= Regexp::NOENCODING if flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
595
- o
596
- end
597
- end
598
-
599
- class RationalNode < Node
600
- # Returns the value of the node as a Ruby Rational.
601
- def value
602
- Rational(slice.chomp("r"))
603
- end
604
- end
605
-
606
- class RegularExpressionNode < Node
607
- # Returns a numeric value that represents the flags that were used to create
608
- # the regular expression.
609
- def options
610
- o = flags & 0b111
611
- o |= Regexp::FIXEDENCODING if flags.anybits?(RegularExpressionFlags::EUC_JP | RegularExpressionFlags::WINDOWS_31J | RegularExpressionFlags::UTF_8)
612
- o |= Regexp::NOENCODING if flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
613
- o
614
- end
615
- end
616
- end
3
+ require "prism"
4
+ YARP = Prism