prism 2.0.0.rc1-x86_64-linux-gnu

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. checksums.yaml +7 -0
  2. data/BSDmakefile +58 -0
  3. data/CHANGELOG.md +870 -0
  4. data/CODE_OF_CONDUCT.md +76 -0
  5. data/CONTRIBUTING.md +58 -0
  6. data/LICENSE.md +7 -0
  7. data/Makefile +145 -0
  8. data/README.md +81 -0
  9. data/config.yml +4752 -0
  10. data/docs/build_system.md +119 -0
  11. data/docs/configuration.md +69 -0
  12. data/docs/cruby_compilation.md +27 -0
  13. data/docs/design.md +53 -0
  14. data/docs/encoding.md +121 -0
  15. data/docs/fuzzing.md +81 -0
  16. data/docs/heredocs.md +36 -0
  17. data/docs/javascript.md +133 -0
  18. data/docs/local_variable_depth.md +229 -0
  19. data/docs/mapping.md +117 -0
  20. data/docs/parser_translation.md +24 -0
  21. data/docs/parsing_rules.md +22 -0
  22. data/docs/releasing.md +147 -0
  23. data/docs/relocation.md +32 -0
  24. data/docs/ripper_translation.md +63 -0
  25. data/docs/ruby_api.md +45 -0
  26. data/docs/ruby_parser_translation.md +19 -0
  27. data/docs/serialization.md +230 -0
  28. data/docs/testing.md +72 -0
  29. data/ext/prism/api_node.c +7005 -0
  30. data/ext/prism/extconf.rb +126 -0
  31. data/ext/prism/extension.c +1783 -0
  32. data/ext/prism/extension.h +19 -0
  33. data/include/prism/arena.h +37 -0
  34. data/include/prism/ast.h +10371 -0
  35. data/include/prism/buffer.h +52 -0
  36. data/include/prism/comments.h +55 -0
  37. data/include/prism/compiler/accel.h +24 -0
  38. data/include/prism/compiler/align.h +36 -0
  39. data/include/prism/compiler/assume.h +25 -0
  40. data/include/prism/compiler/exported.h +24 -0
  41. data/include/prism/compiler/fallthrough.h +22 -0
  42. data/include/prism/compiler/filesystem.h +32 -0
  43. data/include/prism/compiler/flex_array.h +19 -0
  44. data/include/prism/compiler/force_inline.h +21 -0
  45. data/include/prism/compiler/format.h +25 -0
  46. data/include/prism/compiler/inline.h +17 -0
  47. data/include/prism/compiler/nodiscard.h +22 -0
  48. data/include/prism/compiler/nonnull.h +18 -0
  49. data/include/prism/compiler/unused.h +18 -0
  50. data/include/prism/constant_pool.h +81 -0
  51. data/include/prism/diagnostic.h +93 -0
  52. data/include/prism/errors_format.h +53 -0
  53. data/include/prism/excludes.h +29 -0
  54. data/include/prism/integer.h +41 -0
  55. data/include/prism/internal/allocator.h +68 -0
  56. data/include/prism/internal/allocator_debug.h +88 -0
  57. data/include/prism/internal/arena.h +108 -0
  58. data/include/prism/internal/bit.h +42 -0
  59. data/include/prism/internal/buffer.h +91 -0
  60. data/include/prism/internal/char.h +145 -0
  61. data/include/prism/internal/comments.h +53 -0
  62. data/include/prism/internal/constant_pool.h +152 -0
  63. data/include/prism/internal/diagnostic.h +389 -0
  64. data/include/prism/internal/encoding.h +242 -0
  65. data/include/prism/internal/integer.h +68 -0
  66. data/include/prism/internal/isinf.h +16 -0
  67. data/include/prism/internal/line_offset_list.h +34 -0
  68. data/include/prism/internal/list.h +62 -0
  69. data/include/prism/internal/magic_comments.h +23 -0
  70. data/include/prism/internal/memchr.h +15 -0
  71. data/include/prism/internal/node.h +38 -0
  72. data/include/prism/internal/options.h +232 -0
  73. data/include/prism/internal/parser.h +984 -0
  74. data/include/prism/internal/regexp.h +26 -0
  75. data/include/prism/internal/serialize.h +39 -0
  76. data/include/prism/internal/source.h +72 -0
  77. data/include/prism/internal/static_literals.h +100 -0
  78. data/include/prism/internal/stringy.h +35 -0
  79. data/include/prism/internal/strncasecmp.h +18 -0
  80. data/include/prism/internal/strpbrk.h +33 -0
  81. data/include/prism/internal/tokens.h +11 -0
  82. data/include/prism/json.h +32 -0
  83. data/include/prism/line_offset_list.h +61 -0
  84. data/include/prism/magic_comments.h +35 -0
  85. data/include/prism/node.h +94 -0
  86. data/include/prism/options.h +354 -0
  87. data/include/prism/parser.h +404 -0
  88. data/include/prism/prettyprint.h +31 -0
  89. data/include/prism/serialize.h +115 -0
  90. data/include/prism/source.h +155 -0
  91. data/include/prism/stream.h +28 -0
  92. data/include/prism/string_query.h +63 -0
  93. data/include/prism/stringy.h +72 -0
  94. data/include/prism/version.h +38 -0
  95. data/include/prism.h +131 -0
  96. data/lib/prism/3.3/prism.so +0 -0
  97. data/lib/prism/3.4/prism.so +0 -0
  98. data/lib/prism/4.0/prism.so +0 -0
  99. data/lib/prism/compiler.rb +815 -0
  100. data/lib/prism/desugar_compiler.rb +463 -0
  101. data/lib/prism/dispatcher.rb +2383 -0
  102. data/lib/prism/dot_visitor.rb +4848 -0
  103. data/lib/prism/dsl.rb +1369 -0
  104. data/lib/prism/ffi.rb +740 -0
  105. data/lib/prism/inspect_visitor.rb +2425 -0
  106. data/lib/prism/lex_compat.rb +953 -0
  107. data/lib/prism/mutation_compiler.rb +780 -0
  108. data/lib/prism/node.rb +33204 -0
  109. data/lib/prism/node_ext.rb +504 -0
  110. data/lib/prism/node_find.rb +215 -0
  111. data/lib/prism/parse_result/errors.rb +72 -0
  112. data/lib/prism/parse_result/newlines.rb +423 -0
  113. data/lib/prism/parse_result.rb +1221 -0
  114. data/lib/prism/pattern.rb +314 -0
  115. data/lib/prism/polyfill/append_as_bytes.rb +15 -0
  116. data/lib/prism/polyfill/byteindex.rb +13 -0
  117. data/lib/prism/polyfill/scan_byte.rb +14 -0
  118. data/lib/prism/polyfill/unpack1.rb +14 -0
  119. data/lib/prism/polyfill/warn.rb +36 -0
  120. data/lib/prism/reflection.rb +427 -0
  121. data/lib/prism/relocation.rb +567 -0
  122. data/lib/prism/serialize.rb +5308 -0
  123. data/lib/prism/string_query.rb +46 -0
  124. data/lib/prism/translation/parser/builder.rb +70 -0
  125. data/lib/prism/translation/parser/compiler.rb +2226 -0
  126. data/lib/prism/translation/parser/lexer.rb +769 -0
  127. data/lib/prism/translation/parser.rb +376 -0
  128. data/lib/prism/translation/parser_current.rb +26 -0
  129. data/lib/prism/translation/parser_versions.rb +36 -0
  130. data/lib/prism/translation/ripper/filter.rb +53 -0
  131. data/lib/prism/translation/ripper/lexer.rb +133 -0
  132. data/lib/prism/translation/ripper/sexp.rb +118 -0
  133. data/lib/prism/translation/ripper/shim.rb +7 -0
  134. data/lib/prism/translation/ripper.rb +4278 -0
  135. data/lib/prism/translation/ruby_parser.rb +1721 -0
  136. data/lib/prism/translation.rb +20 -0
  137. data/lib/prism/visitor.rb +1440 -0
  138. data/lib/prism.rb +168 -0
  139. data/prism.gemspec +234 -0
  140. data/rbi/generated/prism/compiler.rbi +489 -0
  141. data/rbi/generated/prism/desugar_compiler.rbi +306 -0
  142. data/rbi/generated/prism/dispatcher.rbi +1138 -0
  143. data/rbi/generated/prism/dot_visitor.rbi +618 -0
  144. data/rbi/generated/prism/dsl.rbi +751 -0
  145. data/rbi/generated/prism/inspect_visitor.rbi +503 -0
  146. data/rbi/generated/prism/lex_compat.rbi +162 -0
  147. data/rbi/generated/prism/mutation_compiler.rbi +464 -0
  148. data/rbi/generated/prism/node.rbi +13681 -0
  149. data/rbi/generated/prism/node_ext.rbi +259 -0
  150. data/rbi/generated/prism/node_find.rbi +79 -0
  151. data/rbi/generated/prism/parse_result/errors.rbi +21 -0
  152. data/rbi/generated/prism/parse_result/newlines.rbi +208 -0
  153. data/rbi/generated/prism/parse_result.rbi +764 -0
  154. data/rbi/generated/prism/pattern.rbi +134 -0
  155. data/rbi/generated/prism/reflection.rbi +89 -0
  156. data/rbi/generated/prism/relocation.rbi +329 -0
  157. data/rbi/generated/prism/serialize.rbi +181 -0
  158. data/rbi/generated/prism/string_query.rbi +36 -0
  159. data/rbi/generated/prism/translation.rbi +7 -0
  160. data/rbi/generated/prism/visitor.rbi +650 -0
  161. data/rbi/generated/prism.rbi +86 -0
  162. data/rbi/prism/translation/parser.rbi +11 -0
  163. data/rbi/prism/translation/parser_versions.rbi +28 -0
  164. data/rbi/prism/translation/ripper.rbi +15 -0
  165. data/rbi/rubyvm/node_find.rbi +14 -0
  166. data/sig/generated/prism/compiler.rbs +492 -0
  167. data/sig/generated/prism/desugar_compiler.rbs +305 -0
  168. data/sig/generated/prism/dispatcher.rbs +1292 -0
  169. data/sig/generated/prism/dot_visitor.rbs +635 -0
  170. data/sig/generated/prism/dsl.rbs +928 -0
  171. data/sig/generated/prism/inspect_visitor.rbs +509 -0
  172. data/sig/generated/prism/lex_compat.rbs +166 -0
  173. data/sig/generated/prism/mutation_compiler.rbs +464 -0
  174. data/sig/generated/prism/node.rbs +20160 -0
  175. data/sig/generated/prism/node_ext.rbs +290 -0
  176. data/sig/generated/prism/node_find.rbs +90 -0
  177. data/sig/generated/prism/parse_result/errors.rbs +22 -0
  178. data/sig/generated/prism/parse_result/newlines.rbs +223 -0
  179. data/sig/generated/prism/parse_result.rbs +859 -0
  180. data/sig/generated/prism/pattern.rbs +156 -0
  181. data/sig/generated/prism/reflection.rbs +101 -0
  182. data/sig/generated/prism/relocation.rbs +428 -0
  183. data/sig/generated/prism/serialize.rbs +195 -0
  184. data/sig/generated/prism/string_query.rbs +36 -0
  185. data/sig/generated/prism/translation.rbs +8 -0
  186. data/sig/generated/prism/visitor.rbs +1111 -0
  187. data/sig/generated/prism.rbs +84 -0
  188. data/sig/manifest.yaml +2 -0
  189. data/src/arena.c +117 -0
  190. data/src/buffer.c +380 -0
  191. data/src/char.c +289 -0
  192. data/src/comments.c +454 -0
  193. data/src/constant_pool.c +406 -0
  194. data/src/diagnostic.c +886 -0
  195. data/src/encoding.c +5345 -0
  196. data/src/errors_format.c +519 -0
  197. data/src/integer.c +681 -0
  198. data/src/json.c +5733 -0
  199. data/src/line_offset_list.c +100 -0
  200. data/src/list.c +24 -0
  201. data/src/memchr.c +37 -0
  202. data/src/node.c +4515 -0
  203. data/src/options.c +451 -0
  204. data/src/parser.c +349 -0
  205. data/src/prettyprint.c +9024 -0
  206. data/src/prism.c +23739 -0
  207. data/src/regexp.c +1706 -0
  208. data/src/serialize.c +2309 -0
  209. data/src/source.c +518 -0
  210. data/src/static_literals.c +685 -0
  211. data/src/string_query.c +166 -0
  212. data/src/stringy.c +91 -0
  213. data/src/strncasecmp.c +37 -0
  214. data/src/strpbrk.c +447 -0
  215. data/src/tokens.c +724 -0
  216. metadata +259 -0
@@ -0,0 +1,314 @@
1
+ # frozen_string_literal: true
2
+ # :markup: markdown
3
+ #--
4
+ # rbs_inline: enabled
5
+
6
+ module Prism
7
+ # A pattern is an object that wraps a Ruby pattern matching expression. The
8
+ # expression would normally be passed to an `in` clause within a `case`
9
+ # expression or a rightward assignment expression. For example, in the
10
+ # following snippet:
11
+ #
12
+ # case node
13
+ # in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]
14
+ # end
15
+ #
16
+ # the pattern is the <tt>ConstantPathNode[...]</tt> expression.
17
+ #
18
+ # The pattern gets compiled into an object that responds to #call by running
19
+ # the #compile method. This method itself will run back through Prism to
20
+ # parse the expression into a tree, then walk the tree to generate the
21
+ # necessary callable objects. For example, if you wanted to compile the
22
+ # expression above into a callable, you would:
23
+ #
24
+ # callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile
25
+ # callable.call(node)
26
+ #
27
+ # The callable object returned by #compile is guaranteed to respond to #call
28
+ # with a single argument, which is the node to match against. It also is
29
+ # guaranteed to respond to #===, which means it itself can be used in a `case`
30
+ # expression, as in:
31
+ #
32
+ # case node
33
+ # when callable
34
+ # end
35
+ #
36
+ # If the query given to the initializer cannot be compiled into a valid
37
+ # matcher (either because of a syntax error or because it is using syntax we
38
+ # do not yet support) then a Prism::Pattern::CompilationError will be
39
+ # raised.
40
+ class Pattern
41
+ # Raised when the query given to a pattern is either invalid Ruby syntax or
42
+ # is using syntax that we don't yet support.
43
+ class CompilationError < StandardError
44
+ # Create a new CompilationError with the given representation of the node
45
+ # that caused the error.
46
+ #
47
+ #: (String repr) -> void
48
+ def initialize(repr) # :nodoc:
49
+ super(<<~ERROR)
50
+ prism was unable to compile the pattern you provided into a usable
51
+ expression. It failed on to understand the node represented by:
52
+
53
+ #{repr}
54
+
55
+ Note that not all syntax supported by Ruby's pattern matching syntax
56
+ is also supported by prism's patterns. If you're using some syntax
57
+ that you believe should be supported, please open an issue on
58
+ GitHub at https://github.com/ruby/prism/issues/new.
59
+ ERROR
60
+ end
61
+ end
62
+
63
+ # The query that this pattern was initialized with.
64
+ attr_reader :query #: String
65
+ # @rbs @compiled: Proc?
66
+
67
+ # Create a new pattern with the given query. The query should be a string
68
+ # containing a Ruby pattern matching expression.
69
+ #
70
+ #: (String query) -> void
71
+ def initialize(query)
72
+ @query = query
73
+ @compiled = nil
74
+ end
75
+
76
+ # Compile the query into a callable object that can be used to match against
77
+ # nodes.
78
+ #
79
+ #: () -> Proc
80
+ def compile
81
+ result = Prism.parse("case nil\nin #{query}\nend")
82
+
83
+ case_match_node = result.value.statements.body.last
84
+ raise CompilationError, case_match_node.inspect unless case_match_node.is_a?(CaseMatchNode)
85
+
86
+ in_node = case_match_node.conditions.last
87
+ raise CompilationError, in_node.inspect unless in_node.is_a?(InNode)
88
+
89
+ compile_node(in_node.pattern)
90
+ end
91
+
92
+ # Scan the given node and all of its children for nodes that match the
93
+ # pattern. If a block is given, it will be called with each node that
94
+ # matches the pattern. If no block is given, an enumerator will be returned
95
+ # that will yield each node that matches the pattern.
96
+ #
97
+ #: (node root) -> Enumerator[node, void]
98
+ #: (node root) { (node) -> void } -> void
99
+ def scan(root, &blk)
100
+ return to_enum(:scan, root) unless block_given?
101
+
102
+ @compiled ||= compile
103
+ queue = [root]
104
+
105
+ while (node = queue.shift)
106
+ yield node if @compiled.call(node) # steep:ignore
107
+ queue.concat(node.compact_child_nodes)
108
+ end
109
+ end
110
+
111
+ private
112
+
113
+ # Shortcut for combining two procs into one that returns true if both return
114
+ # true.
115
+ #
116
+ #: (Proc left, Proc right) -> Proc
117
+ def combine_and(left, right) # :nodoc:
118
+ ->(other) { left.call(other) && right.call(other) }
119
+ end
120
+
121
+ # Shortcut for combining two procs into one that returns true if either
122
+ # returns true.
123
+ #
124
+ #: (Proc left, Proc right) -> Proc
125
+ def combine_or(left, right) # :nodoc:
126
+ ->(other) { left.call(other) || right.call(other) }
127
+ end
128
+
129
+ # Raise an error because the given node is not supported. Note purposefully
130
+ # not typing this method since it is a no return method that Steep does not
131
+ # understand.
132
+ #
133
+ #: (node node) -> bot
134
+ def compile_error(node) # :nodoc:
135
+ raise CompilationError, node.inspect
136
+ end
137
+
138
+ # in [foo, bar, baz]
139
+ #
140
+ #: (ArrayPatternNode node) -> Proc
141
+ def compile_array_pattern_node(node) # :nodoc:
142
+ compile_error(node) if !node.rest.nil? || node.posts.any?
143
+
144
+ constant = node.constant
145
+ compiled_constant = compile_node(constant) if constant
146
+
147
+ preprocessed = node.requireds.map { |required| compile_node(required) }
148
+
149
+ compiled_requireds = ->(other) do
150
+ deconstructed = other.deconstruct
151
+
152
+ deconstructed.length == preprocessed.length &&
153
+ preprocessed
154
+ .zip(deconstructed)
155
+ .all? { |(matcher, value)| matcher.call(value) }
156
+ end
157
+
158
+ if compiled_constant
159
+ combine_and(compiled_constant, compiled_requireds)
160
+ else
161
+ compiled_requireds
162
+ end
163
+ end
164
+
165
+ # in foo | bar
166
+ #
167
+ #: (AlternationPatternNode node) -> Proc
168
+ def compile_alternation_pattern_node(node) # :nodoc:
169
+ combine_or(compile_node(node.left), compile_node(node.right))
170
+ end
171
+
172
+ # in Prism::ConstantReadNode
173
+ #
174
+ #: (ConstantPathNode node) -> Proc
175
+ def compile_constant_path_node(node) # :nodoc:
176
+ parent = node.parent
177
+
178
+ if (parent.is_a?(ConstantReadNode) || parent.is_a?(ConstantPathNode)) && parent.slice == Prism.name
179
+ name = node.name
180
+ raise CompilationError, node.inspect if name.nil?
181
+
182
+ compile_constant_name(node, name)
183
+ else
184
+ compile_error(node)
185
+ end
186
+ end
187
+
188
+ # in ConstantReadNode
189
+ # in String
190
+ #
191
+ #: (ConstantReadNode node) -> Proc
192
+ def compile_constant_read_node(node) # :nodoc:
193
+ compile_constant_name(node, node.name)
194
+ end
195
+
196
+ # Compile a name associated with a constant.
197
+ #
198
+ #: ((ConstantPathNode | ConstantReadNode) node, Symbol name) -> Proc
199
+ def compile_constant_name(node, name) # :nodoc:
200
+ if Prism.const_defined?(name, false)
201
+ clazz = Prism.const_get(name)
202
+
203
+ ->(other) { clazz === other }
204
+ elsif Object.const_defined?(name, false)
205
+ clazz = Object.const_get(name)
206
+
207
+ ->(other) { clazz === other }
208
+ else
209
+ compile_error(node)
210
+ end
211
+ end
212
+
213
+ # in InstanceVariableReadNode[name: Symbol]
214
+ # in { name: Symbol }
215
+ #
216
+ #: (HashPatternNode node) -> Proc
217
+ def compile_hash_pattern_node(node) # :nodoc:
218
+ compile_error(node) if node.rest
219
+
220
+ if (constant = node.constant)
221
+ compiled_constant = compile_node(constant)
222
+ end
223
+
224
+ preprocessed =
225
+ node.elements.to_h do |element|
226
+ key = element.key
227
+ if key.is_a?(SymbolNode)
228
+ [key.unescaped.to_sym, compile_node(element.value)]
229
+ else
230
+ raise CompilationError, element.inspect
231
+ end
232
+ end
233
+
234
+ compiled_keywords = ->(other) do
235
+ deconstructed = other.deconstruct_keys(preprocessed.keys)
236
+
237
+ preprocessed.all? do |keyword, matcher|
238
+ deconstructed.key?(keyword) && matcher.call(deconstructed[keyword])
239
+ end
240
+ end
241
+
242
+ if compiled_constant
243
+ combine_and(compiled_constant, compiled_keywords)
244
+ else
245
+ compiled_keywords
246
+ end
247
+ end
248
+
249
+ # in nil
250
+ #
251
+ #: (NilNode node) -> Proc
252
+ def compile_nil_node(node) # :nodoc:
253
+ ->(attribute) { attribute.nil? }
254
+ end
255
+
256
+ # in /foo/
257
+ #
258
+ #: (RegularExpressionNode node) -> Proc
259
+ def compile_regular_expression_node(node) # :nodoc:
260
+ regexp = Regexp.new(node.unescaped, node.closing[1..])
261
+
262
+ ->(attribute) { regexp === attribute }
263
+ end
264
+
265
+ # in ""
266
+ # in "foo"
267
+ #
268
+ #: (StringNode node) -> Proc
269
+ def compile_string_node(node) # :nodoc:
270
+ string = node.unescaped
271
+
272
+ ->(attribute) { string === attribute }
273
+ end
274
+
275
+ # in :+
276
+ # in :foo
277
+ #
278
+ #: (SymbolNode node) -> Proc
279
+ def compile_symbol_node(node) # :nodoc:
280
+ symbol = node.unescaped.to_sym
281
+
282
+ ->(attribute) { symbol === attribute }
283
+ end
284
+
285
+ # Compile any kind of node. Dispatch out to the individual compilation
286
+ # methods based on the type of node.
287
+ #
288
+ #: (node node) -> Proc
289
+ def compile_node(node) # :nodoc:
290
+ case node
291
+ when AlternationPatternNode
292
+ compile_alternation_pattern_node(node)
293
+ when ArrayPatternNode
294
+ compile_array_pattern_node(node)
295
+ when ConstantPathNode
296
+ compile_constant_path_node(node)
297
+ when ConstantReadNode
298
+ compile_constant_read_node(node)
299
+ when HashPatternNode
300
+ compile_hash_pattern_node(node)
301
+ when NilNode
302
+ compile_nil_node(node)
303
+ when RegularExpressionNode
304
+ compile_regular_expression_node(node)
305
+ when StringNode
306
+ compile_string_node(node)
307
+ when SymbolNode
308
+ compile_symbol_node(node)
309
+ else
310
+ compile_error(node)
311
+ end
312
+ end
313
+ end
314
+ 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
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Polyfill for String#byteindex, which didn't exist until Ruby 3.2.
4
+ if !("".respond_to?(:byteindex))
5
+ String.include(
6
+ Module.new {
7
+ def byteindex(needle, offset = 0)
8
+ charindex = index(needle, offset)
9
+ slice(0...charindex).bytesize if charindex
10
+ end
11
+ }
12
+ )
13
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "strscan"
4
+
5
+ # Polyfill for StringScanner#scan_byte, which didn't exist until Ruby 3.4.
6
+ if !(StringScanner.method_defined?(:scan_byte))
7
+ StringScanner.include(
8
+ Module.new {
9
+ def scan_byte # :nodoc:
10
+ get_byte&.b&.ord
11
+ end
12
+ }
13
+ )
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Polyfill for String#unpack1 with the offset parameter. Not all Ruby engines
4
+ # have Method#parameters implemented, so we check the arity instead if
5
+ # necessary.
6
+ if (unpack1 = String.instance_method(:unpack1)).respond_to?(:parameters) ? unpack1.parameters.none? { |_, name| name == :offset } : (unpack1.arity == 1)
7
+ String.prepend(
8
+ Module.new {
9
+ def unpack1(format, offset: 0) # :nodoc:
10
+ offset == 0 ? super(format) : self[offset..].unpack1(format) # steep:ignore
11
+ end
12
+ }
13
+ )
14
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Polyfill for Kernel#warn with the category parameter. Not all Ruby engines
4
+ # have Method#parameters implemented, so we check the arity instead if
5
+ # necessary.
6
+ if (method = Kernel.instance_method(:warn)).respond_to?(:parameters) ? method.parameters.none? { |_, name| name == :category } : (method.arity == -1)
7
+ Kernel.prepend(
8
+ Module.new {
9
+ def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
10
+ case uplevel
11
+ when nil
12
+ super(*msgs)
13
+ when Integer
14
+ super(*msgs, uplevel: uplevel + 1)
15
+ else
16
+ super(*msgs, uplevel: uplevel.to_int + 1)
17
+ end
18
+ end
19
+ }
20
+ )
21
+
22
+ Object.prepend(
23
+ Module.new {
24
+ def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
25
+ case uplevel
26
+ when nil
27
+ super(*msgs)
28
+ when Integer
29
+ super(*msgs, uplevel: uplevel + 1)
30
+ else
31
+ super(*msgs, uplevel: uplevel.to_int + 1)
32
+ end
33
+ end
34
+ }
35
+ )
36
+ end