summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2025-01-11 21:10:09 -0500
committergit <svn-admin@ruby-lang.org>2025-01-14 15:32:39 +0000
commit713f31872a42b75924d346ce5df3e567db074cc5 (patch)
treea1d9f0b09f8fe71ede69a4828cfc7cbd338a2572 /lib
parent1758137eada3823b4f4df67e330264fa7455c46b (diff)
[ruby/prism] Freeze AST option
To make it so that you can pass `freeze: true` to Prism parse methods and get back a deeply-frozen AST that is Ractor- shareable. https://github.com/ruby/prism/commit/8e6a93b2d2
Diffstat (limited to 'lib')
-rw-r--r--lib/prism.rb6
-rw-r--r--lib/prism/ffi.rb72
2 files changed, 63 insertions, 15 deletions
diff --git a/lib/prism.rb b/lib/prism.rb
index 94f4c8ca5f..8024577fa3 100644
--- a/lib/prism.rb
+++ b/lib/prism.rb
@@ -59,11 +59,11 @@ module Prism
end
# :call-seq:
- # Prism::load(source, serialized) -> ParseResult
+ # Prism::load(source, serialized, freeze) -> ParseResult
#
# Load the serialized AST using the source as a reference into a tree.
- def self.load(source, serialized)
- Serialize.load(source, serialized)
+ def self.load(source, serialized, freeze = false)
+ Serialize.load(source, serialized, freeze)
end
end
diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb
index 9ab1557838..de11953a26 100644
--- a/lib/prism/ffi.rb
+++ b/lib/prism/ffi.rb
@@ -279,7 +279,7 @@ module Prism
# access to the IO object already through the closure of the lambda, we
# can pass a null pointer here and not worry.
LibRubyParser.pm_serialize_parse_stream(buffer.pointer, nil, callback, dump_options(options))
- Prism.load(source, buffer.read)
+ Prism.load(source, buffer.read, options.fetch(:freeze, false))
end
end
@@ -354,22 +354,37 @@ module Prism
def dump_common(string, options) # :nodoc:
LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
- buffer.read
+
+ dumped = buffer.read
+ dumped.freeze if options.fetch(:freeze, false)
+
+ dumped
end
end
def lex_common(string, code, options) # :nodoc:
- serialized = LibRubyParser::PrismBuffer.with do |buffer|
- LibRubyParser.pm_serialize_lex(buffer.pointer, string.pointer, string.length, dump_options(options))
- buffer.read
+ serialized =
+ LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser.pm_serialize_lex(buffer.pointer, string.pointer, string.length, dump_options(options))
+ buffer.read
+ end
+
+ freeze = options.fetch(:freeze, false)
+ source = Source.for(code)
+ result = Serialize.load_tokens(source, serialized, freeze)
+
+ if freeze
+ source.source.freeze
+ source.offsets.freeze
+ source.freeze
end
- Serialize.load_tokens(Source.for(code), serialized)
+ result
end
def parse_common(string, code, options) # :nodoc:
serialized = dump_common(string, options)
- Prism.load(code, serialized)
+ Prism.load(code, serialized, options.fetch(:freeze, false))
end
def parse_comments_common(string, code, options) # :nodoc:
@@ -382,7 +397,14 @@ module Prism
loader.load_header
loader.load_encoding
loader.load_start_line
- loader.load_comments
+
+ if (freeze = options.fetch(:freeze, false))
+ source.source.freeze
+ source.offsets.freeze
+ source.freeze
+ end
+
+ loader.load_comments(freeze)
end
end
@@ -392,12 +414,35 @@ module Prism
source = Source.for(code)
loader = Serialize::Loader.new(source, buffer.read)
+ freeze = options.fetch(:freeze, false)
- tokens = loader.load_tokens
- node, comments, magic_comments, data_loc, errors, warnings = loader.load_nodes
- tokens.each { |token,| token.value.force_encoding(loader.encoding) }
+ tokens = loader.load_tokens(false)
+ node, comments, magic_comments, data_loc, errors, warnings = loader.load_nodes(freeze)
- ParseLexResult.new([node, tokens], comments, magic_comments, data_loc, errors, warnings, source)
+ tokens.each do |token,|
+ token.value.force_encoding(loader.encoding)
+
+ if freeze
+ token.value.freeze
+ token.location.freeze
+ token.freeze
+ end
+ end
+
+ value = [node, tokens]
+ result = ParseLexResult.new(value, comments, magic_comments, data_loc, errors, warnings, source)
+
+ if freeze
+ source.source.freeze
+ source.offsets.freeze
+ source.freeze
+ tokens.each(&:freeze)
+ tokens.freeze
+ value.freeze
+ result.freeze
+ end
+
+ result
end
end
@@ -482,6 +527,9 @@ module Prism
template << "C"
values << (options.fetch(:partial_script, false) ? 1 : 0)
+ template << "C"
+ values << (options.fetch(:freeze, false) ? 1 : 0)
+
template << "L"
if (scopes = options[:scopes])
values << scopes.length