prism 0.29.0 → 1.3.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 +115 -1
- data/CONTRIBUTING.md +0 -4
- data/Makefile +1 -1
- data/README.md +4 -0
- data/config.yml +920 -148
- data/docs/build_system.md +8 -11
- data/docs/fuzzing.md +1 -1
- data/docs/parsing_rules.md +4 -1
- data/docs/relocation.md +34 -0
- data/docs/ripper_translation.md +22 -0
- data/docs/serialization.md +3 -0
- data/ext/prism/api_node.c +2863 -2079
- data/ext/prism/extconf.rb +14 -37
- data/ext/prism/extension.c +241 -391
- data/ext/prism/extension.h +2 -2
- data/include/prism/ast.h +2156 -453
- data/include/prism/defines.h +58 -7
- data/include/prism/diagnostic.h +24 -6
- data/include/prism/node.h +0 -21
- data/include/prism/options.h +94 -3
- data/include/prism/parser.h +82 -40
- data/include/prism/regexp.h +18 -8
- data/include/prism/static_literals.h +3 -2
- data/include/prism/util/pm_char.h +1 -2
- data/include/prism/util/pm_constant_pool.h +0 -8
- data/include/prism/util/pm_integer.h +22 -15
- data/include/prism/util/pm_newline_list.h +11 -0
- data/include/prism/util/pm_string.h +28 -12
- data/include/prism/version.h +3 -3
- data/include/prism.h +47 -11
- data/lib/prism/compiler.rb +3 -0
- data/lib/prism/desugar_compiler.rb +111 -74
- data/lib/prism/dispatcher.rb +16 -1
- data/lib/prism/dot_visitor.rb +55 -34
- data/lib/prism/dsl.rb +660 -468
- data/lib/prism/ffi.rb +113 -8
- data/lib/prism/inspect_visitor.rb +296 -64
- data/lib/prism/lex_compat.rb +1 -1
- data/lib/prism/mutation_compiler.rb +11 -6
- data/lib/prism/node.rb +4262 -5023
- data/lib/prism/node_ext.rb +91 -14
- data/lib/prism/parse_result/comments.rb +0 -7
- data/lib/prism/parse_result/errors.rb +65 -0
- data/lib/prism/parse_result/newlines.rb +101 -11
- data/lib/prism/parse_result.rb +183 -6
- data/lib/prism/reflection.rb +12 -10
- data/lib/prism/relocation.rb +504 -0
- data/lib/prism/serialize.rb +496 -609
- data/lib/prism/string_query.rb +30 -0
- data/lib/prism/translation/parser/compiler.rb +185 -155
- data/lib/prism/translation/parser/lexer.rb +26 -4
- data/lib/prism/translation/parser.rb +9 -4
- data/lib/prism/translation/ripper.rb +23 -25
- data/lib/prism/translation/ruby_parser.rb +86 -17
- data/lib/prism/visitor.rb +3 -0
- data/lib/prism.rb +6 -8
- data/prism.gemspec +9 -5
- data/rbi/prism/dsl.rbi +521 -0
- data/rbi/prism/node.rbi +1115 -1120
- data/rbi/prism/parse_result.rbi +29 -0
- data/rbi/prism/string_query.rbi +12 -0
- data/rbi/prism/visitor.rbi +3 -0
- data/rbi/prism.rbi +36 -30
- data/sig/prism/dsl.rbs +190 -303
- data/sig/prism/mutation_compiler.rbs +1 -0
- data/sig/prism/node.rbs +678 -632
- data/sig/prism/parse_result.rbs +22 -0
- data/sig/prism/relocation.rbs +185 -0
- data/sig/prism/string_query.rbs +11 -0
- data/sig/prism/visitor.rbs +1 -0
- data/sig/prism.rbs +103 -64
- data/src/diagnostic.c +64 -28
- data/src/node.c +502 -1739
- data/src/options.c +76 -27
- data/src/prettyprint.c +188 -112
- data/src/prism.c +3376 -2293
- data/src/regexp.c +208 -71
- data/src/serialize.c +182 -50
- data/src/static_literals.c +64 -85
- data/src/token_type.c +4 -4
- data/src/util/pm_char.c +1 -1
- data/src/util/pm_constant_pool.c +0 -8
- data/src/util/pm_integer.c +53 -25
- data/src/util/pm_newline_list.c +29 -0
- data/src/util/pm_string.c +131 -80
- data/src/util/pm_strpbrk.c +32 -6
- metadata +11 -7
- data/include/prism/util/pm_string_list.h +0 -44
- data/lib/prism/debug.rb +0 -249
- data/lib/prism/translation/parser/rubocop.rb +0 -73
- data/src/util/pm_string_list.c +0 -28
data/lib/prism/ffi.rb
CHANGED
@@ -13,7 +13,15 @@ module Prism
|
|
13
13
|
|
14
14
|
# Define the library that we will be pulling functions from. Note that this
|
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
|
+
libprism_in_libdir = "#{RbConfig::CONFIG["libdir"]}/prism/libprism.#{RbConfig::CONFIG["SOEXT"]}"
|
18
|
+
if File.exist? libprism_in_build
|
19
|
+
INCLUDE_DIR = File.expand_path("../../include", __dir__)
|
20
|
+
ffi_lib libprism_in_build
|
21
|
+
else
|
22
|
+
INCLUDE_DIR = "#{RbConfig::CONFIG["libdir"]}/prism/include"
|
23
|
+
ffi_lib libprism_in_libdir
|
24
|
+
end
|
17
25
|
|
18
26
|
# Convert a native C type declaration into a symbol that FFI understands.
|
19
27
|
# For example:
|
@@ -38,7 +46,7 @@ module Prism
|
|
38
46
|
# given functions. For each one, define a function with the same name and
|
39
47
|
# signature as the C function.
|
40
48
|
def self.load_exported_functions_from(header, *functions, callbacks)
|
41
|
-
File.foreach(
|
49
|
+
File.foreach("#{INCLUDE_DIR}/#{header}") do |line|
|
42
50
|
# We only want to attempt to load exported functions.
|
43
51
|
next unless line.start_with?("PRISM_EXPORTED_FUNCTION ")
|
44
52
|
|
@@ -72,6 +80,8 @@ module Prism
|
|
72
80
|
end
|
73
81
|
|
74
82
|
callback :pm_parse_stream_fgets_t, [:pointer, :int, :pointer], :pointer
|
83
|
+
enum :pm_string_init_result_t, %i[PM_STRING_INIT_SUCCESS PM_STRING_INIT_ERROR_GENERIC PM_STRING_INIT_ERROR_DIRECTORY]
|
84
|
+
enum :pm_string_query_t, [:PM_STRING_QUERY_ERROR, -1, :PM_STRING_QUERY_FALSE, :PM_STRING_QUERY_TRUE]
|
75
85
|
|
76
86
|
load_exported_functions_from(
|
77
87
|
"prism.h",
|
@@ -82,6 +92,9 @@ module Prism
|
|
82
92
|
"pm_serialize_lex",
|
83
93
|
"pm_serialize_parse_lex",
|
84
94
|
"pm_parse_success_p",
|
95
|
+
"pm_string_query_local",
|
96
|
+
"pm_string_query_constant",
|
97
|
+
"pm_string_query_method_name",
|
85
98
|
[:pm_parse_stream_fgets_t]
|
86
99
|
)
|
87
100
|
|
@@ -176,13 +189,26 @@ module Prism
|
|
176
189
|
def self.with_file(filepath)
|
177
190
|
raise TypeError unless filepath.is_a?(String)
|
178
191
|
|
192
|
+
# On Windows and Mac, it's expected that filepaths will be encoded in
|
193
|
+
# UTF-8. If they are not, we need to convert them to UTF-8 before
|
194
|
+
# passing them into pm_string_mapped_init.
|
195
|
+
if RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince|darwin/i) &&
|
196
|
+
(encoding = filepath.encoding) != Encoding::ASCII_8BIT && encoding != Encoding::UTF_8
|
197
|
+
filepath = filepath.encode(Encoding::UTF_8)
|
198
|
+
end
|
199
|
+
|
179
200
|
FFI::MemoryPointer.new(SIZEOF) do |pm_string|
|
180
|
-
|
201
|
+
case (result = LibRubyParser.pm_string_mapped_init(pm_string, filepath))
|
202
|
+
when :PM_STRING_INIT_SUCCESS
|
181
203
|
pointer = LibRubyParser.pm_string_source(pm_string)
|
182
204
|
length = LibRubyParser.pm_string_length(pm_string)
|
183
205
|
return yield new(pointer, length, false)
|
184
|
-
|
206
|
+
when :PM_STRING_INIT_ERROR_GENERIC
|
185
207
|
raise SystemCallError.new(filepath, FFI.errno)
|
208
|
+
when :PM_STRING_INIT_ERROR_DIRECTORY
|
209
|
+
raise Errno::EISDIR.new(filepath)
|
210
|
+
else
|
211
|
+
raise "Unknown error initializing pm_string_t: #{result.inspect}"
|
186
212
|
end
|
187
213
|
ensure
|
188
214
|
LibRubyParser.pm_string_free(pm_string)
|
@@ -200,8 +226,8 @@ module Prism
|
|
200
226
|
|
201
227
|
class << self
|
202
228
|
# Mirror the Prism.dump API by using the serialization API.
|
203
|
-
def dump(
|
204
|
-
LibRubyParser::PrismString.with_string(
|
229
|
+
def dump(source, **options)
|
230
|
+
LibRubyParser::PrismString.with_string(source) { |string| dump_common(string, options) }
|
205
231
|
end
|
206
232
|
|
207
233
|
# Mirror the Prism.dump_file API by using the serialization API.
|
@@ -302,6 +328,27 @@ module Prism
|
|
302
328
|
!parse_file_success?(filepath, **options)
|
303
329
|
end
|
304
330
|
|
331
|
+
# Mirror the Prism.profile API by using the serialization API.
|
332
|
+
def profile(source, **options)
|
333
|
+
LibRubyParser::PrismString.with_string(source) do |string|
|
334
|
+
LibRubyParser::PrismBuffer.with do |buffer|
|
335
|
+
LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
|
336
|
+
nil
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
# Mirror the Prism.profile_file API by using the serialization API.
|
342
|
+
def profile_file(filepath, **options)
|
343
|
+
LibRubyParser::PrismString.with_file(filepath) do |string|
|
344
|
+
LibRubyParser::PrismBuffer.with do |buffer|
|
345
|
+
options[:filepath] = filepath
|
346
|
+
LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
|
347
|
+
nil
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
305
352
|
private
|
306
353
|
|
307
354
|
def dump_common(string, options) # :nodoc:
|
@@ -376,6 +423,20 @@ module Prism
|
|
376
423
|
end
|
377
424
|
end
|
378
425
|
|
426
|
+
# Return the value that should be dumped for the version option.
|
427
|
+
def dump_options_version(version)
|
428
|
+
case version
|
429
|
+
when nil, "latest"
|
430
|
+
0
|
431
|
+
when /\A3\.3(\.\d+)?\z/
|
432
|
+
1
|
433
|
+
when /\A3\.4(\.\d+)?\z/
|
434
|
+
0
|
435
|
+
else
|
436
|
+
raise ArgumentError, "invalid version: #{version}"
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
379
440
|
# Convert the given options into a serialized options string.
|
380
441
|
def dump_options(options)
|
381
442
|
template = +""
|
@@ -394,7 +455,7 @@ module Prism
|
|
394
455
|
|
395
456
|
template << "L"
|
396
457
|
if (encoding = options[:encoding])
|
397
|
-
name = encoding.name
|
458
|
+
name = encoding.is_a?(Encoding) ? encoding.name : encoding
|
398
459
|
values.push(name.bytesize, name.b)
|
399
460
|
template << "A*"
|
400
461
|
else
|
@@ -408,7 +469,16 @@ module Prism
|
|
408
469
|
values << dump_options_command_line(options)
|
409
470
|
|
410
471
|
template << "C"
|
411
|
-
values <<
|
472
|
+
values << dump_options_version(options[:version])
|
473
|
+
|
474
|
+
template << "C"
|
475
|
+
values << (options[:encoding] == false ? 1 : 0)
|
476
|
+
|
477
|
+
template << "C"
|
478
|
+
values << (options.fetch(:main_script, false) ? 1 : 0)
|
479
|
+
|
480
|
+
template << "C"
|
481
|
+
values << (options.fetch(:partial_script, false) ? 1 : 0)
|
412
482
|
|
413
483
|
template << "L"
|
414
484
|
if (scopes = options[:scopes])
|
@@ -434,4 +504,39 @@ module Prism
|
|
434
504
|
values.pack(template)
|
435
505
|
end
|
436
506
|
end
|
507
|
+
|
508
|
+
# Here we are going to patch StringQuery to put in the class-level methods so
|
509
|
+
# that it can maintain a consistent interface
|
510
|
+
class StringQuery
|
511
|
+
class << self
|
512
|
+
# Mirrors the C extension's StringQuery::local? method.
|
513
|
+
def local?(string)
|
514
|
+
query(LibRubyParser.pm_string_query_local(string, string.bytesize, string.encoding.name))
|
515
|
+
end
|
516
|
+
|
517
|
+
# Mirrors the C extension's StringQuery::constant? method.
|
518
|
+
def constant?(string)
|
519
|
+
query(LibRubyParser.pm_string_query_constant(string, string.bytesize, string.encoding.name))
|
520
|
+
end
|
521
|
+
|
522
|
+
# Mirrors the C extension's StringQuery::method_name? method.
|
523
|
+
def method_name?(string)
|
524
|
+
query(LibRubyParser.pm_string_query_method_name(string, string.bytesize, string.encoding.name))
|
525
|
+
end
|
526
|
+
|
527
|
+
private
|
528
|
+
|
529
|
+
# Parse the enum result and return an appropriate boolean.
|
530
|
+
def query(result)
|
531
|
+
case result
|
532
|
+
when :PM_STRING_QUERY_ERROR
|
533
|
+
raise ArgumentError, "Invalid or non ascii-compatible encoding"
|
534
|
+
when :PM_STRING_QUERY_FALSE
|
535
|
+
false
|
536
|
+
when :PM_STRING_QUERY_TRUE
|
537
|
+
true
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
437
542
|
end
|