lib/prism/ffi.rb in prism-0.16.0 vs lib/prism/ffi.rb in prism-0.17.0
- old
+ new
@@ -7,11 +7,11 @@
require "ffi"
module Prism
BACKEND = :FFI
- module LibRubyParser
+ module LibRubyParser # :nodoc:
extend FFI::Library
# Define the library that we will be pulling functions from. Note that this
# must align with the build shared library from make/rake.
ffi_lib File.expand_path("../../build/librubyparser.#{RbConfig::CONFIG["SOEXT"]}", __dir__)
@@ -67,14 +67,14 @@
end
load_exported_functions_from(
"prism.h",
"pm_version",
- "pm_parse_serialize",
- "pm_parse_serialize_comments",
- "pm_lex_serialize",
- "pm_parse_lex_serialize"
+ "pm_serialize_parse",
+ "pm_serialize_parse_comments",
+ "pm_serialize_lex",
+ "pm_serialize_parse_lex"
)
load_exported_functions_from(
"prism/util/pm_buffer.h",
"pm_buffer_sizeof",
@@ -93,11 +93,11 @@
"pm_string_sizeof"
)
# This object represents a pm_buffer_t. We only use it as an opaque pointer,
# so it doesn't need to know the fields of pm_buffer_t.
- class PrismBuffer
+ class PrismBuffer # :nodoc:
SIZEOF = LibRubyParser.pm_buffer_sizeof
attr_reader :pointer
def initialize(pointer)
@@ -131,11 +131,11 @@
end
end
# This object represents a pm_string_t. We only use it as an opaque pointer,
# so it doesn't have to be an FFI::Struct.
- class PrismString
+ class PrismString # :nodoc:
SIZEOF = LibRubyParser.pm_string_sizeof
attr_reader :pointer
def initialize(pointer)
@@ -165,112 +165,164 @@
LibRubyParser.pm_string_free(pointer)
pointer.free
end
end
end
-
- def self.dump_internal(source, source_size, filepath)
- PrismBuffer.with do |buffer|
- metadata = [filepath.bytesize, filepath.b, 0].pack("LA*L") if filepath
- pm_parse_serialize(source, source_size, buffer.pointer, metadata)
- buffer.read
- end
- end
end
# Mark the LibRubyParser module as private as it should only be called through
# the prism module.
private_constant :LibRubyParser
# The version constant is set by reading the result of calling pm_version.
VERSION = LibRubyParser.pm_version.read_string
- # Mirror the Prism.dump API by using the serialization API.
- def self.dump(code, filepath = nil)
- LibRubyParser.dump_internal(code, code.bytesize, filepath)
- end
+ class << self
+ # Mirror the Prism.dump API by using the serialization API.
+ def dump(code, **options)
+ LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser.pm_serialize_parse(buffer.pointer, code, code.bytesize, dump_options(options))
+ buffer.read
+ end
+ end
- # Mirror the Prism.dump_file API by using the serialization API.
- def self.dump_file(filepath)
- LibRubyParser::PrismString.with(filepath) do |string|
- LibRubyParser.dump_internal(string.source, string.length, filepath)
+ # Mirror the Prism.dump_file API by using the serialization API.
+ def dump_file(filepath, **options)
+ LibRubyParser::PrismString.with(filepath) do |string|
+ dump(string.read, **options, filepath: filepath)
+ end
end
- end
- # Mirror the Prism.lex API by using the serialization API.
- def self.lex(code, filepath = nil)
- LibRubyParser::PrismBuffer.with do |buffer|
- LibRubyParser.pm_lex_serialize(code, code.bytesize, filepath, buffer.pointer)
- Serialize.load_tokens(Source.new(code), buffer.read)
+ # Mirror the Prism.lex API by using the serialization API.
+ def lex(code, **options)
+ LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser.pm_serialize_lex(buffer.pointer, code, code.bytesize, dump_options(options))
+ Serialize.load_tokens(Source.new(code), buffer.read)
+ end
end
- end
- # Mirror the Prism.lex_file API by using the serialization API.
- def self.lex_file(filepath)
- LibRubyParser::PrismString.with(filepath) do |string|
- lex(string.read, filepath)
+ # Mirror the Prism.lex_file API by using the serialization API.
+ def lex_file(filepath, **options)
+ LibRubyParser::PrismString.with(filepath) do |string|
+ lex(string.read, **options, filepath: filepath)
+ end
end
- end
- # Mirror the Prism.parse API by using the serialization API.
- def self.parse(code, filepath = nil)
- Prism.load(code, dump(code, filepath))
- end
+ # Mirror the Prism.parse API by using the serialization API.
+ def parse(code, **options)
+ Prism.load(code, dump(code, **options))
+ end
- # Mirror the Prism.parse_file API by using the serialization API. This uses
- # native strings instead of Ruby strings because it allows us to use mmap when
- # it is available.
- def self.parse_file(filepath)
- LibRubyParser::PrismString.with(filepath) do |string|
- parse(string.read, filepath)
+ # Mirror the Prism.parse_file API by using the serialization API. This uses
+ # native strings instead of Ruby strings because it allows us to use mmap when
+ # it is available.
+ def parse_file(filepath, **options)
+ LibRubyParser::PrismString.with(filepath) do |string|
+ parse(string.read, **options, filepath: filepath)
+ end
end
- end
- # Mirror the Prism.parse_comments API by using the serialization API.
- def self.parse_comments(code, filepath = nil)
- LibRubyParser::PrismBuffer.with do |buffer|
- metadata = [filepath.bytesize, filepath.b, 0].pack("LA*L") if filepath
- LibRubyParser.pm_parse_serialize_comments(code, code.bytesize, buffer.pointer, metadata)
+ # Mirror the Prism.parse_comments API by using the serialization API.
+ def parse_comments(code, **options)
+ LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser.pm_serialize_parse_comments(buffer.pointer, code, code.bytesize, dump_options(options))
- source = Source.new(code)
- loader = Serialize::Loader.new(source, buffer.read)
+ source = Source.new(code)
+ loader = Serialize::Loader.new(source, buffer.read)
- loader.load_header
- loader.load_force_encoding
- loader.load_comments
+ loader.load_header
+ loader.load_force_encoding
+ loader.load_start_line
+ loader.load_comments
+ end
end
- end
- # Mirror the Prism.parse_file_comments API by using the serialization
- # API. This uses native strings instead of Ruby strings because it allows us
- # to use mmap when it is available.
- def self.parse_file_comments(filepath)
- LibRubyParser::PrismString.with(filepath) do |string|
- parse_comments(string.read, filepath)
+ # Mirror the Prism.parse_file_comments API by using the serialization
+ # API. This uses native strings instead of Ruby strings because it allows us
+ # to use mmap when it is available.
+ def parse_file_comments(filepath, **options)
+ LibRubyParser::PrismString.with(filepath) do |string|
+ parse_comments(string.read, **options, filepath: filepath)
+ end
end
- end
- # Mirror the Prism.parse_lex API by using the serialization API.
- def self.parse_lex(code, filepath = nil)
- LibRubyParser::PrismBuffer.with do |buffer|
- metadata = [filepath.bytesize, filepath.b, 0].pack("LA*L") if filepath
- LibRubyParser.pm_parse_lex_serialize(code, code.bytesize, buffer.pointer, metadata)
+ # Mirror the Prism.parse_lex API by using the serialization API.
+ def parse_lex(code, **options)
+ LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser.pm_serialize_parse_lex(buffer.pointer, code, code.bytesize, dump_options(options))
- source = Source.new(code)
- loader = Serialize::Loader.new(source, buffer.read)
+ source = Source.new(code)
+ loader = Serialize::Loader.new(source, buffer.read)
- tokens = loader.load_tokens
- node, comments, magic_comments, errors, warnings = loader.load_nodes
+ tokens = loader.load_tokens
+ node, comments, magic_comments, errors, warnings = loader.load_nodes
+ tokens.each { |token,| token.value.force_encoding(loader.encoding) }
- tokens.each { |token,| token.value.force_encoding(loader.encoding) }
+ ParseResult.new([node, tokens], comments, magic_comments, errors, warnings, source)
+ end
+ end
- ParseResult.new([node, tokens], comments, magic_comments, errors, warnings, source)
+ # Mirror the Prism.parse_lex_file API by using the serialization API.
+ def parse_lex_file(filepath, **options)
+ LibRubyParser::PrismString.with(filepath) do |string|
+ parse_lex(string.read, **options, filepath: filepath)
+ end
end
- end
- # Mirror the Prism.parse_lex_file API by using the serialization API.
- def self.parse_lex_file(filepath)
- LibRubyParser::PrismString.with(filepath) do |string|
- parse_lex(string.read, filepath)
+ private
+
+ # Convert the given options into a serialized options string.
+ def dump_options(options)
+ template = +""
+ values = []
+
+ template << "L"
+ if (filepath = options[:filepath])
+ values.push(filepath.bytesize, filepath.b)
+ template << "A*"
+ else
+ values << 0
+ end
+
+ template << "L"
+ values << options.fetch(:line, 1)
+
+ template << "L"
+ if (encoding = options[:encoding])
+ name = encoding.name
+ values.push(name.bytesize, name.b)
+ template << "A*"
+ else
+ values << 0
+ end
+
+ template << "C"
+ values << (options.fetch(:frozen_string_literal, false) ? 1 : 0)
+
+ template << "C"
+ values << (options[:verbose] ? 0 : 1)
+
+ template << "L"
+ if (scopes = options[:scopes])
+ values << scopes.length
+
+ scopes.each do |scope|
+ template << "L"
+ values << scope.length
+
+ scope.each do |local|
+ name = local.name
+ template << "L"
+ values << name.bytesize
+
+ template << "A*"
+ values << name.b
+ end
+ end
+ else
+ values << 0
+ end
+
+ values.pack(template)
end
end
end